All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
bootmem.h
Go to the documentation of this file.
1 #include <cvmx.h>
2 #include <cvmx-rwlock.h>
3 #include <cvmx-bootmem.h>
4 #include <stdio.h>
5 
6 #pragma once
7 
8 class CBootMem
9 {
10 public:
11 
12  // Singleton
13  static CBootMem* Instance()
14  {
15  static CBootMem cInstance;
16  return &cInstance;
17  }
18 
19 
20  // I n i t
21  // =======
22  // Start on all cores
23  void Init(uint32_t ulEntries=256, bool bMulticore=true)
24  {
25  if (m_bInited)
26  {
27  if (ulEntries > m_ulEntries)
28  {
29  printf("CBootMem::Init() function already called with lesser entries (Inited entries %d, called again with %d entries)", m_ulEntries, ulEntries);
30  }
31  return;
32  }
33  m_ulEntries = ulEntries;
34 
35  uint64_t uxBytes = sizeof(TGlobal) + ulEntries * sizeof(TEntry);
36 
37  uint8_t *pucMem = (uint8_t*)cvmx_bootmem_alloc_named(uxBytes, 128, m_pcBootMemName);
38  if (pucMem == NULL)
39  {
40  if (cvmx_bootmem_find_named_block(m_pcBootMemName))
41  {
42  pucMem = (uint8_t*)cvmx_phys_to_ptr(cvmx_bootmem_find_named_block(m_pcBootMemName)->base_addr);
43  }
44  else
45  {
46  printf("CBootMem::Init() Unable to find bootmem named block (%s)", m_pcBootMemName);
47  exit(-1);
48  }
49  }
50  else
51  {
52  memset(pucMem, 0, uxBytes); // Init all to zero
53  m_ptGlobal = (TGlobal*)pucMem;
54  cvmx_rwlock_wp_init(&m_ptGlobal->tRwLock);
55  }
56 
57  m_ptGlobal = (TGlobal*)pucMem;
58  m_ptEntry = (TEntry*)(pucMem + sizeof(TGlobal));
59  m_bInited = true;
60  if (bMulticore) {
62  }
63  }
64 
65  // A l l o c
66  // =========
67  // Same as alloc but can be called mutlicore. Make sure pcCoreMask is setup
68  void* Alloc(CCoremask* pcCoreMask, const char *pcName, uint64_t uxSize, uint64_t uxAlignment = CVMX_CACHE_LINE_SIZE)
69  {
70  void* pMem = NULL;
71 
72  CAVIUM_ASSERT(pcCoreMask != NULL,("CBootMem::pcCoreMask is NULL"));
73 
74  if (!m_bInited) Init();
75 
76  pcCoreMask->BarrierSync();
77  if (pcCoreMask->IsFirstCore())
78  {
79  pMem = CBootMem::Instance()->Alloc(pcName, uxSize, uxAlignment);
80  CAVIUM_ASSERT(pMem != NULL,("CBootMem::alloc failed (%s)", pcName));
81  }
82  pcCoreMask->BarrierSync();
83  if (!pcCoreMask->IsFirstCore())
84  {
85  pMem = CBootMem::Instance()->Search(pcName);
86  CAVIUM_ASSERT(pMem != NULL,("CBootMem::search failed (%s)", pcName));
87  }
88  pcCoreMask->BarrierSync();
89  return pMem;
90  }
91 
92  // A l l o c
93  // =========
94  void* Alloc(const char *pcName, uint64_t uxSize, uint64_t uxAlignment = CVMX_CACHE_LINE_SIZE)
95  {
96  void* pMem = NULL;
97  cvmx_rwlock_wp_write_lock(&m_ptGlobal->tRwLock);
98 
99  CAVIUM_ASSERT((pcName) && (strlen(pcName)>0),("CBootMem::invalid name"));
100 
101  CAVIUM_ASSERT(m_bInited,("CBootMem::not inited (%s), use CBootMem::Instance()->Init()", pcName));
102 
103  // Search name, if already exist, return pointer to named memory
104  for (uint32_t ulEntry=0; ulEntry<m_ulEntries; ulEntry++)
105  {
106  if (m_ptEntry[ulEntry].bInUse)
107  {
108  if (strcmp(pcName, m_ptEntry[ulEntry].cName) == 0)
109  {
110  void *pReturn = cvmx_phys_to_ptr(m_ptEntry[ulEntry].uxPhysMem);
111  cvmx_rwlock_wp_write_unlock(&m_ptGlobal->tRwLock);
112  return pReturn;
113  }
114  }
115  }
116 
117  // Search free entry
118  uint32_t ulEntryFound = m_ulEntries+1;
119  for (uint32_t ulEntry=0; ulEntry<m_ulEntries; ulEntry++)
120  {
121  if (!m_ptEntry[ulEntry].bInUse)
122  {
123  ulEntryFound = ulEntry;
124  break;
125  }
126  }
127 
128  CAVIUM_ASSERT(ulEntryFound < m_ulEntries,("CBootMem::no free entry (%s)", pcName));
129 
130  // Allocate memory
131  pMem = cvmx_bootmem_alloc(uxSize, uxAlignment);
132 
133  CAVIUM_ASSERT(pMem,("CBootMem::bootmemalloc failed (%s)", pcName));
134 
135  // Init all to zero
136  memset((uint8_t*)pMem, 0, uxSize);
137 
138  // Set entry
139  m_ptEntry[ulEntryFound].bInUse = true;
140  m_ptEntry[ulEntryFound].uxSize = uxSize;
141  m_ptEntry[ulEntryFound].uxPhysMem = cvmx_ptr_to_phys(pMem);
142  snprintf(m_ptEntry[ulEntryFound].cName, SIZE_NAME, pcName);
143  cvmx_rwlock_wp_write_unlock(&m_ptGlobal->tRwLock);
144  return pMem;
145  }
146 
147  // S e a r c h
148  // ===========
149  // Search memory using name
150  void* Search(const char *pcName)
151  {
152  void* pMem = NULL;
153  cvmx_rwlock_wp_read_lock(&m_ptGlobal->tRwLock);
154 
155  if (!m_bInited)
156  {
157  cvmx_rwlock_wp_write_unlock(&m_ptGlobal->tRwLock);
158  return pMem;
159  }
160 
161  for (uint32_t ulEntry=0; ulEntry<m_ulEntries; ulEntry++)
162  {
163  if (m_ptEntry[ulEntry].bInUse)
164  {
165  if (strcmp(pcName, m_ptEntry[ulEntry].cName) == 0)
166  {
167  pMem = cvmx_phys_to_ptr(m_ptEntry[ulEntry].uxPhysMem);
168  break;
169  }
170  }
171  }
172  cvmx_rwlock_wp_read_unlock(&m_ptGlobal->tRwLock);
173  return pMem;
174  }
175 
176  // P r i n t
177  // =========
178  // Print overview use memory
179  void Print(void)
180  {
181  uint32_t ulCount = 0;
182  uint64_t uxSize = 0;
183  cvmx_rwlock_wp_read_lock(&m_ptGlobal->tRwLock);
184  printf("===============================\n");
185  printf("B O O T M E M O V E R V I E W\n");
186  printf("===============================\n");
187 
188  if (!m_bInited)
189  {
190  return;
191  }
192 
193  for (uint32_t ulEntry=0; ulEntry<m_ulEntries; ulEntry++)
194  {
195  if (m_ptEntry[ulEntry].bInUse)
196  {
197  if (m_ptEntry[ulEntry].uxSize > 1024*1024)
198  {
199  printf("%-30s data %p, %.2g MB\n", m_ptEntry[ulEntry].cName, cvmx_phys_to_ptr(m_ptEntry[ulEntry].uxPhysMem), (float)(m_ptEntry[ulEntry].uxSize/(1024*1024)));
200  }
201  else if (m_ptEntry[ulEntry].uxSize > 1024)
202  {
203  printf("%-30s data %p, %.2g KB\n", m_ptEntry[ulEntry].cName, cvmx_phys_to_ptr(m_ptEntry[ulEntry].uxPhysMem), (float)(m_ptEntry[ulEntry].uxSize/(1024)));
204  }
205  else
206  {
207  printf("%-30s data %p, %lu B\n", m_ptEntry[ulEntry].cName, cvmx_phys_to_ptr(m_ptEntry[ulEntry].uxPhysMem), m_ptEntry[ulEntry].uxSize);
208  }
209  ulCount++;
210  uxSize += m_ptEntry[ulEntry].uxSize;
211  }
212  }
213  cvmx_rwlock_wp_read_unlock(&m_ptGlobal->tRwLock);
214  printf("Count %d, Total size %.2g MB\n", ulCount, (float)(uxSize/(1024*1024)) );
215  printf("===============================\n");
216  }
217 
218  // F r e e
219  // =======
220  // Free memory using name
221  bool Free(const char *pcName)
222  {
223  bool bResult = false;
224  cvmx_rwlock_wp_write_lock(&m_ptGlobal->tRwLock);
225 
226  if (!m_bInited)
227  {
228  cvmx_rwlock_wp_write_unlock(&m_ptGlobal->tRwLock);
229  return false;
230  }
231 
232  for (uint32_t ulEntry=0; ulEntry<m_ulEntries; ulEntry++)
233  {
234  if (m_ptEntry[ulEntry].bInUse)
235  {
236  if (strcmp(pcName, m_ptEntry[ulEntry].cName) == 0)
237  {
238  bResult = Free(ulEntry);
239  break;
240  }
241  }
242  }
243  cvmx_rwlock_wp_write_unlock(&m_ptGlobal->tRwLock);
244  return bResult;
245  }
246 
247  // F r e e
248  // =======
249  // Free memory using pointer
250  bool Free(void *pMem)
251  {
252  bool bResult = false;
253  uint64_t uxPhysMem = cvmx_ptr_to_phys(pMem);
254  cvmx_rwlock_wp_write_lock(&m_ptGlobal->tRwLock);
255 
256  if (!m_bInited)
257  {
258  cvmx_rwlock_wp_write_unlock(&m_ptGlobal->tRwLock);
259  return false;
260  }
261 
262  for (uint32_t ulEntry=0; ulEntry<m_ulEntries; ulEntry++)
263  {
264  if (m_ptEntry[ulEntry].bInUse)
265  {
266  if (m_ptEntry[ulEntry].uxPhysMem == uxPhysMem)
267  {
268  bResult = Free(ulEntry);
269  break;
270  }
271  }
272  }
273  cvmx_rwlock_wp_write_unlock(&m_ptGlobal->tRwLock);
274  return bResult;
275  }
276 
277 private:
278 
279  // C o n s t r u c t o r
280  // =====================
281  CBootMem()
282  {
283  m_pcBootMemName = "CBootMem";
284  m_ptGlobal = NULL;
285  m_ptEntry = NULL;
286  m_ulEntries = 0;
287  m_bInited = false;
288  }
289 
290 
291  bool Free(uint32_t ulEntry)
292  {
293  if (ulEntry >= m_ulEntries)
294  {
295  return false;
296  }
297 
298  if (!m_ptEntry[ulEntry].bInUse)
299  {
300  return false;
301  }
302 
303  m_ptEntry[ulEntry].bInUse = false;
304  m_ptEntry[ulEntry].uxPhysMem = 0;
305  m_ptEntry[ulEntry].uxSize = 0;
306  return true;
307  }
308 
309 
310  enum EPrivate
311  {
312  SIZE_NAME = 100
313  };
314 
315  struct TGlobal
316  {
317  cvmx_rwlock_wp_lock_t tRwLock;
318  };
319 
320  struct TEntry
321  {
322  bool bInUse;
323  uint64_t uxSize;
324  char cName[SIZE_NAME];
325  uint64_t uxPhysMem;
326  };
327 
328  TGlobal* m_ptGlobal;
329  TEntry* m_ptEntry;
330  uint32_t m_ulEntries;
331  bool m_bInited;
332  const char * m_pcBootMemName;
333 };
void * Alloc(const char *pcName, uint64_t uxSize, uint64_t uxAlignment=CVMX_CACHE_LINE_SIZE)
Definition: bootmem.h:94
#define CAVIUM_ASSERT(exp, msg)
Definition: caviumaccess.h:30
void * Alloc(CCoremask *pcCoreMask, const char *pcName, uint64_t uxSize, uint64_t uxAlignment=CVMX_CACHE_LINE_SIZE)
Definition: bootmem.h:68
bool Free(void *pMem)
Definition: bootmem.h:250
static CBootMem * Instance()
Definition: bootmem.h:13
void * Search(const char *pcName)
Definition: bootmem.h:150
bool Free(const char *pcName)
Definition: bootmem.h:221
bool IsFirstCore(void)
Definition: coremask.h:40
void BarrierSync(void)
Definition: coremask.h:71
void Init(uint32_t ulEntries=256, bool bMulticore=true)
Definition: bootmem.h:23
static void BarrierSyncStatic(void)
Definition: coremask.h:80
void Print(void)
Definition: bootmem.h:179