📄 gdk_utils.c
字号:
if (stackBat == NULL) return GDK_FAIL; BBPrename(memBat->batCacheid, "mem_trace"); BBPrename(stackBat->batCacheid, "mem_stack"); memBat->hsorted = memBat->tsorted = 0; BATkey(memBat, TRUE); stackBat->hsorted = stackBat->tsorted = 0; BATset(stackBat, TRUE); } mtrace++; } else if (mtrace > 0) mtrace--; memBat->batDirty = TRUE; stackBat->batDirty = TRUE; if (*enable == bit_nil) { printf("testing mtrace:\n"); mtrace_test(); --mtrace; } return GDK_SUCCEED;}BUNadd_dag(BAT *b, BUN p, mem_t current, mem_t parent){ const static int bunsize = sizeof(mem_t) + sizeof(mem_t); BUN last = BUNlast(b); while (p != last) { if ((*(mem_t *) BUNhloc(b, p)) == current && (*(mem_t *) BUNtloc(b, p)) == parent) return p; p += bunsize; } if (b->batBuns->free + bunsize > b->batBuns->size) { int tmp = mtrace; mtrace = 0; if (BATextend(b, BATgrows(b)) == NULL) return BUNlast(b); mtrace = tmp; last = BUNlast(b); } bunfastins_nocheck(b, last, ¤t, &parent, bunsize); return last;}#define MAX_STACK_ADDR 16#define STACK_LIST(STACK_ENTRY) \ STACK_ENTRY(1) STACK_ENTRY(2) STACK_ENTRY(3) \ STACK_ENTRY(4) STACK_ENTRY(5) STACK_ENTRY(6) STACK_ENTRY(7) \ STACK_ENTRY(8) STACK_ENTRY(9) STACK_ENTRY(10) STACK_ENTRY(11) \ STACK_ENTRY(12) STACK_ENTRY(13) STACK_ENTRY(14) STACK_ENTRY(15)#define STACK_READ(X) \ if (continue_stack_trace && \ ((mem_t)__builtin_frame_address((X)) != 0L) && \ ((X) < MAX_STACK_ADDR)) { \ parent = current; \ current = (mem_t)__builtin_return_address((X)); \ if(parent) \ p = add_dag(b, p, current, parent); \ } else if (continue_stack_trace) { \ continue_stack_trace = FALSE; \ }intadd_stack(BAT *b){ mem_t current = 0, parent = 0; bit continue_stack_trace = TRUE; BUN p = BUNfirst(b); STACK_LIST(STACK_READ); return BUNindex(b, p);}#define __USE_GNU 1#include <dlfcn.h>voidprint_address(ptr address){ Dl_info dlip; char *filename; dladdr(address, &dlip); filename = 0; /* strrchr(dlip.dli_fname,'/'); */ printf(PTRFMT "\t%s\t%s\n", PTRFMTCAST address, dlip.dli_sname, filename ? filename + 1 : dlip.dli_fname);}static intGDKmprint(int *pidx){ int idx = *pidx; BUN p = BUNptr(stackBat, idx), first = BUNfirst(stackBat); const static int bunsize = sizeof(mem_t) + sizeof(mem_t); mem_t *a; if (p == NULL) printf("No stack for index %d\n", idx); a = (mem_t *) BUNhloc(stackBat, p); print_address(*a); a = (mem_t *) BUNtloc(stackBat, p); print_address(*a); while (p > first) { p -= bunsize; if (*(mem_t *) BUNhloc(stackBat, p) == *a) { a = (mem_t *) BUNtloc(stackBat, p); print_address(*a); } } return GDK_SUCCEED;}voidadd_mem(BAT *b, mem_t mem, int idx){ REGISTER BUN last; const static int bunsize = sizeof(mem_t) + sizeof(int); if (b->batBuns->free + bunsize > b->batBuns->size) { int tmp = mtrace; mtrace = 0; if (BATextend(b, BATgrows(b))) return; mtrace = tmp; } last = BUNlast(b); bunfastins_nocheck(b, last, &mem, &idx, bunsize);}voiddel_mem(BAT *b, mem_t mem){ REGISTER BUN first = BUNfirst(b), p = BUNlast(b); const static int bunsize = sizeof(mem_t) + sizeof(int); for (p -= bunsize; p >= first; p -= bunsize) { if (*(mem_t *) BUNhloc(b, p) == mem) { int idx = -*(int *) BUNtloc(b, p); if (idx > 0) { printf("Double deletion of memory " PTRFMT ", " "size: " SSZFMT ", stack:%d\n", PTRFMTCAST(void *)mem, ((ssize_t *) mem)[-1], idx); if (mtrace > 1) GDKmprint(&idx); } else { BUNdelete(b, p); /* BUNinplace(b,p,&mem,&idx,0); */ } return; } } printf("Free of unknown memory " PTRFMT ", size: " SSZFMT "\n", PTRFMTCAST(void *) mem, ((ssize_t *) mem)[-1]);}#endif#line 898 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_utils.mx"#line 950 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_utils.mx"static voidGDKmemfail(str s, size_t len, size_t memtarget, size_t vmtarget){ int bak = GDKdebug; /* bumped your nose against the wall; try to prevent repetition by adjusting maxsizes */ if (memtarget < 0.3 * GDKmem_inuse()) { size_t newmax = (size_t) (0.7 * (double) GDKmem_inuse()); if (newmax < GDK_mem_maxsize) GDK_mem_maxsize = newmax; } if (vmtarget < 0.3 * GDKvm_cursize()) { size_t newmax = (size_t) (0.7 * (double) GDKvm_cursize()); if (newmax < GDK_vm_maxsize) GDK_vm_maxsize = newmax; } gdk_set_lock(GDKthreadLock, "GDKmemfail"); THRprintf(GDKout, "#%s(" SZFMT ") fail => BBPtrim(enter) usage[mem=" SZFMT ",vm=" SZFMT "]\n", s, len, GDKmem_inuse(), GDKvm_cursize()); GDKmemdump(); GDKdebug |= 4; gdk_unset_lock(GDKthreadLock, "GDKmemfail"); BBPtrim(memtarget, vmtarget); gdk_set_lock(GDKthreadLock, "GDKmemfail"); GDKdebug = MIN(GDKdebug, bak); THRprintf(GDKout, "#%s(" SZFMT ") fail => BBPtrim(ready) usage[mem=" SZFMT ",vm=" SZFMT "]\n", s, len, GDKmem_inuse(), GDKvm_cursize()); GDKmemdump(); gdk_unset_lock(GDKthreadLock, "GDKmemfail");}/* the blocksize is stored in the ssize_t before it. Negative size <=> VM memory */#define GDK_MEM_BLKSIZE(p) ((ssize_t*) (p))[-1]#ifndef GDK_MEM_MISALIGN/* allocate 8 bytes extra (so it stays 8-bytes aligned) and put realsize in front */#define GDKmalloc_prefixsize(s,size) { \ s = (ssize_t *) malloc(size + 8); \ if (s != NULL) { \ assert((((size_t) s)&7) == 0); /* no MISALIGN */ \ s = (ssize_t*) ((char*) s + 8); \ s[-1] = (ssize_t) (size + 8); \ } \}#else/* work around old stupid libc mallocs that give 4-byte aligned pointers */#define GDKmalloc_prefixsize(s,size) { \ s = (ssize_t *) malloc(size+8); \ if (((size_t) s) & 4) { /* misaligned */ \ assert(sizeof(size_t) == 4); /* not on 64-bits */ \ s = (ssize_t*) ((char*) s + 4); \ s[-1] = (ssize_t) (size + 9); /* 1-bit is a marker */ \ } else if (s != NULL) { \ s = (ssize_t*) ((char*) s + 8); \ s[-1] = (ssize_t) (size + 8); \ } \}#endifvoid *GDKmallocmax(size_t size, size_t * maxsize, int emergency){ ssize_t *s = NULL; if (size == 0) {#ifdef GDK_MEM_NULLALLOWED return NULL;#else GDKfatal("GDKmallocmax: called with size " SZFMT "", size);#endif } size = (size + 3) & ~3; /* round up to a multiple of four */ if (size > GDK_mem_bigsize) { size_t newsize = size + sizeof(size_t) + sizeof(size_t); size_t newmax = MAX(*maxsize, newsize); s = (ssize_t *) GDKvmalloc(newsize, &newmax, emergency); if (s == 0 && emergency == 0) return s; MT_alloc_register(s, *maxsize, 'S'); s += 2; s[-2] = (ssize_t) newmax; s[-1] = -((ssize_t) newsize); *maxsize = newmax - (sizeof(size_t) + sizeof(size_t)); return (void *) s; } CHKMEM(size, 0); GDKmalloc_prefixsize(s, size); if (s == NULL) { GDKmemfail("GDKmalloc", size, BBPTRIM_ALL, 0); GDKmalloc_prefixsize(s, size); if (s == NULL) { if (emergency) return NULL; MT_alloc_print(); GDKfatal("GDKmallocmax: failed for %u bytes", size); } else { THRprintf(GDKout, "#GDKmallocmax: recovery ok. Continuing..\n"); } } *maxsize = size; #line 515 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_utils.mx" { size_t _memdelta = (size_t) size+8;#ifdef GDK_MEM_TRACE void* _blk = (void*) s; if (mtrace) { int _idx = add_stack(stackBat); add_mem(memBat,_blk,_idx); }#endif GDK_mallocedbytes_estimate += _memdelta;#ifdef GDK_MEM_KEEPHISTO { int _idx; GDKmallidx(_idx, _memdelta); GDK_nmallocs[_idx]++; }#endif }#line 1057 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_utils.mx" return (void *) s;}void *GDKmalloc(size_t size){ return GDKmallocmax(size, &size, 1);}void *GDKzalloc(size_t size){ size_t maxsize; void *p = GDKmallocmax(size, &maxsize, 1); if (p) memset(p,0,size); return p;}voidGDKfree(void *blk){ ssize_t size = 0, *s = (ssize_t *) blk; if (s == NULL) return; size = GDK_MEM_BLKSIZE(s); /* check against duplicate free */ assert((size & 2) == 0); s[-1] |= 2; if (size < 0) { size_t maxsize = (size_t) s[-2]; size = -size; MT_alloc_register((char *) (s - 2), maxsize, 's'); GDKvmfree((char *) (s - 2), (size_t) size, maxsize); } else {#ifndef NDEBUG /* The check above detects obvious duplicate free's, * but fails in case the "check-bit" is cleared between * two free's (e.g., as the respective memory has been * re-allocated and initialized. * To simplify detection & debugging of duplicate free's, * we now overwrite the to be freed memory, which will * (1) trigger a segfault in case the memory had already * been freed and/or trigger some error in case the memory * is accessed after is has been freed. * To avoid performance penalty in the "production version", * we only do this in debugging/development mode (i.e., * when configured with --enable-assert). * Disable at runtime via `Mserver --debug=33554432` or * `debugmask(or(debugmask(),33554432));` in MIL. */ DEADBEEFCHK memset(s,0xDB,size - (8 + (size & 1))); /* 0xDeadBeef */#endif#ifdef GDK_MEM_MISALIGN if (size & 1) free(((char *) s) - 4); else#endif free(((char *) s) - 8); #line 537 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_utils.mx" { size_t _memdelta = (size_t) size;#ifdef GDK_MEM_TRACE void* _blk = (void*) s; if (mtrace) { del_mem(memBat,_blk); }#endif if (_memdelta > GDK_mallocedbytes_estimate) { /* clearly, the stats are off: it should never become less-than-zero */ GDKmem_heapcheck(GDKms()); } else { GDK_mallocedbytes_estimate -= _memdelta; }#ifdef GDK_MEM_KEEPHISTO { int _idx; GDKmallidx(_idx, _memdelta); GDK_nmallocs[_idx]--; }#endif }#line 1122 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_utils.mx" }}ptrGDKreallocmax(void *blk, size_t size, size_t * maxsize, int emergency){ ssize_t oldsize = 0, *s = (ssize_t *) blk; if (s == NULL) { return GDKmallocmax(size, maxsize, emergency); }#ifdef GDK_MEM_NULLALLOWED if (size == 0) { GDKfree(blk); *maxsize = 0; return NULL; }#endif if (size <= 0) { GDKfatal("GDKreallocmax: called with size %u", size); } /* round up to a multiple of four */ size = (size + 3) & ~3; oldsize = GDK_MEM_BLKSIZE(s); /* check against duplicate free */ assert((oldsize & 2) == 0); if (oldsize < 0) { size_t newsize = size + sizeof(size_t) + sizeof(size_t); size_t oldmax = (size_t) s[-2]; size_t newmax = MAX(*maxsize, newsize); s = (ssize_t *) GDKvmrealloc((ptr) (s - 2), (size_t) - oldsize, newsize, oldmax, &newmax, emergency); if (s == NULL && !emergency) return NULL; s[0] = newmax; s[1] = -((ssize_t) newsize); *maxsize = newmax - (sizeof(size_t) + sizeof(size_t)); return (ptr) (s + 2); }#ifndef GDK_MEM_MISALIGN if (size <= GDK_mem_bigsize) { size_t newsize = size + 8; blk = realloc(((char *) blk) - 8, newsize); if (blk != NULL) { /* place 8 bytes before it */ assert((((size_t) blk) & 4) == 0); blk = ((char *) blk) + 8; ((ssize_t *) blk)[-1] = (ssize_t) newsize; /* adapt statistics */ #line 515 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_utils.mx" { size_t _memdelta = (size_t) newsize;#ifdef GDK_MEM_TRACE void* _blk = (void*) blk; if (mtrace) { int _idx = add_stack(stackBat); add_mem(memBat,_blk,_idx); }#endif GDK_mallocedbytes_estimate += _memdelta;#ifdef GDK_MEM_KEEPHISTO { int _idx; GDKmallidx(_idx, _memdelta); GDK_nmallocs[_idx]++; }#endif }#line 1176 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_utils.mx" #line 537 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_utils.mx" { size_t _memdelta = (size_t) oldsize;#ifdef GDK_MEM_TRACE void* _blk = (void*) s; if (mtrace) { del_mem(memBat,_blk); }#endif if (_memdelta > GDK_mallocedbytes_estimate) { /* clearly, the stats are off: it should never become less-than-zero */ GDKmem_heapcheck(GDKms()); } else { GDK_mallocedbytes_estimate -= _memdelta; }#ifdef GDK_MEM_KEEPHISTO { int _idx; GDKmallidx(_idx, _memdelta); GDK_nmallocs[_idx]--; }#endif }#line 1177 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_utils.mx" *maxsize = size; return blk; } } /* alloc© due too failed realloc (may be very big heap that needs vm) */#else /* alloc© because we cannot trust realloc due to misalignment */ if (oldsize & 1) oldsize = MIN(size, (size_t) oldsize - 5); else#endif oldsize = MIN(size, (size_t) (oldsize - 8)); blk = (void *) GDKmallocmax(size, maxsize, emergency); if (blk) { memcpy(blk, s, oldsize); GDKfree(s); } return (void *) blk;}ptrGDKrealloc(void *blk, size_t size){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -