F´ Flight Software - C/C++ Documentation  NASA-v1.6.0
A framework for building embedded system applications to NASA flight quality standards.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
BufferManagerComponentImpl.cpp
Go to the documentation of this file.
1 // ======================================================================
2 // \title BufferManagerComponentImpl.cpp
3 // \author tcanham
4 // \brief cpp file for BufferManager component implementation class
5 //
6 // \copyright
7 // Copyright 2009-2015, by the California Institute of Technology.
8 // ALL RIGHTS RESERVED. United States Government Sponsorship
9 // acknowledged.
10 //
11 // ======================================================================
12 
13 
15 #include <Fw/Types/BasicTypes.hpp>
16 #include <Fw/Types/Assert.hpp>
17 #include <Fw/Buffer/Buffer.hpp>
18 #include <new>
19 
20 namespace Svc {
21 
22  // ----------------------------------------------------------------------
23  // Construction, initialization, and destruction
24  // ----------------------------------------------------------------------
25 
28  const char *const compName
29  ) : BufferManagerComponentBase(compName)
30  ,m_setup(false)
31  ,m_cleaned(false)
32  ,m_mgrId(0)
33  ,m_buffers(nullptr)
34  ,m_allocator(nullptr)
35  ,m_memId(0)
36  ,m_numStructs(0)
37  ,m_highWater(0)
38  ,m_currBuffs(0)
39  ,m_noBuffs(0)
40  ,m_emptyBuffs(0)
41  {
42 
43  }
44 
47  const NATIVE_INT_TYPE instance
48  )
49  {
50  BufferManagerComponentBase::init(instance);
51  }
52 
55  {
56  if (m_setup) {
57  this->cleanup();
58  }
59  }
60 
63  {
64  FW_ASSERT(this->m_buffers);
65  FW_ASSERT(this->m_allocator);
66 
67  if (not this->m_cleaned) {
68  // walk through Fw::Buffer instances and delete them
69  for (NATIVE_UINT_TYPE entry = 0; entry < this->m_numStructs; entry++) {
70  this->m_buffers[entry].buff.~Buffer();
71  }
72  this->m_cleaned = true;
73  // release memory
74  this->m_allocator->deallocate(this->m_memId,this->m_buffers);
75  this->m_setup = false;
76  }
77  }
78 
79 
80  // ----------------------------------------------------------------------
81  // Handler implementations for user-defined typed input ports
82  // ----------------------------------------------------------------------
83 
84  void BufferManagerComponentImpl ::
85  bufferSendIn_handler(
86  const NATIVE_INT_TYPE portNum,
87  Fw::Buffer &fwBuffer
88  )
89  {
90  // make sure component has been set up
91  FW_ASSERT(this->m_setup);
92  FW_ASSERT(m_buffers);
93  // check for empty buffers - this is just a warning since this component returns
94  // empty buffers if it can't allocate one.
95  if (fwBuffer.getSize() == 0) {
96  this->log_WARNING_HI_ZeroSizeBuffer();
97  this->m_emptyBuffs++;
98  return;
99  }
100  // use the bufferID member field to find the original slot
101  U32 context = fwBuffer.getContext();
102  U32 id = context & 0xFFFF;
103  U32 mgrId = context >> 16;
104  // check some things
105  FW_ASSERT(id < this->m_numStructs,id,this->m_numStructs);
106  FW_ASSERT(mgrId == this->m_mgrId,mgrId,id,this->m_mgrId);
107  FW_ASSERT(true == this->m_buffers[id].allocated,id,this->m_mgrId);
108  FW_ASSERT(reinterpret_cast<U8*>(fwBuffer.getData()) >= this->m_buffers[id].memory,id,this->m_mgrId);
109  FW_ASSERT(reinterpret_cast<U8*>(fwBuffer.getData()) < (this->m_buffers[id].memory + this->m_buffers[id].size),id,this->m_mgrId);
110  // user can make smaller for their own purposes, but it shouldn't be bigger
111  FW_ASSERT(fwBuffer.getSize() <= this->m_buffers[id].size,id,this->m_mgrId);
112  // clear the allocated flag
113  this->m_buffers[id].allocated = false;
114  this->m_currBuffs--;
115  }
116 
117  Fw::Buffer BufferManagerComponentImpl ::
118  bufferGetCallee_handler(
119  const NATIVE_INT_TYPE portNum,
120  U32 size
121  )
122  {
123  // make sure component has been set up
124  FW_ASSERT(this->m_setup);
125  FW_ASSERT(m_buffers);
126  // find smallest buffer based on size.
127  for (NATIVE_UINT_TYPE buff = 0; buff < this->m_numStructs; buff++) {
128  if ((not this->m_buffers[buff].allocated) and (size <= this->m_buffers[buff].size)) {
129  this->m_buffers[buff].allocated = true;
130  this->m_currBuffs++;
131  if (this->m_currBuffs > this->m_highWater) {
132  this->m_highWater = this->m_currBuffs;
133  }
134  Fw::Buffer copy = this->m_buffers[buff].buff;
135  // change size to match request
136  copy.setSize(size);
137  return copy;
138  }
139  }
140 
141  // if no buffers found, return empty buffer
142  this->log_WARNING_HI_NoBuffsAvailable(size);
143  this->m_noBuffs++;
144  return Fw::Buffer();
145 
146  }
147 
149  NATIVE_UINT_TYPE mgrId,
150  NATIVE_UINT_TYPE memId,
151  Fw::MemAllocator& allocator,
152  const BufferBins& bins
153  ) {
154 
155  this->m_mgrId = mgrId;
156  this->m_memId = memId;
157  this->m_allocator = &allocator;
158  // clear bins
159  memset(&this->m_bufferBins,0,sizeof(this->m_bufferBins));
160 
161  this->m_bufferBins = bins;
162 
163  // compute the amount of memory needed
164  NATIVE_UINT_TYPE memorySize = 0; // track needed memory
165  this->m_numStructs = 0; // size the number of tracking structs
166  // walk through bins and add up the sizes
167  for (NATIVE_UINT_TYPE bin = 0; bin < BUFFERMGR_MAX_NUM_BINS; bin++) {
168  if (this->m_bufferBins.bins[bin].numBuffers) {
169  memorySize +=
170  (this->m_bufferBins.bins[bin].bufferSize * this->m_bufferBins.bins[bin].numBuffers) + // allocate each set of buffer memory
171  (static_cast<NATIVE_UINT_TYPE>(sizeof(AllocatedBuffer)) * this->m_bufferBins.bins[bin].numBuffers); // allocate the structs to track the buffers
172  this->m_numStructs += this->m_bufferBins.bins[bin].numBuffers;
173  }
174  }
175 
176  NATIVE_UINT_TYPE allocatedSize = memorySize;
177  bool recoverable = false;
178 
179  // allocate memory
180  void *memory = allocator.allocate(memId,allocatedSize,recoverable);
181  // make sure the memory returns was non-zero and the size requested
182  FW_ASSERT(memory);
183  FW_ASSERT(memorySize == allocatedSize,memorySize,allocatedSize);
184  // structs will be at beginning of memory
185  this->m_buffers = static_cast<AllocatedBuffer*>(memory);
186  // memory buffers will be at end of structs in memory, so compute that memory as the beginning of the
187  // struct past the number of structs
188  U8* bufferMem = reinterpret_cast<U8*>(&this->m_buffers[this->m_numStructs]);
189 
190  // walk through entries and initialize them
191  NATIVE_UINT_TYPE currStruct = 0;
192  for (NATIVE_UINT_TYPE bin = 0; bin < BUFFERMGR_MAX_NUM_BINS; bin++) {
193  if (this->m_bufferBins.bins[bin].numBuffers) {
194  for (NATIVE_UINT_TYPE binEntry = 0; binEntry < this->m_bufferBins.bins[bin].numBuffers; binEntry++) {
195  // placement new for Fw::Buffer instance. We don't need the new() return value,
196  // because we know where the Fw::Buffer instance is
197  U32 context = (this->m_mgrId << 16) | currStruct;
198  (void) new(&this->m_buffers[currStruct].buff) Fw::Buffer(bufferMem,this->m_bufferBins.bins[bin].bufferSize,context);
199  this->m_buffers[currStruct].allocated = false;
200  this->m_buffers[currStruct].memory = bufferMem;
201  this->m_buffers[currStruct].size = this->m_bufferBins.bins[bin].bufferSize;
202  bufferMem += this->m_bufferBins.bins[bin].bufferSize;
203  currStruct++;
204  }
205  }
206  }
207 
208  // check that the initiation pointer made it to the end of allocated space
209  U8* const CURR_PTR = bufferMem;
210  U8* const END_PTR = static_cast<U8*>(memory) + memorySize;
211  FW_ASSERT(CURR_PTR == END_PTR,
212  reinterpret_cast<POINTER_CAST>(CURR_PTR), reinterpret_cast<POINTER_CAST>(END_PTR));
213  // secondary init verification
214  FW_ASSERT(currStruct == this->m_numStructs,currStruct,this->m_numStructs);
215  // indicate setup is done
216  this->m_setup = true;
217  }
218 
219  void BufferManagerComponentImpl ::
220  schedIn_handler(
221  const NATIVE_INT_TYPE portNum,
222  NATIVE_UINT_TYPE context
223  )
224  {
225  // write telemetry values
226  this->tlmWrite_HiBuffs(this->m_highWater);
227  this->tlmWrite_CurrBuffs(this->m_currBuffs);
228  this->tlmWrite_TotalBuffs(this->m_numStructs);
229  this->tlmWrite_NoBuffs(this->m_noBuffs);
230  this->tlmWrite_EmptyBuffs(this->m_emptyBuffs);
231  }
232 
233 } // end namespace Svc
Svc::BufferManagerComponentImpl::~BufferManagerComponentImpl
~BufferManagerComponentImpl()
Definition: BufferManagerComponentImpl.cpp:54
Svc::BufferManagerComponentImpl::setup
void setup(NATIVE_UINT_TYPE mgrID, NATIVE_UINT_TYPE memID, Fw::MemAllocator &allocator, const BufferBins &bins)
set up configuration
Definition: BufferManagerComponentImpl.cpp:148
Fw::Buffer::getData
U8 * getData() const
Definition: Buffer.cpp:60
Fw::MemAllocator::deallocate
virtual void deallocate(const NATIVE_UINT_TYPE identifier, void *ptr)=0
Deallocate memory.
U8
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.hpp:73
NATIVE_UINT_TYPE
unsigned int NATIVE_UINT_TYPE
native unsigned integer type declaration
Definition: BasicTypes.hpp:28
Svc::BufferManagerComponentImpl::BufferManagerComponentImpl
BufferManagerComponentImpl(const char *const compName)
Definition: BufferManagerComponentImpl.cpp:27
Buffer.hpp
Svc::BufferManagerComponentImpl::BufferBin::numBuffers
NATIVE_UINT_TYPE numBuffers
number of buffers in this bin. Set to zero for unused bins.
Definition: BufferManagerComponentImpl.hpp:81
Fw::Buffer::getContext
U32 getContext() const
Definition: Buffer.cpp:68
Svc::BufferManagerComponentImpl::cleanup
void cleanup()
Definition: BufferManagerComponentImpl.cpp:62
Fw::MemAllocator::allocate
virtual void * allocate(const NATIVE_UINT_TYPE identifier, NATIVE_UINT_TYPE &size, bool &recoverable)=0
Allocate memory.
Fw::Buffer
Definition: Buffer.hpp:43
Svc::BUFFERMGR_MAX_NUM_BINS
static const NATIVE_UINT_TYPE BUFFERMGR_MAX_NUM_BINS
Definition: BufferManagerComponentImplCfg.hpp:7
NATIVE_INT_TYPE
int NATIVE_INT_TYPE
native integer type declaration
Definition: BasicTypes.hpp:27
Svc::BufferManagerComponentImpl::BufferBins
Definition: BufferManagerComponentImpl.hpp:85
BufferManagerComponentImpl.hpp
Fw::Buffer::getSize
U32 getSize() const
Definition: Buffer.cpp:64
Svc::BufferManagerComponentImpl::BufferBins::bins
BufferBin bins[BUFFERMGR_MAX_NUM_BINS]
set of bins to define buffers
Definition: BufferManagerComponentImpl.hpp:87
Fw::Buffer::setSize
void setSize(U32 size)
Definition: Buffer.cpp:79
Svc::BufferManagerComponentImpl::BufferBin::bufferSize
NATIVE_UINT_TYPE bufferSize
size of the buffers in this bin. Set to zero for unused bins.
Definition: BufferManagerComponentImpl.hpp:80
Svc::BufferManagerComponentImpl::init
void init(const NATIVE_INT_TYPE instance=0)
Definition: BufferManagerComponentImpl.cpp:46
Fw::MemAllocator
Definition: MemAllocator.hpp:44
FW_ASSERT
#define FW_ASSERT(...)
Definition: Assert.hpp:9
Svc
Definition: ActiveRateGroupCfg.hpp:18