28 #define GBM_MAGIC 0x74732876
30 #define GBM_SYSTEM_PAGE_SIZE 4096 // 4k Tables
31 #define GBM_MALLOC_OVERHEAD 32 // pointer for alloc
32 #define GBM_TABLE_SIZE (GBM_SYSTEM_PAGE_SIZE-GBM_MALLOC_OVERHEAD) // usable size of table
35 #define GBM_LD_ALIGNED 3
37 #define GBM_MAX_TABLES 16 // n different sizes -> max = GBM_MAX_TABLES * GBM_ALIGNED
38 #define GBM_MAX_SIZE (GBM_MAX_TABLES*GBM_ALIGNED)
39 #define GBM_MAX_INDEX 256 // has to be 2 ^ x (with x = GBM_MAX_TABLES ? )
69 #define GBB_INCR 11 // memsize increment in percent between adjacent clusters
70 #define GBB_CLUSTERS 64 // # of different clusters
71 #define GBB_ALIGN GBM_LD_ALIGNED // align memsize of clusters (# of bits)
72 #define GBB_MINSIZE GBM_MAX_SIZE // minimal size of allocated big block
73 #define GBB_MAX_TRIALS 4 // maximal number of clusters to search for an unused block
74 #define GBB_MAGIC 0x67823747
90 #define GBB_HEADER_SIZE (sizeof(gbb_data)-sizeof(gbb_freedata))
101 class AllocLogEntry {
109 AllocLogEntry(
void *block_,
size_t size_,
long index_,
bool do_trace) :
115 AllocLogEntry(
const AllocLogEntry& other) :
125 size_t get_size()
const {
return size; }
126 long get_index()
const {
return index; }
128 bool operator<(
const AllocLogEntry& other)
const {
return block < other.block; }
132 typedef std::set<AllocLogEntry> AllocLogEntries;
135 AllocLogEntries entries;
137 const AllocLogEntry *existingEntry(
void *block) {
138 AllocLogEntries::const_iterator found = entries.find(AllocLogEntry(block, 0, 0,
false));
140 return found == entries.end() ?
NULp : &*found;
147 size_t count = entries.size();
149 fprintf(stderr,
"%zu non-freed blocks:\n", count);
150 AllocLogEntries::const_iterator end = entries.end();
151 for (AllocLogEntries::const_iterator entry = entries.begin(); entry != end; ++entry) {
152 entry->dump(stderr,
"block was allocated from here");
157 void allocated(
void *block,
size_t size,
long index) {
158 const AllocLogEntry *exists = existingEntry(block);
161 exists->dump(stderr,
"Already allocated from here");
164 entries.insert(AllocLogEntry(block, size, index,
true));
167 void freed(
void *block,
size_t size,
long index) {
168 const AllocLogEntry *exists = existingEntry(block);
178 entries.erase(*exists);
183 static AllocLogger allocLogger;
203 bool have_used_items =
false;
207 have_used_items =
true;
212 if (!have_used_items) {
214 memset((
char*)&gbm, 0,
sizeof(gbm));
220 if (!gbm_mem_initialized) {
250 gbm_mem_initialized =
true;
260 #if defined(DUMP_MEMBLKS_AT_EXIT)
261 printf(
"memory at exit:\n");
263 #endif // DUMP_MEMBLKS_AT_EXIT
265 #if defined(DUMP_MEMBLKS_AT_EXIT)
266 printf(
"memory at exit (after flush):\n");
268 #endif // DUMP_MEMBLKS_AT_EXIT
275 #define TEST() testMemblocks(__FILE__, __LINE__)
277 void testMemblocks(
const char *file,
int line) {
286 fprintf(stderr,
"Illegal block (size=%zu) in cluster %i (size=%zu) (%s,%i)\n", blk->
size, idx, cl->
size, file, line);
303 "Inconsistent database: Do not overwrite old files with this database", why);
337 printf(
"put %p (%li bytes)\n", memblk, size);
389 block = (
gbb_data *)ARB_calloc<char>(allocationSize);
397 printf(
"allocated %li bytes\n", size);
404 while ((block=*blockPtr) && block->
size<
size)
407 if (!block)
goto allocFromSys;
413 memset((
char*)&(block->
content), 0, size);
416 printf(
"using unused block "
417 "(add=%p,size=%li, block->size=%li,cluster->size=%li)\n",
428 return (
char*)&(block->
content);
450 result = (
char *)gds;
454 "Do not overwrite old files with this database");
459 if (ggi->
size < nsize) {
470 result = (
char *)ggi->
gds;
476 memset(result, 0, nsize);
480 allocLogger.allocated(erg, size, index);
493 allocLogger.freed(data, size, index);
515 if (block->
size<size) {
imemerr(
"block size does not match");
return; }
547 #endif // MEMORY_TEST==0
556 printf(
"Memory Debug Information:\n");
565 printf(
"\t'I=%3i' 'Size=%3i' * 'Items %4i' = 'size %7i' 'sum=%7li' 'totalsum=%7li' : Free %3i\n",
569 i * GBM_ALIGNED * (
int) ggi->
useditems[i],
578 printf(
"\t'I=%3i' External Data Items=%3li = Sum=%3li 'sum=%7li' 'total=%7li\n",
588 char *topofmem = (
char *)sbrk(0);
589 printf(
"spbrk %lx old %lx size %ti\n",
598 #if defined(UNIT_TESTS) && 0
602 void TEST_ARBDB_memory() {
604 long *blocks[ALLOCS];
606 #if (MEMORY_TEST == 0)
607 printf(
"Before allocations:\n");
611 static int16_t non_alloc[75];
614 printf(
"Added one non-allocated block:\n");
619 for (
int pass = 1; pass <= 2; ++pass) {
622 for (
size_t size = 10; size<5000; size += size/3) {
623 for (
long index = 0; index<3; ++index) {
630 blocks[allocs++] =
block;
633 long *block = blocks[allocs++];
639 #if (MEMORY_TEST == 0)
641 printf(
"%li memory blocks allocated:\n", allocs);
645 printf(
"Memory freed:\n");
648 printf(
"Memory flushed:\n");
static int getClusterIndex(size_t size)
bool operator<(const BoundTreeAwarCallbackPtr &bc1, const BoundTreeAwarCallbackPtr &bc2)
gbm_data * tables[GBM_MAX_TABLES+1]
static struct gbb_Cluster gbb_cluster[GBB_CLUSTERS+1]
void GB_internal_errorf(const char *templat,...)
static void imemerr(const char *why)
class BackTraceInfo * GBK_get_backtrace(size_t skipFramesAtBottom)
void GBK_dump_former_backtrace(class BackTraceInfo *trace, FILE *out, const char *message)
static ARBDB_memory_manager memman
void free_gbm_table(gbm_table *table)
static bool gbm_mem_initialized
void * gbmGetMemImpl(size_t size, long index)
void gbmFreeMemImpl(void *data, size_t size, long index)
void message(char *errortext)
long useditems[GBM_MAX_TABLES+1]
void * gbm_get_mem(size_t size, long index)
long tablecnt[GBM_MAX_TABLES+1]
static struct gbm_pool gbm_pool4idx[GBM_MAX_INDEX]
#define GBM_SYSTEM_PAGE_SIZE
int gb_isMappedMemory(void *mem)
void GB_internal_error(const char *message)
static char * gbm_get_memblk(size_t size)
void GBK_free_backtrace(class BackTraceInfo *trace)
void GBK_dump_backtrace(FILE *out, const char *message)
static void gbm_put_memblk(char *memblk, size_t size)
void gbm_free_mem(void *block, size_t size, long index)
void alloc_aligned(void **tgt, size_t alignment, size_t len)
static struct @3 gbm_global