All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
freeindexstorage.h
Go to the documentation of this file.
1 /*
2  * freeindexstorage.h
3  *
4  * Created on: Jan 3, 2012
5  * Author: root
6  *
7  * Date : 06-11-2013 : Init contained a bug: the pushing of all indexes could loop infinite...
8  * Date : 28-01-2014 : Added function GetEntryPointer
9  * Fixed a bug,introduced by fix 06-11-2013, that m_ui32EndIndex was not always accounted
10  * for..
11  * Removed CVMX_SHARED variables because statics do not support multiple instances of this class
12  * Added an InUse array to deteremine if locations are free or not
13  * Date : 05-02-2014 : Fixed a bug, fifo was not closed
14  * Date : 25-10-2015 : In ReturnIndex, lock was not released when exiting when illegal index was tested or position of index was empty.
15  */
16 #ifndef FREEINDEXSTORAGE_H_
17 #define FREEINDEXSTORAGE_H_
18  // Needed by doxygen
20 
21 extern "C"
22 {
23 #include "cvmx.h"
24 #include "cvmx-spinlock.h"
25 #include "cvmx-coremask.h"
26 #include "cvmx-sysinfo.h"
27 #include "cvmx-rwlock.h"
28 #include "cvmx-bootmem.h"
29 }
30 #include <common.h>
31 
32 template <typename T>
33 class CFreeIndexStorage : public CMpFifo<uint16_t>
34 {
35 public:
36  CFreeIndexStorage(); // constructor
37  void Init(uint32_t ui32StartIndex, uint32_t ui32EndIndex, char *pcMemName, bool bCheckForInUse = true, bool bRandomFill = false);
38  bool SetEntry(uint16_t ui16Index, T &tItem);
39  bool FillEntry(uint16_t ui16Index, T &tItem);
40  bool RemoveEntry(uint16_t ui16Index);
41  bool ClearEntry(uint16_t ui16Index);
42  bool SearchEntry(T tItem, uint16_t &ui16Index);
43  bool SearchAndRemoveEntry(T tItem);
44  bool GetFreeIndex(uint16_t &ui16Index);
45  bool GetFreeIndexAndSet(uint16_t &ui16Index, T &tItem);
46  bool ReturnIndex(uint16_t ui16Index);
47  T GetEntry(uint16_t ui16Index);
48  T* GetEntryPointer(uint16_t ui16Index);
49  void Reset();
50  void Close();
52 
53 protected:
54  struct TGlobalVar
55  {
57  cvmx_rwlock_wp_lock_t tRW_Lock;
58  };
59 
60 
68  TGlobalVar *m_pGlobalVarStorage;
69  char m_cMemName[80];
70  char m_cFifoMemName[80];
71 };
72 
74 {
75  m_ptItemsStorage = NULL;
76 }
77 
78 template <class T> void CFreeIndexStorage<T>::Init(uint32_t ui32StartIndex, uint32_t ui32EndIndex, char *pcMemName, bool bCheckForInUse, bool bRandomFill)
79 {
80  m_cCoreMask.Set();
81  strcpy(m_cMemName, pcMemName);
82  strcpy(m_cFifoMemName, m_cMemName);
83  strcat(m_cFifoMemName,"_Fifo");
84 
85  m_ui32MaxNrOfEntries = ui32EndIndex - ui32StartIndex + 1;
86 
87  CMpFifo<uint16_t>::Init(m_ui32MaxNrOfEntries, m_cFifoMemName);
88 
89  m_ui32StartIndex = ui32StartIndex;
90  m_ui32EndIndex = ui32EndIndex;
91  m_bCheckForInUse = bCheckForInUse;
92 
93  // Calculate size of array allocated in bootmem via bootmem_alloc_named. Size of all but last structs should be multiple of cache line size
94  uint32_t ui32SizeOfItemStorage = m_ui32MaxNrOfEntries * sizeof (T);
95  ui32SizeOfItemStorage = (1 + (ui32SizeOfItemStorage-1) / CVMX_CACHE_LINE_SIZE) * CVMX_CACHE_LINE_SIZE;
96  uint32_t ui32SizeOfInUseStorage = m_ui32MaxNrOfEntries * sizeof (bool);
97  ui32SizeOfInUseStorage = (1 + (ui32SizeOfInUseStorage-1) / CVMX_CACHE_LINE_SIZE) * CVMX_CACHE_LINE_SIZE;
98  uint32_t ui32SizeOfGlobalVar = sizeof (TGlobalVar);
99 
100  char *pcBootMem = (char *)cvmx_bootmem_alloc_named(ui32SizeOfItemStorage + ui32SizeOfInUseStorage + ui32SizeOfGlobalVar, 128, m_cMemName);
101  if (pcBootMem == NULL)
102  {
103  if (cvmx_bootmem_find_named_block(m_cMemName))
104  {
105  pcBootMem = (char *)cvmx_phys_to_ptr(cvmx_bootmem_find_named_block(m_cMemName)->base_addr);
106  }
107  else
108  {
109  printf ("Could not attach to m_cMemName \n");
110  return;
111  }
112  }
113 
114  m_ptItemsStorage = (T *)pcBootMem;
115  m_pInUseStorage = (bool *)(pcBootMem + ui32SizeOfItemStorage);
116  m_pGlobalVarStorage = (TGlobalVar *)(pcBootMem + ui32SizeOfItemStorage + ui32SizeOfInUseStorage);
117 
118  if (m_cCoreMask.IsFirstCore())
119  {
120  memset(pcBootMem, 0, ui32SizeOfItemStorage + ui32SizeOfInUseStorage + ui32SizeOfGlobalVar);
121 
122  // Enter valid numbers in queue
123  uint16_t ui16Tmp;
124  for (uint32_t i = ui32StartIndex; i <= ui32EndIndex; i++)
125  {
126  ui16Tmp = (uint16_t)i;
127  Push(ui16Tmp);
128  }
129  if (bRandomFill)
130  {
131  Shuffle();
132  }
133  m_pGlobalVarStorage->ui32NrOfEntries = m_ui32MaxNrOfEntries;
134  cvmx_rwlock_wp_init(&m_pGlobalVarStorage->tRW_Lock);
135  }
136  CVMX_SYNCWS;
137  m_cCoreMask.BarrierSync();
138 }
139 
140 template <class T> bool CFreeIndexStorage<T>::GetFreeIndex(uint16_t &ui16Index)
141 {
142  cvmx_rwlock_wp_write_lock(&m_pGlobalVarStorage->tRW_Lock);
143  bool bReturnValue = Pop(&ui16Index);
144  if (bReturnValue)
145  {
146  m_pGlobalVarStorage->ui32NrOfEntries--;
147  m_pInUseStorage[ui16Index - m_ui32StartIndex] = true;
148  }
149  cvmx_rwlock_wp_write_unlock(&m_pGlobalVarStorage->tRW_Lock);
150  return bReturnValue;
151 }
152 
153 template <class T> bool CFreeIndexStorage<T>::GetFreeIndexAndSet(uint16_t &ui16Index, T &tItem)
154 {
155  cvmx_rwlock_wp_write_lock(&m_pGlobalVarStorage->tRW_Lock);
156  bool bReturnValue = Pop(&ui16Index);
157  if (bReturnValue)
158  {
159  m_pGlobalVarStorage->ui32NrOfEntries--;
160  m_pInUseStorage[ui16Index - m_ui32StartIndex] = true;
161  m_ptItemsStorage[ui16Index - m_ui32StartIndex] = tItem;
162  }
163  cvmx_rwlock_wp_write_unlock(&m_pGlobalVarStorage->tRW_Lock);
164  return bReturnValue;
165 }
166 
167 template <class T> bool CFreeIndexStorage<T>::ReturnIndex(uint16_t ui16Index)
168 {
169  if (ui16Index < m_ui32StartIndex || ui16Index > m_ui32EndIndex)
170  {
171  return false;
172  }
173  cvmx_rwlock_wp_write_lock(&m_pGlobalVarStorage->tRW_Lock);
174  if (m_bCheckForInUse && m_pInUseStorage[ui16Index - m_ui32StartIndex] == false)
175  {
176  cvmx_rwlock_wp_write_unlock(&m_pGlobalVarStorage->tRW_Lock);
177  return false; // Item is already empty
178  }
179  bool bReturnValue = Push(ui16Index);
180  if (bReturnValue)
181  {
182  m_pGlobalVarStorage->ui32NrOfEntries++;
183  m_pInUseStorage[ui16Index - m_ui32StartIndex] = false;
184  }
185  cvmx_rwlock_wp_write_unlock(&m_pGlobalVarStorage->tRW_Lock);
186  return bReturnValue;
187 }
188 
189 template <class T> bool CFreeIndexStorage<T>::SetEntry(uint16_t ui16Index, T &tItem)
190 {
191  if (ui16Index < m_ui32StartIndex || ui16Index > m_ui32EndIndex)
192  {
193  return false;
194  }
195  cvmx_rwlock_wp_write_lock(&m_pGlobalVarStorage->tRW_Lock);
196  if (m_bCheckForInUse && m_pInUseStorage[ui16Index - m_ui32StartIndex] == true)
197  {
198  cvmx_rwlock_wp_write_unlock(&m_pGlobalVarStorage->tRW_Lock);
199  return false;
200  }
201 
202  m_ptItemsStorage[ui16Index - m_ui32StartIndex] = tItem;
203  m_pInUseStorage[ui16Index - m_ui32StartIndex] = true;
204  cvmx_rwlock_wp_write_unlock(&m_pGlobalVarStorage->tRW_Lock);
205  return true;
206 }
207 
208 
209 template <class T> bool CFreeIndexStorage<T>::ClearEntry(uint16_t ui16Index)
210 {
211  if (ui16Index < m_ui32StartIndex || ui16Index > m_ui32EndIndex)
212  {
213  return false;
214  }
215  cvmx_rwlock_wp_write_lock(&m_pGlobalVarStorage->tRW_Lock);
216  if (m_bCheckForInUse && m_pInUseStorage[ui16Index - m_ui32StartIndex] == false)
217  {
218  cvmx_rwlock_wp_write_unlock(&m_pGlobalVarStorage->tRW_Lock);
219  return false; // Item is already empty
220  }
221 
222  memset(&m_ptItemsStorage[ui16Index - m_ui32StartIndex], 0, sizeof (T));
223  m_pInUseStorage[ui16Index - m_ui32StartIndex] = false;
224  cvmx_rwlock_wp_write_unlock(&m_pGlobalVarStorage->tRW_Lock);
225  return true;
226 }
227 
228 template <class T> bool CFreeIndexStorage<T>::RemoveEntry(uint16_t ui16Index)
229 {
230  if (ui16Index < m_ui32StartIndex || ui16Index > m_ui32EndIndex)
231  {
232  return false;
233  }
234  cvmx_rwlock_wp_write_lock(&m_pGlobalVarStorage->tRW_Lock);
235  if (m_bCheckForInUse && m_pInUseStorage[ui16Index - m_ui32StartIndex] == false)
236  {
237  cvmx_rwlock_wp_write_unlock(&m_pGlobalVarStorage->tRW_Lock);
238  return false; // Item is already empty
239  }
240  memset(&m_ptItemsStorage[ui16Index - m_ui32StartIndex], 0, sizeof (T));
241  if (!Push(ui16Index))
242  {
243  cvmx_rwlock_wp_write_unlock(&m_pGlobalVarStorage->tRW_Lock);
244  return false;
245  }
246 
247  m_pGlobalVarStorage->ui32NrOfEntries++;
248  m_pInUseStorage[ui16Index - m_ui32StartIndex] = false;
249  cvmx_rwlock_wp_write_unlock(&m_pGlobalVarStorage->tRW_Lock);
250 
251  return true;
252 }
253 
254 template <class T> bool CFreeIndexStorage<T>::SearchEntry(T tItem, uint16_t &ui16Index)
255 {
256  bool bReturnValue = false;
257  cvmx_rwlock_wp_read_lock(&m_pGlobalVarStorage->tRW_Lock);
258  uint32_t i;
259  T tT;
260  for (i = 0; i < m_ui32MaxNrOfEntries; i++)
261  {
262  tT = m_ptItemsStorage[i];
263  if (tT == tItem)
264  break;
265  }
266  if (i < m_ui32MaxNrOfEntries)
267  {
268  ui16Index = i + m_ui32StartIndex;
269  bReturnValue = true;
270  }
271  else
272  {
273  ui16Index = 0;
274  }
275  cvmx_rwlock_wp_read_unlock(&m_pGlobalVarStorage->tRW_Lock);
276  return bReturnValue;
277 }
278 
279 template <class T> bool CFreeIndexStorage<T>::SearchAndRemoveEntry(T tItem)
280 {
281  bool bReturnValue = false;
282  cvmx_rwlock_wp_write_lock(&m_pGlobalVarStorage->tRW_Lock);
283  uint16_t i;
284  T tT;
285  for (i = 0; i < m_ui32MaxNrOfEntries; i++)
286  {
287  tT = m_ptItemsStorage[i];
288  if (tT == tItem)
289  break;
290  }
291  if (i < m_ui32MaxNrOfEntries)
292  {
293  memset(&m_ptItemsStorage[i], 0, sizeof (T));
294  if (Push(i))
295  {
296  m_pGlobalVarStorage->ui32NrOfEntries++;
297  }
298  bReturnValue = true;
299  }
300  cvmx_rwlock_wp_write_unlock(&m_pGlobalVarStorage->tRW_Lock);
301  return bReturnValue;
302 }
303 
304 template <class T> T CFreeIndexStorage<T>::GetEntry(uint16_t ui16Index)
305 {
306  T tItem;
307  memset(&tItem, 0, sizeof(T));
308 
309  if (ui16Index < m_ui32StartIndex || ui16Index > m_ui32EndIndex)
310  {
311  return tItem;
312  }
313  cvmx_rwlock_wp_read_lock(&m_pGlobalVarStorage->tRW_Lock);
314  if (m_bCheckForInUse && m_pInUseStorage[ui16Index - m_ui32StartIndex] == false)
315  {
316  cvmx_rwlock_wp_read_unlock(&m_pGlobalVarStorage->tRW_Lock);
317  return tItem;
318  }
319  if (m_ptItemsStorage != NULL)
320  {
321  tItem = m_ptItemsStorage[ui16Index - m_ui32StartIndex];
322  }
323  cvmx_rwlock_wp_read_unlock(&m_pGlobalVarStorage->tRW_Lock);
324  return tItem;
325 }
326 
327 template <class T> T* CFreeIndexStorage<T>::GetEntryPointer(uint16_t ui16Index)
328 {
329  if (ui16Index < m_ui32StartIndex || ui16Index > m_ui32EndIndex)
330  {
331  return 0;
332  }
333  cvmx_rwlock_wp_read_lock(&m_pGlobalVarStorage->tRW_Lock);
334  if (m_bCheckForInUse && m_pInUseStorage[ui16Index - m_ui32StartIndex] == false)
335  {
336  cvmx_rwlock_wp_read_unlock(&m_pGlobalVarStorage->tRW_Lock);
337  return 0;
338  }
339 
340  T* ptItem = NULL;
341  if (m_ptItemsStorage != NULL)
342  {
343  ptItem = &m_ptItemsStorage[ui16Index - m_ui32StartIndex];
344  }
345  cvmx_rwlock_wp_read_unlock(&m_pGlobalVarStorage->tRW_Lock);
346  return ptItem;
347 }
348 
350 {
351  cvmx_rwlock_wp_read_lock(&m_pGlobalVarStorage->tRW_Lock);
352  uint32_t ui32NrOfEntries = m_pGlobalVarStorage->ui32NrOfEntries;
353  cvmx_rwlock_wp_read_unlock(&m_pGlobalVarStorage->tRW_Lock);
354  return ui32NrOfEntries;
355 }
356 
357 // Empty queue and fill it again
358 template <class T> void CFreeIndexStorage<T>::Reset()
359 {
360  cvmx_rwlock_wp_write_lock(&m_pGlobalVarStorage->tRW_Lock);
361  uint16_t ui16Index;
362  while (Pop(&ui16Index)) {}; // Empty queue
363  // Fill queue again
364  for (unsigned int i = m_ui32StartIndex; i <= m_ui32EndIndex; i++)
365  {
366  Push((uint16_t)i);
367  }
368  m_pGlobalVarStorage->ui32NrOfEntries = m_ui32MaxNrOfEntries;
369  memset(m_pInUseStorage, 0, sizeof (bool) * m_ui32MaxNrOfEntries);
370  cvmx_rwlock_wp_write_unlock(&m_pGlobalVarStorage->tRW_Lock);
371 }
372 
373 template <class T> void CFreeIndexStorage<T>::Close()
374 {
375  if (m_cCoreMask.IsFirstCore())
376  {
377  cvmx_rwlock_wp_write_lock(&m_pGlobalVarStorage->tRW_Lock);
379  cvmx_rwlock_wp_write_unlock(&m_pGlobalVarStorage->tRW_Lock);
380  cvmx_bootmem_free_named(m_cMemName);
381  }
382 }
383 #endif /* FREEINDEXSTORAGE_H_ */
bool SearchAndRemoveEntry(T tItem)
void Init(uint32_t ulNrOfItems, char *pMemName=NULL)
Definition: mpfifo.h:51
uint32_t GetNrOfEntries()
cvmx_rwlock_wp_lock_t tRW_Lock
bool SearchEntry(T tItem, uint16_t &ui16Index)
Definition: mpfifo.h:15
T GetEntry(uint16_t ui16Index)
bool ClearEntry(uint16_t ui16Index)
bool GetFreeIndexAndSet(uint16_t &ui16Index, T &tItem)
bool ReturnIndex(uint16_t ui16Index)
bool RemoveEntry(uint16_t ui16Index)
void Init(uint32_t ui32StartIndex, uint32_t ui32EndIndex, char *pcMemName, bool bCheckForInUse=true, bool bRandomFill=false)
TGlobalVar * m_pGlobalVarStorage
void Close(T **ptFifoArray=NULL, TPointers *ptPointers=NULL)
Definition: mpfifo.h:292
bool GetFreeIndex(uint16_t &ui16Index)
bool SetEntry(uint16_t ui16Index, T &tItem)
uint32_t m_ui32MaxNrOfEntries
bool FillEntry(uint16_t ui16Index, T &tItem)
T * GetEntryPointer(uint16_t ui16Index)