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 <FpConfig.hpp>
16#include <Fw/Types/Assert.hpp>
17#include <Fw/Buffer/Buffer.hpp>
18#include <new>
19
20namespace Svc {
21
22 // ----------------------------------------------------------------------
23 // Construction, initialization, and destruction
24 // ----------------------------------------------------------------------
25
26 BufferManagerComponentImpl ::
27 BufferManagerComponentImpl(
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
45 void BufferManagerComponentImpl ::
46 init(
47 const NATIVE_INT_TYPE instance
48 )
49 {
51 }
52
53 BufferManagerComponentImpl ::
54 ~BufferManagerComponentImpl()
55 {
56 if (m_setup) {
57 this->cleanup();
58 }
59 }
60
61 void BufferManagerComponentImpl ::
62 cleanup()
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
#define FW_ASSERT(...)
Definition Assert.hpp:7
PlatformPointerCastType POINTER_CAST
Definition BasicTypes.h:53
PlatformIntType NATIVE_INT_TYPE
Definition BasicTypes.h:51
uint8_t U8
8-bit unsigned integer
Definition BasicTypes.h:26
PlatformUIntType NATIVE_UINT_TYPE
Definition BasicTypes.h:52
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 * allocate(const NATIVE_UINT_TYPE identifier, NATIVE_UINT_TYPE &size, bool &recoverable)=0
Allocate memory.
void init()
Object initializer.
Definition ObjBase.cpp:27
Auto-generated base for BufferManager component.
void setup(NATIVE_UINT_TYPE mgrID, NATIVE_UINT_TYPE memID, Fw::MemAllocator &allocator, const BufferBins &bins)
set up configuration
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