(file) Return to alloc.c CVS log (file) (dir) Up to [OMI] / omi / pal

  1 krisbash 1.1 #include <nits/base/nits.h>
  2              #include "strings.h"
  3              #include <assert.h>
  4              #include <limits.h>
  5              #include <stdio.h>
  6              
  7              #if !defined(_MSC_VER)
  8              # include <pthread.h>
  9              #endif
 10              
 11              #if defined(USE_ALLOCATOR)
 12              # define ALLOC_MAGIC 0x89ABCDEF
 13              # define ENABLE_FILLING
 14              # define ENABLE_CLEARING
 15              
 16              static AllocStats _stats;
 17              static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;
 18              
 19              typedef struct _AllocHeader AllocHeader;
 20              
 21              struct _AllocHeader
 22 krisbash 1.1 {
 23                  struct _AllocHeader* prev;
 24                  struct _AllocHeader* next;
 25                  const char* file;
 26                  unsigned int line;
 27                  unsigned int id;
 28                  unsigned int magic;
 29                  unsigned int size;
 30              };
 31              
 32              static unsigned int _id;
 33              
 34              static AllocHeader* _list;
 35              
 36              typedef struct _AllocTrailer
 37              {
 38                  unsigned int magic;
 39              }
 40              AllocTrailer;
 41              
 42              static size_t _GetSize(void* ptr)
 43 krisbash 1.1 {
 44                  AllocHeader* h = (AllocHeader*)ptr - 1;
 45                  AllocTrailer* t;
 46              
 47                  if (h->magic != ALLOC_MAGIC || h->size == 0)
 48                      return (size_t)-1;
 49              
 50                  t = (AllocTrailer*)((char*)ptr + h->size);
 51              
 52                  if (t->magic != ALLOC_MAGIC)
 53                      return (size_t)-1;
 54              
 55                  return (size_t)h->size;
 56              }
 57              
 58              AllocStats PAL_GetAllocStats()
 59              {
 60                  AllocStats stats;
 61                  pthread_mutex_lock(&_mutex);
 62                  stats = _stats;
 63                  pthread_mutex_unlock(&_mutex);
 64 krisbash 1.1     return stats;
 65              }
 66              
 67              size_t PAL_GetBlocksAllocated()
 68              {
 69                  AllocStats stats;
 70                  pthread_mutex_lock(&_mutex);
 71                  stats = _stats;
 72                  pthread_mutex_unlock(&_mutex);
 73                  return (size_t)(stats.numAllocs - stats.numFrees);
 74              }
 75              
 76              void PAL_CheckBlocksAllocated(
 77                  size_t oldBlocksAllocated,
 78                  const char* file,
 79                  size_t line,
 80                  const char* function)
 81              {
 82                  size_t blocksAllocated = PAL_GetBlocksAllocated();
 83                  size_t nblocks;
 84              
 85 krisbash 1.1     if (blocksAllocated <= oldBlocksAllocated)
 86                      return;
 87              
 88                  nblocks = blocksAllocated - oldBlocksAllocated;
 89              
 90                  printf("\nWARNING: %s(%u): %s(): %u blocks were leaked\n\n",
 91                      file, (int)line, function, (int)nblocks); 
 92              }
 93              
 94              void PAL_DumpAllocStats()
 95              {
 96                  AllocStats stats = PAL_GetAllocStats();
 97              
 98                  printf("=== PAL_DumpAllocStats:\n");
 99                  printf("usage: %d\n", (int)stats.usage);
100                  printf("peakUsage: %d\n", (int)stats.peakUsage);
101                  printf("numAllocs: %d\n", (int)stats.numAllocs);
102                  printf("numFrees: %d\n", (int)stats.numFrees);
103                  printf("\n");
104              }
105              
106 krisbash 1.1 void PAL_DumpAllocList()
107              {
108                  AllocHeader* p;
109              
110                  if (!_list)
111                      return;
112              
113                  printf("\nWARNING: one or more blocks still allocated!\n");
114              
115                  for (p = _list; p; p = p->next)
116                  {
117                      printf("BLOCK: %s(%u): ptr=%p: magic=%08X id=%u size=%u\n",
118                          p->file, (int)p->line, p, p->magic, p->id, p->size);
119                  }
120              
121                  printf("\n");
122                  printf("\n");
123              }
124              
125              static void* _Alloc(
126                  const char* file,
127 krisbash 1.1     size_t line,
128                  const char* func,
129                  size_t size)
130              {
131                  AllocHeader* h;
132                  AllocTrailer* t;
133                  void* p;
134              
135                  /* Be sure size will fit into h->size field */
136                  assert(size <= UINT_MAX);
137              
138                  /* Return null if request size is zero */
139                  if (size == 0)
140                  {
141                      assert(0);
142                      return NULL;
143                  }
144              
145                  /* Allocate the block of memory with room for header and trailer */
146                  if (!(h = SystemMalloc(sizeof(AllocHeader) + size + sizeof(AllocTrailer))))
147                  {
148 krisbash 1.1         assert(0);
149                      return NULL;
150                  }
151              
152                  /* Initialize the header */
153                  h->prev = NULL;
154                  h->next = NULL;
155                  h->file = file;
156                  h->line = line;
157                  h->magic = ALLOC_MAGIC;
158                  h->size = (unsigned int)size;
159              
160                  /* Initialize the user block (fill with 0xAA bytes) */
161                  p = h + 1;
162              #if defined(ENABLE_FILLING)
163                  memset(p, 0xAA, size);
164              #else
165                  memset(p, 0x00, size);
166              #endif
167              
168                  /* Initialize the trailer */
169 krisbash 1.1     t = (AllocTrailer*)((char*)p + size);
170                  t->magic = ALLOC_MAGIC;
171              
172                  /* Check that this function created a valid block */
173                  assert(_GetSize(p) == size);
174              
175                  /* Update statistics and add block to glboal list */
176                  pthread_mutex_lock(&_mutex);
177                  {
178                      _stats.usage += size;
179                      _stats.numAllocs++;
180              
181                      if (_stats.usage > _stats.peakUsage)
182                          _stats.peakUsage = _stats.usage;
183              
184                      /* Prepend block to list */
185                      {
186                          if (_list)
187                              _list->prev = h;
188              
189                          h->prev = NULL;
190 krisbash 1.1             h->next = _list;
191                          _list = h;
192                      }
193              
194                      h->id = _id++;
195                  }
196                  pthread_mutex_unlock(&_mutex);
197              
198                  return p;
199              }
200              
201              void* __PAL_Malloc(
202                  const char* file,
203                  size_t line,
204                  const char* func,
205                  size_t size)
206              {
207              #if defined(ENABLE_ALLOC_FAULT_INJECTION)
208                  if (file && 
209                      NitsShouldFault(NitsMakeCallSite(-1, func, file, line), NitsAutomatic))
210                      return NULL;
211 krisbash 1.1 #endif
212              
213                  return _Alloc(file, line, func, size);
214              }
215              
216              void* __PAL_MallocCallsite(
217                  NitsCallSite callsite,
218                  size_t size)
219              {
220              #if defined(ENABLE_ALLOC_FAULT_INJECTION)
221                  if (NitsShouldFault(callsite, NitsAutomatic))
222                      return NULL;
223              #endif
224              
225                  return _Alloc(callsite.file, callsite.line, callsite.function, size);
226              }
227              
228              void* _Calloc(
229                  const char* file,
230                  size_t line,
231                  const char* func,
232 krisbash 1.1     size_t count,
233                  size_t size)
234              {
235                  void* p;
236                  size_t n = count * size; 
237              
238                  if (n == 0)
239                      return NULL;
240                  
241                  if (!(p = _Alloc(file, line, func, n)))
242                      return NULL;
243              
244                  return memset(p, 0x00, n);    
245              }
246              
247              void* __PAL_Calloc(
248                  const char* file,
249                  size_t line,
250                  const char* func,
251                  size_t count,
252                  size_t size)
253 krisbash 1.1 {
254              
255              #if defined(ENABLE_ALLOC_FAULT_INJECTION)
256                  if (file && 
257                      NitsShouldFault(NitsMakeCallSite(-1, func, file, line), NitsAutomatic))
258                      return NULL;
259              #endif
260              
261                  return _Calloc( file, line, func, count, size);
262              }
263              
264              void* __PAL_CallocCallsite(
265                  NitsCallSite callsite,
266                  size_t count,
267                  size_t size)
268              {
269              
270              #if defined(ENABLE_ALLOC_FAULT_INJECTION)
271                  if (NitsShouldFault(callsite, NitsAutomatic))
272                      return NULL;
273              #endif
274 krisbash 1.1     
275                  return _Calloc(callsite.file, callsite.line, callsite.function, count, size);
276              }
277              
278              
279              void* _Realloc(
280                  const char* file,
281                  size_t line,
282                  const char* func,
283                  void* ptr,
284                  size_t size)
285              {
286                  size_t n;
287                  void* p;
288              
289                  /* Fail if request size is zero */
290                  if (size == 0)
291                  {
292                      assert(0);
293                      return NULL;
294                  }
295 krisbash 1.1 
296                  /* If ptr is null, then just pass to _Alloc() */
297                  if (!ptr)
298                      return _Alloc(file, line, func, size);
299              
300                  /* Get the size of the old block (assert if invalid block) */
301                  n = _GetSize(ptr);
302                  assert(n != (size_t)-1);
303              
304                  /* Allocate the new block */
305                  if (!(p = _Alloc(file, line, func, size)))
306                  {
307                      assert(0);
308                      return NULL;
309                  }
310                  
311                  /* Copy over data from the old block */
312                  if (n < size)
313                  {
314                      memcpy(p, ptr, n);
315              
316 krisbash 1.1         /* Fill unused part with 0xAA bytes */
317              #if defined(ENABLE_FILLING)
318                      memset((char*)p + n, 0xAA, size - n);
319              #else
320                      memset((char*)p + n, 0x00, size - n);
321              #endif
322                  }
323                  else
324                      memcpy(p, ptr, size);
325              
326                  /* Free the old block */
327                  __PAL_Free(file, line, func, ptr);
328              
329                  return p;    
330              }
331              
332              void* __PAL_Realloc(
333                  const char* file,
334                  size_t line,
335                  const char* func,
336                  void* ptr,
337 krisbash 1.1     size_t size)
338              {
339              
340              #if defined(ENABLE_ALLOC_FAULT_INJECTION)
341                  if (file && 
342                      NitsShouldFault(NitsMakeCallSite(-1, func, file, line), NitsAutomatic))
343                      return NULL;
344              #endif
345              
346                  return _Realloc(file, line, func, ptr, size);
347              }
348              
349              
350              void* __PAL_ReallocCallsite(
351                  NitsCallSite callsite,
352                  void* ptr,
353                  size_t size)
354              {
355              #if defined(ENABLE_ALLOC_FAULT_INJECTION)
356                  if (NitsShouldFault(callsite, NitsAutomatic))
357                      return NULL;
358 krisbash 1.1 #endif
359              
360                  return _Realloc(callsite.file, callsite.line, callsite.function, ptr, size);
361              }
362              
363              void __PAL_Free(
364                  const char* file,
365                  size_t line,
366                  const char* func,
367                  void* ptr)
368              {
369                  if (ptr)
370                  {
371                      size_t n;
372                      AllocHeader* h;
373              
374                      /* Get size of this block */
375                      n = _GetSize(ptr);
376                      assert(n != (size_t)-1);
377              
378                      /* Fill the block with 0xDD bytes */
379 krisbash 1.1 #if defined(ENABLE_CLEARING)
380                      memset(ptr, 0xDD, n);
381              #endif
382              
383                      /* Get pointer to header */
384                      h = (AllocHeader*)ptr - 1;
385              
386                      /* Update statistics and remove block from list */
387                      pthread_mutex_lock(&_mutex);
388                      {
389                          _stats.usage -= n;
390                          _stats.numFrees++;
391              
392                          /* Remove block from the list */
393                          if (h == _list)
394                          {
395                              _list = h->next;
396              
397                              if (_list)
398                                  _list->prev = NULL;
399                          }
400 krisbash 1.1             else
401                          {
402                              if (h->prev)
403                                  h->prev->next = h->next;
404                              if (h->next)
405                                  h->next->prev = h->prev;
406                          }
407              
408                      }
409                      pthread_mutex_unlock(&_mutex);
410              
411                      /* Free the block */
412                      SystemFree(h);
413                  }
414              }
415              
416              char* __PAL_Strdup(
417                  const char* file,
418                  size_t line,
419                  const char* func,
420                  const char* str)
421 krisbash 1.1 {
422                  char* p;
423                  size_t n;
424              
425                  assert(str != NULL);
426              
427                  n = (strlen(str) + 1) * sizeof(char);
428              
429                  if (!(p = _Alloc(file, line, func, n)))
430                      return NULL;
431              
432                  return memcpy(p, str, n);
433              }
434              
435              wchar_t* __PAL_Wcsdup(
436                  const char* file,
437                  size_t line,
438                  const char* func,
439                  const wchar_t* str)
440              {
441                  wchar_t* p;
442 krisbash 1.1     size_t n;
443              
444                  assert(str != NULL);
445              
446                  n = (wcslen(str) + 1) * sizeof(wchar_t);
447              
448                  if (!(p = _Alloc(file, line, func, n)))
449                      return NULL;
450              
451                  return memcpy(p, str, n);
452              }
453              
454              PAL_Char* __PAL_Tcsdup(
455                  const char* file,
456                  size_t line,
457                  const char* func,
458                  const PAL_Char* str)
459              {
460                  PAL_Char* p;
461                  size_t n;
462              
463 krisbash 1.1     assert(str != NULL);
464              
465                  n = (Tcslen(str) + 1) * sizeof(PAL_Char);
466              
467                  if (!(p = _Alloc(file, line, func, n)))
468                      return NULL;
469              
470                  return memcpy(p, str, n);
471              }
472              
473              #endif /* defined(USE_ALLOCATOR) */

ViewCVS 0.9.2