F´ Flight Software - C/C++ Documentation  devel
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 <FpConfig.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  {
48  if (m_setup) {
49  this->cleanup();
50  }
51  }
52 
54  cleanup()
55  {
56  FW_ASSERT(this->m_buffers);
57  FW_ASSERT(this->m_allocator);
58 
59  if (not this->m_cleaned) {
60  // walk through Fw::Buffer instances and delete them
61  for (NATIVE_UINT_TYPE entry = 0; entry < this->m_numStructs; entry++) {
62  this->m_buffers[entry].buff.~Buffer();
63  }
64  this->m_cleaned = true;
65  // release memory
66  this->m_allocator->deallocate(this->m_memId,this->m_buffers);
67  this->m_setup = false;
68  }
69  }
70 
71 
72  // ----------------------------------------------------------------------
73  // Handler implementations for user-defined typed input ports
74  // ----------------------------------------------------------------------
75 
76  void BufferManagerComponentImpl ::
77  bufferSendIn_handler(
78  const NATIVE_INT_TYPE portNum,
79  Fw::Buffer &fwBuffer
80  )
81  {
82  // make sure component has been set up
83  FW_ASSERT(this->m_setup);
84  FW_ASSERT(m_buffers);
85  // check for empty buffers - this is just a warning since this component returns
86  // empty buffers if it can't allocate one.
87  if (fwBuffer.getSize() == 0) {
89  this->m_emptyBuffs++;
90  return;
91  }
92  // use the bufferID member field to find the original slot
93  U32 context = fwBuffer.getContext();
94  U32 id = context & 0xFFFF;
95  U32 mgrId = context >> 16;
96  // check some things
97  FW_ASSERT(
98  id < this->m_numStructs,
99  static_cast<FwAssertArgType>(id),
100  static_cast<FwAssertArgType>(this->m_numStructs));
101  FW_ASSERT(
102  mgrId == this->m_mgrId,
103  static_cast<FwAssertArgType>(mgrId),
104  static_cast<FwAssertArgType>(id),
105  static_cast<FwAssertArgType>(this->m_mgrId));
106  FW_ASSERT(
107  true == this->m_buffers[id].allocated,
108  static_cast<FwAssertArgType>(id),
109  static_cast<FwAssertArgType>(this->m_mgrId));
110  FW_ASSERT(
111  reinterpret_cast<U8*>(fwBuffer.getData()) >= this->m_buffers[id].memory,
112  static_cast<FwAssertArgType>(id),
113  static_cast<FwAssertArgType>(this->m_mgrId));
114  FW_ASSERT(
115  reinterpret_cast<U8*>(fwBuffer.getData()) < (this->m_buffers[id].memory + this->m_buffers[id].size),
116  static_cast<FwAssertArgType>(id),
117  static_cast<FwAssertArgType>(this->m_mgrId));
118  // user can make smaller for their own purposes, but it shouldn't be bigger
119  FW_ASSERT(
120  fwBuffer.getSize() <= this->m_buffers[id].size,
121  static_cast<FwAssertArgType>(id),
122  static_cast<FwAssertArgType>(this->m_mgrId));
123  // clear the allocated flag
124  this->m_buffers[id].allocated = false;
125  this->m_currBuffs--;
126  }
127 
128  Fw::Buffer BufferManagerComponentImpl ::
129  bufferGetCallee_handler(
130  const NATIVE_INT_TYPE portNum,
131  U32 size
132  )
133  {
134  // make sure component has been set up
135  FW_ASSERT(this->m_setup);
136  FW_ASSERT(m_buffers);
137  // find smallest buffer based on size.
138  for (NATIVE_UINT_TYPE buff = 0; buff < this->m_numStructs; buff++) {
139  if ((not this->m_buffers[buff].allocated) and (size <= this->m_buffers[buff].size)) {
140  this->m_buffers[buff].allocated = true;
141  this->m_currBuffs++;
142  if (this->m_currBuffs > this->m_highWater) {
143  this->m_highWater = this->m_currBuffs;
144  }
145  Fw::Buffer copy = this->m_buffers[buff].buff;
146  // change size to match request
147  copy.setSize(size);
148  return copy;
149  }
150  }
151 
152  // if no buffers found, return empty buffer
154  this->m_noBuffs++;
155  return Fw::Buffer();
156 
157  }
158 
160  NATIVE_UINT_TYPE mgrId,
161  NATIVE_UINT_TYPE memId,
162  Fw::MemAllocator& allocator,
163  const BufferBins& bins
164  ) {
165 
166  this->m_mgrId = mgrId;
167  this->m_memId = memId;
168  this->m_allocator = &allocator;
169  // clear bins
170  memset(&this->m_bufferBins,0,sizeof(this->m_bufferBins));
171 
172  this->m_bufferBins = bins;
173 
174  // compute the amount of memory needed
175  NATIVE_UINT_TYPE memorySize = 0; // track needed memory
176  this->m_numStructs = 0; // size the number of tracking structs
177  // walk through bins and add up the sizes
178  for (NATIVE_UINT_TYPE bin = 0; bin < BUFFERMGR_MAX_NUM_BINS; bin++) {
179  if (this->m_bufferBins.bins[bin].numBuffers) {
180  memorySize +=
181  (this->m_bufferBins.bins[bin].bufferSize * this->m_bufferBins.bins[bin].numBuffers) + // allocate each set of buffer memory
182  (static_cast<NATIVE_UINT_TYPE>(sizeof(AllocatedBuffer)) * this->m_bufferBins.bins[bin].numBuffers); // allocate the structs to track the buffers
183  this->m_numStructs += this->m_bufferBins.bins[bin].numBuffers;
184  }
185  }
186 
187  NATIVE_UINT_TYPE allocatedSize = memorySize;
188  bool recoverable = false;
189 
190  // allocate memory
191  void *memory = allocator.allocate(memId,allocatedSize,recoverable);
192  // make sure the memory returns was non-zero and the size requested
193  FW_ASSERT(memory);
194  FW_ASSERT(
195  memorySize == allocatedSize,
196  static_cast<FwAssertArgType>(memorySize),
197  static_cast<FwAssertArgType>(allocatedSize));
198  // structs will be at beginning of memory
199  this->m_buffers = static_cast<AllocatedBuffer*>(memory);
200  // memory buffers will be at end of structs in memory, so compute that memory as the beginning of the
201  // struct past the number of structs
202  U8* bufferMem = reinterpret_cast<U8*>(&this->m_buffers[this->m_numStructs]);
203 
204  // walk through entries and initialize them
205  NATIVE_UINT_TYPE currStruct = 0;
206  for (NATIVE_UINT_TYPE bin = 0; bin < BUFFERMGR_MAX_NUM_BINS; bin++) {
207  if (this->m_bufferBins.bins[bin].numBuffers) {
208  for (NATIVE_UINT_TYPE binEntry = 0; binEntry < this->m_bufferBins.bins[bin].numBuffers; binEntry++) {
209  // placement new for Fw::Buffer instance. We don't need the new() return value,
210  // because we know where the Fw::Buffer instance is
211  U32 context = (this->m_mgrId << 16) | currStruct;
212  (void) new(&this->m_buffers[currStruct].buff) Fw::Buffer(bufferMem,this->m_bufferBins.bins[bin].bufferSize,context);
213  this->m_buffers[currStruct].allocated = false;
214  this->m_buffers[currStruct].memory = bufferMem;
215  this->m_buffers[currStruct].size = this->m_bufferBins.bins[bin].bufferSize;
216  bufferMem += this->m_bufferBins.bins[bin].bufferSize;
217  currStruct++;
218  }
219  }
220  }
221 
222  // check that the initiation pointer made it to the end of allocated space
223  U8* const CURR_PTR = bufferMem;
224  U8* const END_PTR = static_cast<U8*>(memory) + memorySize;
225  FW_ASSERT(CURR_PTR == END_PTR,
226  static_cast<FwAssertArgType>(reinterpret_cast<POINTER_CAST>(CURR_PTR)),
227  static_cast<FwAssertArgType>(reinterpret_cast<POINTER_CAST>(END_PTR)));
228  // secondary init verification
229  FW_ASSERT(
230  currStruct == this->m_numStructs,
231  static_cast<FwAssertArgType>(currStruct),
232  static_cast<FwAssertArgType>(this->m_numStructs));
233  // indicate setup is done
234  this->m_setup = true;
235  }
236 
237  void BufferManagerComponentImpl ::
238  schedIn_handler(
239  const NATIVE_INT_TYPE portNum,
240  U32 context
241  )
242  {
243  // write telemetry values
244  this->tlmWrite_HiBuffs(this->m_highWater);
245  this->tlmWrite_CurrBuffs(this->m_currBuffs);
246  this->tlmWrite_TotalBuffs(this->m_numStructs);
247  this->tlmWrite_NoBuffs(this->m_noBuffs);
248  this->tlmWrite_EmptyBuffs(this->m_emptyBuffs);
249  }
250 
251 } // end namespace Svc
#define FW_ASSERT(...)
Definition: Assert.hpp:14
PlatformPointerCastType POINTER_CAST
Definition: BasicTypes.h:57
PlatformIntType NATIVE_INT_TYPE
Definition: BasicTypes.h:55
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:30
PlatformUIntType NATIVE_UINT_TYPE
Definition: BasicTypes.h:56
PlatformAssertArgType FwAssertArgType
Definition: FpConfig.h:39
C++-compatible configuration header for fprime configuration.
U8 * getData() const
Definition: Buffer.cpp:68
U32 getSize() const
Definition: Buffer.cpp:72
void setSize(U32 size)
Definition: Buffer.cpp:87
U32 getContext() const
Definition: Buffer.cpp:76
virtual void deallocate(const NATIVE_UINT_TYPE identifier, void *ptr)=0
Deallocate memory.
virtual void * allocate(const NATIVE_UINT_TYPE identifier, NATIVE_UINT_TYPE &size, bool &recoverable)=0
Allocate memory.
Auto-generated base for BufferManager component.
void tlmWrite_HiBuffs(U32 arg, Fw::Time _tlmTime=Fw::Time())
void tlmWrite_EmptyBuffs(U32 arg, Fw::Time _tlmTime=Fw::Time())
void tlmWrite_NoBuffs(U32 arg, Fw::Time _tlmTime=Fw::Time())
void tlmWrite_TotalBuffs(U32 arg, Fw::Time _tlmTime=Fw::Time())
void tlmWrite_CurrBuffs(U32 arg, Fw::Time _tlmTime=Fw::Time())
void setup(NATIVE_UINT_TYPE mgrID, NATIVE_UINT_TYPE memID, Fw::MemAllocator &allocator, const BufferBins &bins)
set up configuration
BufferManagerComponentImpl(const char *const compName)
static const NATIVE_UINT_TYPE BUFFERMGR_MAX_NUM_BINS
NATIVE_UINT_TYPE numBuffers
number of buffers in this bin. Set to zero for unused bins.
NATIVE_UINT_TYPE bufferSize
size of the buffers in this bin. Set to zero for unused bins.
BufferBin bins[BUFFERMGR_MAX_NUM_BINS]
set of bins to define buffers