diff --git a/src/pike_memory.c b/src/pike_memory.c index e00e4e814d28e382df234eb64daa779220e789cf..f560b7545a88055b19b5172ce9cc79d7f7972893 100644 --- a/src/pike_memory.c +++ b/src/pike_memory.c @@ -452,32 +452,38 @@ static MUTEX_T debug_malloc_mutex; #undef strdup #undef main -static void add_location(struct memhdr *mh, const char *fn, int line); +static void add_location(struct memhdr *mh, int locnum); static struct memhdr *find_memhdr(void *p); +#include "block_alloc.h" + int verbose_debug_malloc = 0; int verbose_debug_exit = 1; -#define BSIZE 16382 -#define HSIZE 65599 -#define LHSIZE 133153 +#define HSIZE 1109891 +#define LHSIZE 1109891 +#define FLSIZE 8803 -struct memloc +struct fileloc { - struct memloc *next; - const char *filename; - struct memhdr *mh; + struct fileloc *next; + const char *file; int line; - int times; + int number; }; +BLOCK_ALLOC(fileloc, 4090) -struct memloc_block +struct memloc { - struct memloc_block *next; - struct memloc memlocs[BSIZE]; + struct memloc *next; + struct memhdr *mh; + int locnum; + int times; }; +BLOCK_ALLOC(memloc, 16382) + struct memhdr { struct memhdr *next; @@ -486,60 +492,59 @@ struct memhdr struct memloc *locations; }; - -struct memhdr_block -{ - struct memhdr_block *next; - struct memhdr memhdrs[BSIZE]; -}; - -static struct memloc_block *memloc_blocks=0; -static struct memloc *free_memlocs=0; -static struct memhdr no_leak_memlocs; - +static struct fileloc *flhash[FLSIZE]; static struct memloc *mlhash[LHSIZE]; static struct memhdr *hash[HSIZE]; -static struct memhdr_block *memhdr_blocks=0; -static struct memhdr *free_memhdrs=0; +static struct memhdr no_leak_memlocs; +static int file_location_number=0; -struct memhdr *alloc_memhdr(void) +static int location_number(const char *file, int line) { - struct memhdr *tmp; - if(!free_memhdrs) + struct fileloc *f,**prev; + unsigned long h=(long)file; + h*=4711; + h+=line; + h%=FLSIZE; + for(prev=flhash+h;(f=*prev);prev=&f->next) { - struct memhdr_block *n; - int e; - n=(struct memhdr_block *)malloc(sizeof(struct memhdr_block)); - if(!n) + if(f->line == line && f->file == file) { - fprintf(stderr,"Fatal: out of memory.\n"); - verbose_debug_exit=0; - exit(17); - } - n->next=memhdr_blocks; - memhdr_blocks=n; - - for(e=0;e<BSIZE;e++) - { - n->memhdrs[e].next=free_memhdrs; - free_memhdrs=n->memhdrs+e; + *prev=f->next; + f->next=flhash[h]; + flhash[h]=f; + return f->number; } } - tmp=free_memhdrs; - tmp->locations=0; - free_memhdrs=tmp->next; - return tmp; + f=alloc_fileloc(); + f->line=line; + f->file=file; + f->number=++file_location_number; + f->next=flhash[h]; + flhash[h]=f; + return f->number; +} + +static struct fileloc *find_file_location(int locnum) +{ + int e; + struct fileloc *r; + for(e=0;e<FLSIZE;e++) + for(r=flhash[e];r;r=r->next) + if(r->number == locnum) + return r; + fprintf(stderr,"Internal error in DEBUG_MALLOC, failed to find location.\n"); + exit(127); } void low_add_marks_to_memhdr(struct memhdr *to, - struct memhdr *from) + struct memhdr *from) { struct memloc *l; if(!from) return; for(l=from->locations;l;l=l->next) - add_location(to, l->filename, l->line); + add_location(to, l->locnum); } void add_marks_to_memhdr(struct memhdr *to, void *ptr) @@ -547,132 +552,119 @@ void add_marks_to_memhdr(struct memhdr *to, void *ptr) low_add_marks_to_memhdr(to,find_memhdr(ptr)); } -static unsigned long lhash(struct memhdr *m, - const char *fn, - int line) +static inline unsigned long lhash(struct memhdr *m, int locnum) { unsigned long l; l=(long)m; l*=53; - l+=(long)fn; - l*=4711; - l+=line; + l+=locnum; l%=LHSIZE; return l; } -void free_memhdr(struct memhdr *mh) -{ - struct memloc *ml; - while((ml=mh->locations)) - { - unsigned long l=lhash(mh,ml->filename, ml->line); - if(mlhash[l]==ml) mlhash[l]=0; - - mh->locations=ml->next; - ml->next=free_memlocs; - free_memlocs=ml; - } - mh->next=free_memhdrs; - free_memhdrs=mh; -} +#undef INIT_BLOCK +#undef EXIT_BLOCK -static struct memloc *alloc_memloc(void) -{ - struct memloc *tmp; - if(!free_memlocs) - { - struct memloc_block *n; - int e; - n=(struct memloc_block *)malloc(sizeof(struct memloc_block)); - if(!n) - { - fprintf(stderr,"Fatal: out of memory.\n"); - verbose_debug_exit=0; - exit(17); - } - n->next=memloc_blocks; - memloc_blocks=n; +#define INIT_BLOCK(X) X->locations=0 +#define EXIT_BLOCK(X) do { \ + struct memloc *ml; \ + while((ml=X->locations)) \ + { \ + unsigned long l=lhash(X,ml->locnum); \ + if(mlhash[l]==ml) mlhash[l]=0; \ + \ + X->locations=ml->next; \ + free_memloc(ml); \ + } \ +}while(0) - for(e=0;e<BSIZE;e++) - { - n->memlocs[e].next=free_memlocs; - free_memlocs=n->memlocs+e; - } - } +BLOCK_ALLOC(memhdr,16382) + +#undef INIT_BLOCK +#undef EXIT_BLOCK + +#define INIT_BLOCK(X) +#define EXIT_BLOCK(X) - tmp=free_memlocs; - free_memlocs=tmp->next; - return tmp; -} static struct memhdr *find_memhdr(void *p) { - struct memhdr *mh; + struct memhdr *mh,**prev; unsigned long h=(long)p; h%=HSIZE; - for(mh=hash[h]; mh; mh=mh->next) + for(prev=hash+h; (mh=*prev); prev=&mh->next) + { if(mh->data==p) + { + *prev=mh->next; + mh->next=hash[h]; + hash[h]=mh; return mh; + } + } return NULL; } -static void add_location(struct memhdr *mh, const char *fn, int line) +static int find_location(struct memhdr *mh, int locnum) { struct memloc *ml; - unsigned long l=lhash(mh,fn,line); + unsigned long l=lhash(mh,locnum); if(mlhash[l] && mlhash[l]->mh==mh && - mlhash[l]->filename==fn && - mlhash[l]->line==line) - return; + mlhash[l]->locnum==locnum) + return 1; for(ml=mh->locations;ml;ml=ml->next) - if(ml->filename==fn && ml->line==line) - break; - - if(!ml) { - ml=alloc_memloc(); - ml->line=line; - ml->filename=fn; - ml->next=mh->locations; - ml->times++; - ml->mh=mh; - mh->locations=ml; + if(ml->locnum==locnum) + { + mlhash[l]=ml; + return 1; + } } - mlhash[l]=ml; + return 0; } -static int find_location(struct memhdr *mh, const char *fn, int line) +static void add_location(struct memhdr *mh, int locnum) { struct memloc *ml; - unsigned long l=lhash(mh,fn,line); + unsigned long l; - if(mlhash[l] && - mlhash[l]->mh==mh && - mlhash[l]->filename==fn && - mlhash[l]->line==line) - return 1; +#if DEBUG_MALLOC - 0 < 2 + if(find_location(&no_leak_memlocs, locnum)) return; +#endif + + l=lhash(mh,locnum); + + if(mlhash[l] && mlhash[l]->mh==mh && mlhash[l]->locnum==locnum) + { + mlhash[l]->times++; + return; + } for(ml=mh->locations;ml;ml=ml->next) + if(ml->locnum==locnum) + break; + + if(!ml) { - if(ml->filename==fn && ml->line==line) - { - mlhash[l]=ml; - return 1; - } + ml=alloc_memloc(); + ml->locnum=locnum; + ml->next=mh->locations; + ml->mh=mh; + mh->locations=ml; } - return 0; + ml->times++; + mlhash[l]=ml; } -static void make_memhdr(void *p, int s, const char *fn, int line) +static void make_memhdr(void *p, int s, int locnum) { struct memhdr *mh=alloc_memhdr(); struct memloc *ml=alloc_memloc(); - unsigned long l=lhash(mh,fn,line); + unsigned long l=lhash(mh,locnum); unsigned long h=(long)p; h%=HSIZE; @@ -680,8 +672,7 @@ static void make_memhdr(void *p, int s, const char *fn, int line) mh->data=p; mh->size=s; mh->locations=ml; - ml->filename=fn; - ml->line=line; + ml->locnum=locnum; ml->next=0; ml->times=1; hash[h]=mh; @@ -710,9 +701,12 @@ static int remove_memhdr(void *p) void *debug_malloc(size_t s, const char *fn, int line) { void *m; + mt_lock(&debug_malloc_mutex); + m=malloc(s); - if(m) make_memhdr(m, s, fn, line); + if(m) + make_memhdr(m, s, location_number(fn,line)); if(verbose_debug_malloc) fprintf(stderr, "malloc(%d) => %p (%s:%d)\n", s, m, fn, line); @@ -725,10 +719,11 @@ void *debug_malloc(size_t s, const char *fn, int line) void *debug_calloc(size_t a, size_t b, const char *fn, int line) { void *m; + int locnum; mt_lock(&debug_malloc_mutex); m=calloc(a, b); - if(m) make_memhdr(m, a*b, fn, line); + if(m) make_memhdr(m, a*b, location_number(fn,line)); if(verbose_debug_malloc) fprintf(stderr, "calloc(%d,%d) => %p (%s:%d)\n", a, b, m, fn, line); @@ -744,7 +739,7 @@ void *debug_realloc(void *p, size_t s, const char *fn, int line) m=realloc(p, s); if(m) { if(p) remove_memhdr(p); - make_memhdr(m, s, fn, line); + make_memhdr(m, s, location_number(fn,line)); } if(verbose_debug_malloc) fprintf(stderr, "realloc(%p,%d) => %p (%s:%d)\n", p, s, m, fn,line); @@ -768,7 +763,7 @@ char *debug_strdup(const char *s, const char *fn, int line) mt_lock(&debug_malloc_mutex); m=strdup(s); - if(m) make_memhdr(m, strlen(s)+1, fn, line); + if(m) make_memhdr(m, strlen(s)+1, location_number(fn,line)); if(verbose_debug_malloc) fprintf(stderr, "strdup(\"%s\") => %p (%s:%d)\n", s, m, fn, line); @@ -783,9 +778,12 @@ void dump_memhdr_locations(struct memhdr *from, struct memloc *l; for(l=from->locations;l;l=l->next) { - if(find_location(notfrom, l->filename, l->line)) + struct fileloc *f; + if(notfrom && find_location(notfrom, l->locnum)) continue; - fprintf(stderr," *** %s:%d (%d times)\n",l->filename,l->line,l->times); + + f=find_file_location(l->locnum); + fprintf(stderr," *** %s:%d (%d times)\n",f->file,f->line,l->times); } } @@ -807,16 +805,18 @@ void cleanup_memhdrs() fprintf(stderr,"\n"); first=0; } + fprintf(stderr, "LEAK: (%p) %d bytes\n",m->data, m->size); for(l=m->locations;l;l=l->next) + { + struct fileloc *f=find_file_location(l->locnum); fprintf(stderr," *** %s:%d (%d times) %s\n", - l->filename, - l->line, + f->file, + f->line, l->times, - find_location(&no_leak_memlocs, - l->filename, - l->line) ? "" : " *"); + find_location(&no_leak_memlocs, l->locnum) ? "" : " *"); + } } } } @@ -837,7 +837,7 @@ void * debug_malloc_update_location(void *p,const char *fn, int line) { struct memhdr *mh; if((mh=find_memhdr(p))) - add_location(mh, fn, line); + add_location(mh, location_number(fn,line)); } return p; }