F´ Flight Software - C/C++ Documentation  NASA-v1.5.0
A framework for building embedded system applications to NASA flight quality standards.
BufferManager.cpp
Go to the documentation of this file.
1 // ======================================================================
2 // \title BufferManager.hpp
3 // \author bocchino
4 // \brief BufferManager component interface
5 //
6 // \copyright
7 // Copyright (C) 2015-2017, by the California Institute of Technology.
8 // ALL RIGHTS RESERVED. United States Government Sponsorship
9 // acknowledged.
10 //
11 // ======================================================================
12 
13 #include "Fw/Types/Assert.hpp"
14 #include "Fw/Types/BasicTypes.hpp"
16 
17 namespace Svc {
18 
19  // ----------------------------------------------------------------------
20  // Warnings::State
21  // ----------------------------------------------------------------------
22 
23  BufferManager::Warnings::State ::
24  State(void) :
25  storeSizeExceeded(false),
26  tooManyBuffers(false)
27  {
28 
29  }
30 
31  // ----------------------------------------------------------------------
32  // Warnings
33  // ----------------------------------------------------------------------
34 
35  BufferManager::Warnings ::
36  Warnings(BufferManager& bufferManager) :
37  bufferManager(bufferManager)
38  {
39 
40  }
41 
42  void BufferManager::Warnings ::
43  update(const Status::t status)
44  {
45  switch (status) {
46  case Status::SUCCESS:
47  if (this->state.storeSizeExceeded || this->state.tooManyBuffers) {
48  this->bufferManager.log_ACTIVITY_HI_ClearedErrorState();
49  }
50  this->state.storeSizeExceeded = false;
51  this->state.tooManyBuffers = false;
52  break;
53  case Status::STORE_SIZE_EXCEEDED:
54  if (!this->state.storeSizeExceeded) {
55  this->bufferManager.log_WARNING_HI_StoreSizeExceeded();
56  this->state.storeSizeExceeded = true;
57  }
58  break;
59  case Status::TOO_MANY_BUFFERS:
60  if (!this->state.tooManyBuffers) {
61  this->bufferManager.log_WARNING_HI_TooManyBuffers();
62  this->state.tooManyBuffers = true;
63  }
64  break;
65  default:
66  FW_ASSERT(0);
67  break;
68  }
69  }
70 
71  // ----------------------------------------------------------------------
72  // The store
73  // ----------------------------------------------------------------------
74 
75  BufferManager::Store ::
76  Store(const U32 size) :
77  totalSize(size),
78  memoryBase(new U8[size]),
79  freeIndex(0),
80  padSize(0),
81  allocatedSize(0)
82  {
83 
84  }
85 
86  BufferManager::Store ::
87  ~Store(void)
88  {
89  delete[] this->memoryBase;
90  }
91 
92  U32 BufferManager::Store ::
93  getAllocatedSize(void) const
94  {
95  return this->freeIndex;
96  }
97 
98  BufferManager::Store::Status BufferManager::Store ::
99  allocate(
100  const U32 s,
101  U8* &result
102  )
103  {
104  Status status = SUCCESS;
105  U32 newPadSize = 0;
106  FW_ASSERT(this->allocatedSize <= this->totalSize);
107  FW_ASSERT(this->freeIndex <= this->totalSize);
108  if (this->freeIndex + s > this->totalSize) {
109  // Pad size for wraparound allocation
110  newPadSize = this->totalSize - this->freeIndex;
111  }
112  if (this->allocatedSize + s + newPadSize > this->totalSize) {
113  // Allocation too large
114  status = FAILURE;
115  result = 0;
116  }
117  else {
118  if (this->freeIndex + s > this->totalSize) {
119  // Wraparound allocation
120  FW_ASSERT(this->padSize == 0, this->padSize);
121  this->padSize = newPadSize;
122  this->allocatedSize += newPadSize;
123  this->freeIndex = 0;
124  }
125  result = &this->memoryBase[this->freeIndex];
126  this->allocatedSize += s;
127  this->freeIndex += s;
128  FW_ASSERT(this->allocatedSize <= this->totalSize);
129  FW_ASSERT(this->freeIndex <= this->totalSize);
130  }
131  return status;
132  }
133 
134  void BufferManager::Store ::
135  free(
136  const U32 size,
137  U8 *const address
138  )
139  {
140  FW_ASSERT(this->allocatedSize >= size, this->allocatedSize, size);
141  this->allocatedSize -= size;
142  if (address == this->memoryBase) {
143  // Wraparound allocation
144  FW_ASSERT(this->allocatedSize >= padSize, this->allocatedSize, padSize);
145  this->allocatedSize -= this->padSize;
146  this->padSize = 0;
147  }
148  }
149 
150  // ----------------------------------------------------------------------
151  // The allocation queue
152  // ----------------------------------------------------------------------
153 
154  BufferManager::AllocationQueue ::
155  AllocationQueue(const U32 size) :
156  totalSize(size),
157  data(new Entry[size]),
158  nextId(0),
159  allocateIndex(0),
160  freeIndex(0),
161  allocationSize(0)
162  {
163 
164  }
165 
166  BufferManager::AllocationQueue ::
167  ~AllocationQueue(void)
168  {
169  delete[] this->data;
170  }
171 
172  U32 BufferManager::AllocationQueue ::
173  getNextId(void)
174  {
175  const U32 id = this->nextId;
176  ++this->nextId;
177  FW_ASSERT(this->nextId != 0);
178  return id;
179  }
180 
181  U32 BufferManager::AllocationQueue ::
182  getNextIndex(const U32 index)
183  {
184  FW_ASSERT(index < this->totalSize);
185  const U32 result = index + 1;
186  return result == this->totalSize ? 0 : result;
187  }
188 
189  U32 BufferManager::AllocationQueue ::
190  getAllocationSize(void) const
191  {
192  return this->allocationSize;
193  }
194 
196  BufferManager::AllocationQueue ::
197  allocate(
198  const U32 size,
199  U32& id
200  )
201  {
202  FW_ASSERT(this->allocationSize <= this->totalSize);
203  if (this->allocationSize == this->totalSize) {
204  id = 0;
205  return Allocate::FULL;
206  }
207  FW_ASSERT(this->allocateIndex < this->totalSize);
208  Entry& e = this->data[allocateIndex];
209  id = this->getNextId();
210  e.id = id;
211  e.size = size;
212  this->allocateIndex = this->getNextIndex(this->allocateIndex);
213  ++this->allocationSize;
214  return Allocate::SUCCESS;
215  }
216 
218  BufferManager::AllocationQueue ::
219  free(
220  const U32 expectedId,
221  U32& sawId,
222  U32& size
223  )
224  {
225  sawId = 0;
226  size = 0;
227  if (this->allocationSize == 0) {
228  FW_ASSERT(this->freeIndex == this->allocateIndex);
229  return Free::EMPTY;
230  }
231  FW_ASSERT(this->freeIndex < this->totalSize);
232  Entry& e = this->data[this->freeIndex];
233  sawId = e.id;
234  size = e.size;
235  if (expectedId != sawId) {
236  return Free::ID_MISMATCH;
237  }
238  this->freeIndex = this->getNextIndex(this->freeIndex);
239  --this->allocationSize;
240  return Free::SUCCESS;
241  }
242 
243  // ----------------------------------------------------------------------
244  // Construction, initialization, and destruction
245  // ----------------------------------------------------------------------
246 
249  const char *const compName,
250  const U32 storeSize,
251  const U32 maxNumBuffers
252  ) :
253  BufferManagerComponentBase(compName),
254  warnings(*this),
255  store(storeSize),
256  allocationQueue(maxNumBuffers)
257  {
258 
259  }
260 
262  init(const NATIVE_INT_TYPE instance)
263  {
265  }
266 
268  ~BufferManager(void)
269  {
270 
271  }
272 
273  // ----------------------------------------------------------------------
274  // Handler implementations for user-defined typed input ports
275  // ----------------------------------------------------------------------
276 
279  NATIVE_INT_TYPE portNum,
280  U32 size
281  )
282  {
283  U8 *address;
284  U32 id;
285  Fw::Buffer buffer;
286  buffer.set(this->getInstance(), 0, 0, size);
287 
288  Warnings::Status::t warningStatus = Warnings::Status::SUCCESS;
289 
290  {
291  const Store::Status status =
292  this->store.allocate(size, address);
293  if (status == BufferManager::Store::FAILURE) {
294  warningStatus = Warnings::Status::STORE_SIZE_EXCEEDED;
295  }
296  }
297 
298  if (warningStatus == Warnings::Status::SUCCESS) {
299  const AllocationQueue::Allocate::Status status =
300  this->allocationQueue.allocate(size, id);
301  if (status == AllocationQueue::Allocate::FULL) {
302  this->store.free(size, address);
303  warningStatus = Warnings::Status::TOO_MANY_BUFFERS;
304  }
305  }
306 
307  if (warningStatus == Warnings::Status::SUCCESS) {
308  buffer.setbufferID(id);
309  buffer.setdata(reinterpret_cast<U64>(address));
310  }
311 
312  this->warnings.update(warningStatus);
313  return buffer;
314  }
315 
318  const NATIVE_INT_TYPE portNum,
319  Fw::Buffer &buffer
320  )
321  {
322 
323  const U32 instance = static_cast<U32>(this->getInstance());
324  FW_ASSERT(buffer.getmanagerID() == instance);
325 
326  const U32 expectedId = buffer.getbufferID();
327  U8 *const address = reinterpret_cast<U8*>(buffer.getdata());
328  U32 sawId = 0;
329  U32 size = 0;
330 
331  {
332  const AllocationQueue::Free::Status status =
333  this->allocationQueue.free(expectedId, sawId, size);
334  FW_ASSERT(
335  status == AllocationQueue::Free::SUCCESS,
336  status, expectedId, sawId, size
337  );
338  }
339 
340  {
341  this->store.free(size, address);
342  }
343 
344  }
345 
346 }
Svc::BufferManager::BufferManager
BufferManager(const char *const compName, const U32 storeSize, const U32 maxNumBuffers)
Definition: BufferManager.cpp:248
Svc::BufferManagerComponentBase::bufferGetCallee_handler
virtual Fw::Buffer bufferGetCallee_handler(NATIVE_INT_TYPE portNum, U32 size)=0
Handler for input port bufferGetCallee.
Os::FileSystem::Status
Status
Definition: FileSystem.hpp:15
Fw::Buffer::setdata
void setdata(U64 val)
set member data
Definition: BufferSerializableAc.cpp:71
Fw::PassiveComponentBase::getInstance
NATIVE_INT_TYPE getInstance(void) const
Definition: PassiveComponentBase.cpp:29
U8
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.hpp:76
Svc::BufferManagerComponentBase
Auto-generated base for BufferManager component.
Definition: BufferManagerComponentAc.hpp:44
Svc::BufferManager::bufferSendIn_handler
void bufferSendIn_handler(const NATIVE_INT_TYPE portNum, Fw::Buffer &buffer)
Definition: BufferManager.cpp:317
Fw::Buffer
Definition: BufferSerializableAc.hpp:24
Fw::Buffer::set
void set(U32 managerID, U32 bufferID, U64 data, U32 size)
set values
Definition: BufferSerializableAc.cpp:42
Assert.hpp
U64
#define U64(C)
Definition: sha.h:176
Fw::Buffer::getdata
U64 getdata(void)
get member data
Definition: BufferSerializableAc.cpp:57
Svc::BufferManager::store
Store store
The store.
Definition: BufferManager.hpp:339
Svc::BufferManager::~BufferManager
~BufferManager(void)
Definition: BufferManager.cpp:268
Fw::ObjBase::init
void init(void)
Object initializer.
Definition: ObjBase.cpp:26
FW_ASSERT
#define FW_ASSERT(...)
Definition: Assert.hpp:9
BufferManager.hpp
Fw::Buffer::setbufferID
void setbufferID(U32 val)
set member bufferID
Definition: BufferSerializableAc.cpp:68
Svc::BufferManager::allocationQueue
AllocationQueue allocationQueue
The allocation queue.
Definition: BufferManager.hpp:342
Svc::BufferManager::size
PRIVATE U32 size
Definition: BufferManager.hpp:320
Svc
Definition: ActiveLoggerComponentAc.cpp:22
Fw::Buffer::getmanagerID
U32 getmanagerID(void)
get member managerID
Definition: BufferSerializableAc.cpp:49
BasicTypes.hpp
Declares ISF basic types.
NATIVE_INT_TYPE
int NATIVE_INT_TYPE
native integer type declaration
Definition: BasicTypes.hpp:29
Fw::Buffer::getbufferID
U32 getbufferID(void)
get member bufferID
Definition: BufferSerializableAc.cpp:53