ARB
admalloc.cxx
Go to the documentation of this file.
1 // =============================================================== //
2 // //
3 // File : admalloc.cxx //
4 // Purpose : //
5 // //
6 // Institute of Microbiology (Technical University Munich) //
7 // http://www.arb-home.de/ //
8 // //
9 // =============================================================== //
10 
11 #include <unistd.h>
12 #include <climits>
13 #include <set>
14 
15 #include <arb_backtrace.h>
16 #include "gb_storage.h"
17 
18 // #define DUMP_MEMBLKS
19 // #define DUMP_MEMBLKS_AT_EXIT
20 
21 #ifdef DEBUG
22 // #define TEST_MEMBLKS
23 // #define TRACE_ALLOCS
24 #if defined(WARN_TODO)
25 #warning unit tests fail when TRACE_ALLOCS is defined (due to wrong sized block during load(?). cant fix atm. see [6672])
26 #endif
27 #endif
28 
29 #define GBM_MAGIC 0x74732876
30 
31 #define GBM_SYSTEM_PAGE_SIZE 4096 // 4k Tables
32 #define GBM_MALLOC_OVERHEAD 32 // pointer for alloc
33 #define GBM_TABLE_SIZE (GBM_SYSTEM_PAGE_SIZE-GBM_MALLOC_OVERHEAD) // usable size of table
34 
35 #define GBM_ALIGNED 8
36 #define GBM_LD_ALIGNED 3
37 
38 #define GBM_MAX_TABLES 16 // n different sizes -> max = GBM_MAX_TABLES * GBM_ALIGNED
39 #define GBM_MAX_SIZE (GBM_MAX_TABLES*GBM_ALIGNED)
40 #define GBM_MAX_INDEX 256 // has to be 2 ^ x (with x = GBM_MAX_TABLES ? )
41 
42 
43 struct gbm_data {
44  long magic; // indicates free element
45  gbm_data *next; // next free element
46 };
47 
48 struct gbm_table { // a block containing data
51 };
52 
53 static struct gbm_pool { // one pool for each memory index
54  gbm_data *gds; // free data area
55  size_t size; // free size of current table
56  size_t allsize; // full size of all tables
57  gbm_table *first; // link list of tables
58  gbm_data *tables[GBM_MAX_TABLES+1]; // free entries
59  long tablecnt[GBM_MAX_TABLES+1]; // number of free entries
60  long useditems[GBM_MAX_TABLES+1]; // number of used items (everything)
61  size_t extern_data_size; // not handled by this routine
64 
65 static struct {
66  char *old_sbrk;
67 } gbm_global;
68 
69 
70 #define GBB_INCR 11 // memsize increment in percent between adjacent clusters
71 #define GBB_CLUSTERS 64 // # of different clusters
72 #define GBB_ALIGN GBM_LD_ALIGNED // align memsize of clusters (# of bits)
73 #define GBB_MINSIZE GBM_MAX_SIZE // minimal size of allocated big block
74 #define GBB_MAX_TRIALS 4 // maximal number of clusters to search for an unused block
75 #define GBB_MAGIC 0x67823747
76 
77 struct gbb_data;
78 
79 struct gbb_freedata { // part of gbb_data if it`s a free block
80  // cppcheck-suppress unusedStructMember
81  long magic;
82  gbb_data *next; // next unused memblock
83 };
84 
85 struct gbb_data {
86  size_t size; // real size of memblock (from `content` to end of block)
87  long allocFromSystem; // ==0 -> it`s a block imported by gbm_put_mem
88  gbb_freedata content; // startposition of block returned to user or chain info for free blocks
89 };
90 
91 #define GBB_HEADER_SIZE (sizeof(gbb_data)-sizeof(gbb_freedata))
92 
93 static struct gbb_Cluster {
94  size_t size; // minimum size of memblocks in this cluster
95  gbb_data *first; // first free block
96 
98 
99 
100 #ifdef TRACE_ALLOCS
101 
102 class AllocLogEntry {
103  void *block;
104  size_t size;
105  long index;
106 
107  mutable BackTraceInfo *trace;
108 
109 public:
110  AllocLogEntry(void *block_, size_t size_, long index_, bool do_trace) :
111  block(block_),
112  size(size_),
113  index(index_),
114  trace(do_trace ? GBK_get_backtrace(5) : NULp)
115  { }
116  AllocLogEntry(const AllocLogEntry& other) :
117  block(other.block),
118  size(other.size),
119  index(other.index),
120  trace(other.trace)
121  {
122  other.trace = NULp;
123  }
124  ~AllocLogEntry() { if (trace) GBK_free_backtrace(trace); }
125 
126  size_t get_size() const { return size; }
127  long get_index() const { return index; }
128 
129  bool operator<(const AllocLogEntry& other) const { return block < other.block; }
130  void dump(FILE *out, GB_CSTR message) const { GBK_dump_former_backtrace(trace, out, message); }
131 };
132 
133 typedef std::set<AllocLogEntry> AllocLogEntries;
134 
135 class AllocLogger {
136  AllocLogEntries entries;
137 
138  const AllocLogEntry *existingEntry(void *block) {
139  AllocLogEntries::const_iterator found = entries.find(AllocLogEntry(block, 0, 0, false));
140 
141  return found == entries.end() ? NULp : &*found;
142  }
143 
144 public:
145  AllocLogger() {
146  }
147  ~AllocLogger() {
148  size_t count = entries.size();
149  if (count) {
150  fprintf(stderr, "%zu non-freed blocks:\n", count);
151  AllocLogEntries::const_iterator end = entries.end();
152  for (AllocLogEntries::const_iterator entry = entries.begin(); entry != end; ++entry) {
153  entry->dump(stderr, "block was allocated from here");
154  }
155  }
156  }
157 
158  void allocated(void *block, size_t size, long index) {
159  const AllocLogEntry *exists = existingEntry(block);
160  if (exists) {
161  GBK_dump_backtrace(stderr, "Block allocated again");
162  exists->dump(stderr, "Already allocated from here");
163  }
164  else {
165  entries.insert(AllocLogEntry(block, size, index, true));
166  }
167  }
168  void freed(void *block, size_t size, long index) {
169  const AllocLogEntry *exists = existingEntry(block);
170  if (!exists) {
171  if (!gb_isMappedMemory(block)) {
172  gb_assert(0);
173  // GBK_dump_backtrace(stderr, "Tried to free unallocated block");
174  }
175  }
176  else {
177  gb_assert(exists->get_size() == size);
178  gb_assert(exists->get_index() == index);
179  entries.erase(*exists);
180  }
181  }
182 };
183 
184 static AllocLogger allocLogger;
185 
186 #endif
187 
188 inline void free_gbm_table(gbm_table *table) {
189  while (table) {
190  gbm_table *next = table->next;
191 
192  free(table);
193  table = next;
194  }
195 }
196 
197 static bool gbm_mem_initialized = false;
198 
200  gb_assert(gbm_mem_initialized);
201 
202  for (int i = 0; i<GBM_MAX_INDEX; ++i) {
203  gbm_pool& gbm = gbm_pool4idx[i];
204  bool have_used_items = false;
205 
206  for (int t = 0; t < GBM_MAX_TABLES; t++) {
207  if (gbm.useditems[t]) {
208  have_used_items = true;
209  break;
210  }
211  }
212 
213  if (!have_used_items) {
214  free_gbm_table(gbm.first);
215  memset((char*)&gbm, 0, sizeof(gbm));
216  }
217  }
218 }
219 
220 void gbm_init_mem() {
221  if (!gbm_mem_initialized) {
222  for (int i = 0; i<GBM_MAX_INDEX; ++i) {
223  memset((char *)&gbm_pool4idx[i], 0, sizeof(gbm_pool));
224  gbm_pool4idx[i].tables[0] = NULp; // CORE zero get mem
225  }
226  gbm_global.old_sbrk = (char *)sbrk(0);
227 
228  /* init GBB:
229  * --------- */
230 
232  gbb_cluster[0].first = NULp;
233 
234  for (int i = 1; i<GBB_CLUSTERS; ++i) {
235  long nextSize = gbb_cluster[i-1].size * (100+GBB_INCR);
236 
237  nextSize /= 100;
238  nextSize >>= GBB_ALIGN;
239  nextSize ++;
240  nextSize <<= GBB_ALIGN;
241 
242  gbb_cluster[i].size = nextSize;
243  gbb_cluster[i].first = NULp;
244  }
245 
246  // last cluster contains ALL bigger blocks
247 
248  gbb_cluster[GBB_CLUSTERS].size = INT_MAX;
250 
251  gbm_mem_initialized = true;
252  }
253 }
254 
257  gb_assert(!gbm_mem_initialized); // there may be only one instance!
258  gbm_init_mem();
259  }
261 #if defined(DUMP_MEMBLKS_AT_EXIT)
262  printf("memory at exit:\n");
263  gbm_debug_mem();
264 #endif // DUMP_MEMBLKS_AT_EXIT
265  gbm_flush_mem();
266 #if defined(DUMP_MEMBLKS_AT_EXIT)
267  printf("memory at exit (after flush):\n");
268  gbm_debug_mem();
269 #endif // DUMP_MEMBLKS_AT_EXIT
270  }
271 };
273 
274 #ifdef TEST_MEMBLKS
275 
276 #define TEST() testMemblocks(__FILE__, __LINE__)
277 
278 void testMemblocks(const char *file, int line) {
279  int idx;
280 
281  for (idx=0; idx<GBB_CLUSTERS; idx++) {
282  struct gbb_Cluster *cl = &(gbb_cluster[idx]);
283  gbb_data *blk = cl->first;
284 
285  while (blk) {
286  if (blk->size<cl->size) {
287  fprintf(stderr, "Illegal block (size=%zu) in cluster %i (size=%zu) (%s,%i)\n", blk->size, idx, cl->size, file, line);
288  gb_assert(0);
289  }
290  blk = blk->content.next;
291  }
292  }
293 }
294 
295 #else
296 # define TEST()
297 #endif
298 
299 
300 #if (MEMORY_TEST==0)
301 
302 static void imemerr(const char *why) {
303  GB_internal_errorf("Dangerous internal error: '%s'\n"
304  "Inconsistent database: Do not overwrite old files with this database", why);
305 }
306 
307 static int getClusterIndex(size_t size) {
308  // searches the index of the lowest cluster for that: size <= cluster->size
309  int l, m, h;
310 
311  if (size<GBB_MINSIZE) return 0;
312 
313  l = 1;
314  h = GBB_CLUSTERS;
315 
316  while (l!=h) {
317  m = (l+h)/2;
318  if (gbb_cluster[m].size < size) l = m+1;
319  else h = m;
320  }
321 
323 
324  return l;
325 }
326 
327 static void gbm_put_memblk(char *memblk, size_t size) {
328  /* gives any memory block (allocated or not)
329  into the responsibility of this module;
330  the block has to be aligned!!! */
331 
332  gbb_data *block;
333  int idx;
334 
335  TEST();
336 
337 #ifdef DUMP_MEMBLKS
338  printf("put %p (%li bytes)\n", memblk, size);
339 #endif
340 
341  if (size<(GBB_HEADER_SIZE+GBB_MINSIZE)) {
342  GB_internal_errorf("gmb_put_memblk() called with size below %zu bytes",
344  return;
345  }
346 
347  block = (gbb_data *)memblk;
348  block->size = size-GBB_HEADER_SIZE;
349  block->allocFromSystem = 0;
350 
351  idx = getClusterIndex(block->size)-1;
352  if (idx<0) { // (silences warning in NDEBUG mode)
353  gb_assert(0); // should be impossible
354  return;
355  }
356 
357  block->content.next = gbb_cluster[idx].first;
358  block->content.magic = GBB_MAGIC;
359  gbb_cluster[idx].first = block;
360 
361  gb_assert(idx==GBB_CLUSTERS || block->size>=gbb_cluster[idx].size);
362  TEST();
363 }
364 
365 static char *gbm_get_memblk(size_t size) {
366  gbb_data *block = NULp;
367  int trials = GBB_MAX_TRIALS;
368  int idx;
369 
370  TEST();
371 
372  idx = getClusterIndex(size);
373  gb_assert(gbb_cluster[idx].size>=size);
374 
375  while (trials--) { // search a cluster containing a block
376  if ((block = gbb_cluster[idx].first)) break; // found!
377  if (idx==GBB_CLUSTERS) break; // last cluster!
378  idx++;
379  }
380 
381  if (!block) { // if no unused block -> allocate from system
382  int allocationSize;
383 
384  allocFromSys :
385 
386  allocationSize = (idx==GBB_CLUSTERS
387  ? (size_t)size
388  : (size_t)(gbb_cluster[idx].size)) + GBB_HEADER_SIZE;
389 
390  block = (gbb_data *)ARB_calloc<char>(allocationSize);
391 
392  block->size = allocationSize-GBB_HEADER_SIZE;
393  block->allocFromSystem = 1;
394 
395  gb_assert(block->size>=size);
396 
397 #ifdef DUMP_MEMBLKS
398  printf("allocated %li bytes\n", size);
399 #endif
400  }
401  else {
402  gbb_data **blockPtr = &(gbb_cluster[idx].first);
403 
404  if (idx==GBB_CLUSTERS) { // last cluster (test for block size necessary)
405  while ((block=*blockPtr) && block->size<size)
406  blockPtr = &(block->content.next);
407 
408  if (!block) goto allocFromSys;
409  gb_assert(block->size>=size);
410  }
411 
412  if (block->content.magic!=GBB_MAGIC) { imemerr("bad magic number if free block"); return NULp; }
413  *blockPtr = block->content.next;
414  memset((char*)&(block->content), 0, size); // act like calloc
415 
416 #ifdef DUMP_MEMBLKS
417  printf("using unused block "
418  "(add=%p,size=%li, block->size=%li,cluster->size=%li)\n",
419  block, size, block->size, gbb_cluster[idx].size);
420 #endif
421 
422  gb_assert(block->size>=size);
423  }
424 
425  gb_assert(block->size>=size);
426 
427  TEST();
428 
429  return (char*)&(block->content);
430 }
431 
432 void *gbmGetMemImpl(size_t size, long index) {
433  if (size < sizeof(gbm_data)) size = sizeof(gbm_data);
434  index &= GBM_MAX_INDEX-1;
435 
436  gbm_pool *ggi = &gbm_pool4idx[index];
437  unsigned long nsize = (size + (GBM_ALIGNED - 1)) & (-GBM_ALIGNED);
438 
439  char *result;
440  if (nsize > GBM_MAX_SIZE) {
441  ggi->extern_data_size += nsize;
442  ggi->extern_data_items++;
443 
444  result = gbm_get_memblk((size_t)nsize);
445  }
446  else {
447  unsigned long pos = nsize >> GBM_LD_ALIGNED;
448  gbm_data *gds = ggi->tables[pos];
449  if (gds) {
450  ggi->tablecnt[pos]--;
451  result = (char *)gds;
452  if (gds->magic != GBM_MAGIC) {
453  printf("%lX!= %lX\n", gds->magic, (long)GBM_MAGIC);
454  GB_internal_error("Dangerous internal error: Inconsistent database: "
455  "Do not overwrite old files with this database");
456  }
457  ggi->tables[pos] = ggi->tables[pos]->next;
458  }
459  else {
460  if (ggi->size < nsize) {
461  gbm_table *gts;
463 
464  memset((char *)gts, 0, GBM_TABLE_SIZE);
465  ggi->gds = &gts->data[0];
466  gts->next = ggi->first; // link tables
467  ggi->first = gts;
468  ggi->size = GBM_TABLE_SIZE - sizeof(void *);
469  ggi->allsize += GBM_TABLE_SIZE;
470  }
471  result = (char *)ggi->gds;
472  ggi->gds = (gbm_data *)(((char *)ggi->gds) + nsize);
473  ggi->size -= (size_t)nsize;
474  }
475 
476  ggi->useditems[pos]++;
477  memset(result, 0, nsize); // act like calloc()
478  }
479 
480 #ifdef TRACE_ALLOCS
481  allocLogger.allocated(erg, size, index);
482 #endif
483  return result;
484 }
485 
486 void gbmFreeMemImpl(void *data, size_t size, long index) {
487  if (size < sizeof(gbm_data)) size = sizeof(gbm_data);
488  index &= GBM_MAX_INDEX-1;
489 
490  gbm_pool *ggi = &gbm_pool4idx[index];
491  long nsize = (size + (GBM_ALIGNED - 1)) & (-GBM_ALIGNED);
492 
493 #ifdef TRACE_ALLOCS
494  allocLogger.freed(data, size, index);
495 #endif
496 
497  if (nsize > GBM_MAX_SIZE) {
498  gbb_data *block;
499 
500  if (gb_isMappedMemory(data)) {
501  block = (gbb_data *)data;
502 
503  block->size = size-GBB_HEADER_SIZE;
504  block->allocFromSystem = 0;
505 
506  if (size>=(GBB_HEADER_SIZE+GBB_MINSIZE)) {
507  gbm_put_memblk((char*)block, size);
508  }
509  }
510  else {
511  block = (gbb_data *)((char*)data-GBB_HEADER_SIZE);
512 
513  ggi->extern_data_size -= (size_t)nsize;
514  ggi->extern_data_items--;
515 
516  if (block->size<size) { imemerr("block size does not match"); return; }
517 
518  if (block->allocFromSystem) {
519  free(block);
520  }
521  else {
522  /* printf("put unused block (size=%li block->size=%li)\n",
523  size,block->size); */
524  gbm_put_memblk((char*)block, block->size + GBB_HEADER_SIZE);
525  }
526  }
527  }
528  else {
529  if (gb_isMappedMemory(data)) return; // @@@ reason: size may be shorter
530 
531  gbm_data *gdata = (gbm_data*)data;
532 
533  if (gdata->magic == GBM_MAGIC) {
534  imemerr("double free");
535  return;
536  }
537 
538  long pos = nsize >> GBM_LD_ALIGNED;
539 
540  gdata->next = ggi->tables[pos];
541  gdata->magic = GBM_MAGIC;
542  ggi->tables[pos] = gdata;
543  ggi->tablecnt[pos]++;
544  ggi->useditems[pos]--;
545  }
546 }
547 
548 #endif // MEMORY_TEST==0
549 
551  int i;
552  int index;
553  long total = 0;
554  long index_total;
555  gbm_pool *ggi;
556 
557  printf("Memory Debug Information:\n");
558  for (index = 0; index < GBM_MAX_INDEX; index++) {
559  index_total = 0;
560  ggi = &gbm_pool4idx[index];
561  for (i = 0; i < GBM_MAX_TABLES; i++) {
562  index_total += i * GBM_ALIGNED * (int) ggi->useditems[i];
563  total += i * GBM_ALIGNED * (int) ggi->useditems[i];
564 
565  if (ggi->useditems[i] || ggi->tablecnt[i]) {
566  printf("\t'I=%3i' 'Size=%3i' * 'Items %4i' = 'size %7i' 'sum=%7li' 'totalsum=%7li' : Free %3i\n",
567  index,
568  i * GBM_ALIGNED,
569  (int) ggi->useditems[i],
570  i * GBM_ALIGNED * (int) ggi->useditems[i],
571  index_total,
572  total,
573  (int) ggi->tablecnt[i]);
574  }
575  }
576  if (ggi->extern_data_size) {
577  index_total += ggi->extern_data_size;
578  total += ggi->extern_data_size;
579  printf("\t'I=%3i' External Data Items=%3li = Sum=%3li 'sum=%7li' 'total=%7li\n",
580  index,
581  ggi->extern_data_items,
582  (long)ggi->extern_data_size,
583  index_total,
584  total);
585  }
586  }
587 
588  {
589  char *topofmem = (char *)sbrk(0);
590  printf("spbrk %lx old %lx size %ti\n",
591  (long)topofmem,
592  (long)gbm_global.old_sbrk,
593  topofmem-gbm_global.old_sbrk);
594  }
595 }
596 
597 // --------------------------------------------------------------------------------
598 
599 #if defined(UNIT_TESTS) && 0
600 
601 #include <test_unit.h>
602 
603 void TEST_ARBDB_memory() { // not a real unit test - just was used for debugging
604 #define ALLOCS 69
605  long *blocks[ALLOCS];
606 
607 #if (MEMORY_TEST == 0)
608  printf("Before allocations:\n");
609  gbm_debug_mem();
610 
611 #if 1
612  static int16_t non_alloc[75]; // 150 byte
613  gbm_put_memblk((char*)non_alloc, sizeof(non_alloc));
614 
615  printf("Added one non-allocated block:\n");
616  gbm_debug_mem();
617 #endif
618 #endif
619 
620  for (int pass = 1; pass <= 2; ++pass) {
621  long allocs = 0;
622 
623  for (size_t size = 10; size<5000; size += size/3) {
624  for (long index = 0; index<3; ++index) {
625  if (pass == 1) {
626  long *block = (long*)gbm_get_mem(size, index);
627 
628  block[0] = size;
629  block[1] = index;
630 
631  blocks[allocs++] = block;
632  }
633  else {
634  long *block = blocks[allocs++];
635  gbm_free_mem(block, (size_t)block[0], block[1]);
636  }
637  }
638  }
639 
640 #if (MEMORY_TEST == 0)
641  if (pass == 1) {
642  printf("%li memory blocks allocated:\n", allocs);
643  gbm_debug_mem();
644  }
645  else {
646  printf("Memory freed:\n");
647  gbm_debug_mem();
648  }
649  printf("Memory flushed:\n");
650  gbm_flush_mem();
651  gbm_debug_mem();
652 #endif
653 
654  gb_assert(allocs == ALLOCS);
655  }
656 
657  GBK_dump_backtrace(stderr, "test");
658 }
659 
660 
661 #endif // UNIT_TESTS
string result
static int getClusterIndex(size_t size)
Definition: admalloc.cxx:307
size_t extern_data_size
Definition: admalloc.cxx:61
bool operator<(const BoundTreeAwarCallbackPtr &bc1, const BoundTreeAwarCallbackPtr &bc2)
gbm_data * gds
Definition: admalloc.cxx:54
#define GBB_MAX_TRIALS
Definition: admalloc.cxx:74
gbm_data * tables[GBM_MAX_TABLES+1]
Definition: admalloc.cxx:58
#define GBB_HEADER_SIZE
Definition: admalloc.cxx:91
static struct gbb_Cluster gbb_cluster[GBB_CLUSTERS+1]
#define GBB_MAGIC
Definition: admalloc.cxx:75
void GB_internal_errorf(const char *templat,...)
Definition: arb_msg.cxx:458
static void imemerr(const char *why)
Definition: admalloc.cxx:302
size_t size
Definition: admalloc.cxx:94
gbm_table * first
Definition: admalloc.cxx:57
class BackTraceInfo * GBK_get_backtrace(size_t skipFramesAtBottom)
Definition: arb_msg.cxx:417
void GBK_dump_former_backtrace(class BackTraceInfo *trace, FILE *out, const char *message)
Definition: arb_msg.cxx:420
#define GBM_MAX_INDEX
Definition: admalloc.cxx:40
size_t allsize
Definition: admalloc.cxx:56
static ARBDB_memory_manager memman
Definition: admalloc.cxx:272
void free_gbm_table(gbm_table *table)
Definition: admalloc.cxx:188
size_t size
Definition: admalloc.cxx:86
gbb_data * first
Definition: admalloc.cxx:95
char * old_sbrk
Definition: admalloc.cxx:66
gbb_freedata content
Definition: admalloc.cxx:88
long allocFromSystem
Definition: admalloc.cxx:87
static bool gbm_mem_initialized
Definition: admalloc.cxx:197
long extern_data_items
Definition: admalloc.cxx:62
#define GBB_CLUSTERS
Definition: admalloc.cxx:71
void * gbmGetMemImpl(size_t size, long index)
Definition: admalloc.cxx:432
long magic
Definition: admalloc.cxx:44
void gbmFreeMemImpl(void *data, size_t size, long index)
Definition: admalloc.cxx:486
void message(char *errortext)
void gbm_debug_mem()
Definition: admalloc.cxx:550
#define GBB_MINSIZE
Definition: admalloc.cxx:73
long useditems[GBM_MAX_TABLES+1]
Definition: admalloc.cxx:60
gbm_data data[1]
Definition: admalloc.cxx:50
size_t size
Definition: admalloc.cxx:55
void * gbm_get_mem(size_t size, long index)
Definition: gb_memory.h:130
long tablecnt[GBM_MAX_TABLES+1]
Definition: admalloc.cxx:59
static struct gbm_pool gbm_pool4idx[GBM_MAX_INDEX]
void gbm_flush_mem()
Definition: admalloc.cxx:199
#define GBM_SYSTEM_PAGE_SIZE
Definition: admalloc.cxx:31
int gb_isMappedMemory(void *mem)
Definition: admap.cxx:725
#define GBM_ALIGNED
Definition: admalloc.cxx:35
#define GBM_TABLE_SIZE
Definition: admalloc.cxx:33
void GB_internal_error(const char *message)
Definition: arb_msg.cxx:435
#define gb_assert(cond)
Definition: arbdbt.h:11
static char * gbm_get_memblk(size_t size)
Definition: admalloc.cxx:365
gbm_table * next
Definition: admalloc.cxx:49
void GBK_free_backtrace(class BackTraceInfo *trace)
Definition: arb_msg.cxx:424
gbb_data * next
Definition: admalloc.cxx:82
#define GBM_MAGIC
Definition: admalloc.cxx:29
void GBK_dump_backtrace(FILE *out, const char *message)
Definition: arb_msg.cxx:428
#define GBM_MAX_SIZE
Definition: admalloc.cxx:39
#define GBB_ALIGN
Definition: admalloc.cxx:72
#define GBB_INCR
Definition: admalloc.cxx:70
static int line
Definition: arb_a2ps.c:296
#define NULp
Definition: cxxforward.h:97
static void gbm_put_memblk(char *memblk, size_t size)
Definition: admalloc.cxx:327
#define GBM_LD_ALIGNED
Definition: admalloc.cxx:36
static ED4_block block
Definition: ED4_block.cxx:73
gbm_data * next
Definition: admalloc.cxx:45
#define GBM_MAX_TABLES
Definition: admalloc.cxx:38
#define TEST()
Definition: admalloc.cxx:296
void gbm_free_mem(void *block, size_t size, long index)
Definition: gb_memory.h:131
void gbm_init_mem()
Definition: admalloc.cxx:220
void alloc_aligned(void **tgt, size_t alignment, size_t len)
Definition: arb_mem.h:30
static struct @3 gbm_global
const char * GB_CSTR
Definition: arbdb_base.h:25