#include"OVHeap.h" #ifndef OV_JENARIX #ifdef OVHeap_TRACKING /* all of the code in this module is only used when OVHeap_TRACKING is * active otherwise, OVHeap is simply a Macro-wrapper around stdlib's * memory management routines */ #define OVHeap_SORT #define OVHeap_ERROR_LOG stderr static void HandleOutOfMemory(void) { fprintf(OVHeap_ERROR_LOG,"OVHeap-Error: *************************************************\n"); fprintf(OVHeap_ERROR_LOG,"OVHeap-Error: *** EEK! This program just ran out of memory! ***\n"); fprintf(OVHeap_ERROR_LOG,"OVHeap-Error: *************************************************\n"); fflush(OVHeap_ERROR_LOG); #ifdef OVHeap_ABORT_ON_ERROR OVHeap_Dump(false); abort(); #endif } static void HandleError(void) { fprintf(OVHeap_ERROR_LOG,"OVHeap-Error: *************************************************\n"); fprintf(OVHeap_ERROR_LOG,"OVHeap-Error: *** EEK! Memory corruption may have occurred! ***\n"); fprintf(OVHeap_ERROR_LOG,"OVHeap-Error: *************************************************\n"); fflush(OVHeap_ERROR_LOG); #ifdef OVHeap_ABORT_ON_ERROR OVHeap_Dump(false); abort(); #endif } typedef struct DebugRec { struct DebugRec *next; char file[32], note[64]; int line; ov_size size; int type; } DebugRec; #define HASH(x) ((x>>11)&0x3FF) struct _OVHeap { DebugRec *HashTable[1024]; int Count; int MaxCount; }; OVHeap *_OVHeap_New(void) { OVHeap *I = ov_os_calloc(1,sizeof(OVHeap)); return I; } void _OVHeap_Del(OVHeap *I) { #ifndef OV_JENARIX #ifdef OVHeap_TRACKING OVHeap_Dump(I,0); #endif #endif ov_os_free((void*)I); } int OVHeap_Usage(OVHeap *I) { int a; unsigned int tot = 0; DebugRec *rec; for(a=0;a<1024;a++) { rec=I->HashTable[a]; while(rec) { tot+=rec->size; rec=rec->next; } } return(tot); } typedef char OutputLine[1280]; typedef struct { void *p; char text[1280]; } DebugOutput; static int OutputInOrder(DebugOutput *output,int line1,int line2) { return(output[line1].p <= output[line2].p); } static void OVHeap_SortOutput(int n,DebugOutput *array,int *x) { int l,a,r,t,i; if(n<1) return; else if(n==1) { x[0]=0; return; } x--; for(a=1;a<=n;a++) x[a]=a; l=(n>>1)+1; r=n; while(1) { if(l>1) t = x[--l]; else { t = x[r]; x[r] = x[1]; if( --r == 1) { x[1] = t; break; } } i=l; a=l << 1; while (a <= r) { if (a < r && (!OutputInOrder(array,x[a+1]-1,x[a]-1))) a++; if (!OutputInOrder(array,x[a]-1,t-1)) { x[i] = x[a]; a += (i=a); } else a = r + 1; } x[i] = t; } x++; for(a=0;a<n;a++) x[a]--; } void OVHeap_Dump(OVHeap *I,ov_uint32 flags) { int a; int cnt=0; unsigned int tot = 0; DebugRec *rec; char type[]="FV"; #ifdef OVHeap_SORT DebugOutput *output; int *index; #endif #ifdef OVHeap_SORT for(a=0;a<1024;a++) { rec=I->HashTable[a]; while(rec) { rec=rec->next; cnt++; } } output = (DebugOutput*)malloc(cnt*sizeof(DebugOutput)); index = (int*)malloc(cnt*sizeof(int)); cnt = 0; #endif fprintf(OVHeap_ERROR_LOG,"================================= HEAP =================================\n"); fflush(OVHeap_ERROR_LOG); for(a=0;a<1024;a++) { rec=I->HashTable[a]; while(rec) { { tot+=rec->size; if(flags&OVHeap_DUMP_NO_ADDRESSES) { #ifdef OVHeap_SORT output[cnt].p=rec; sprintf(output[cnt].text, #else fprintf(OVHeap_ERROR_LOG, #endif "OVHeap: (%7x) %c %s",(unsigned int) rec->size,type[rec->type],rec->file); } else { #ifdef OVHeap_SORT output[cnt].p=rec; sprintf(output[cnt].text, #else fprintf(OVHeap_ERROR_LOG, #endif "OVHeap:%8x -%8x (%7x) %c %s:%-4d", (unsigned int)rec+1, (unsigned int)((char*)(rec+1)+rec->size), (unsigned int) rec->size,type[rec->type],rec->file,rec->line); } if(flags&OVHeap_DUMP_FILES_TOO) { FILE *f; int line = rec->line; char buffer[1024],*c; f=fopen(rec->file,"r"); while(line--) fgets(buffer,2048,f); c=buffer; while(*c && *c<33) c++; #ifdef OVHeap_SORT strcat(output[cnt].text,c); #else fprintf(OVHeap_ERROR_LOG,"%s",c); #endif fclose(f); } else { #ifdef OVHeap_SORT strcat(output[cnt].text,"\n"); #else fprintf(OVHeap_ERROR_LOG,"\n"); #endif } } rec=rec->next; cnt++; } } #ifdef OVHeap_SORT OVHeap_SortOutput(cnt,output,index); for(a=0;a<cnt;a++) { fprintf(OVHeap_ERROR_LOG,"%s",output[index[a]].text); } #endif fprintf(OVHeap_ERROR_LOG,"OVHeap: Summary: Blocks expected %d, found %d, peaked at %d.\n", I->Count,cnt,I->MaxCount); fprintf(OVHeap_ERROR_LOG,"OVHeap: Summary: Total bytes allocated 0x%x (%0.3f MB).\n",tot,tot/(1024.0*1024)); fprintf(OVHeap_ERROR_LOG,"========================================================================\n"); fflush(OVHeap_ERROR_LOG); } static void OVHeap_HashAdd(OVHeap *I,DebugRec *rec) { int hash; hash=(int)rec; hash=HASH(hash); rec->next=I->HashTable[hash]; I->HashTable[hash]=rec; } static DebugRec *OVHeap_HashRemove(OVHeap *I,void *ptr) { DebugRec *rec,*cur,*last; int hash; rec=(DebugRec*)ptr; rec--; hash=(int)rec; hash=HASH(hash); last=NULL; cur=I->HashTable[hash]; while(cur) { if(cur==rec) { if(last) last->next=cur->next; else I->HashTable[hash]=cur->next; break; } last=cur; cur=cur->next; } return(cur); } /* Ustatus OVHeap_Wrap(Ustatus input,void **ptrptr,char *file, int line, int type) { DebugRec *rec,*cur; int hash; rec=(DebugRec*)(*ptrptr); rec--; hash=(int)rec; hash=HASH(hash); cur=I->HashTable[hash]; while(cur) { if(cur==rec) { strcpy(rec->file,file); rec->line=line; rec->type=type; break; } cur=cur->next; } return input; } */ void *_OVHeap_Malloc(OVHeap *I,ov_size size,const char *file,int line,int type) { DebugRec *rec; rec=(DebugRec*)malloc(sizeof(DebugRec)+size); if(!rec) { if(size) { fprintf(OVHeap_ERROR_LOG,"OVHeap_Malloc-Error: malloc failed %lu.\n",(unsigned long)size); HandleOutOfMemory(); } } else { strcpy(rec->file,file); rec->line=line; rec->size=size; rec->type=type; OVHeap_HashAdd(I,rec); rec++; I->Count++; if(I->MaxCount<I->Count) I->MaxCount=I->Count; } return((void *) rec); } void *_OVHeap_Calloc(OVHeap *I,ov_size num,ov_size size, const char *file,int line,int type) { DebugRec *rec; rec=(DebugRec*)calloc(1,sizeof(DebugRec)+size*num); if(!rec) { if(size) { fprintf(OVHeap_ERROR_LOG,"OVHeap_Malloc-Error: calloc failed %lu x %lu.\n", (unsigned long)size,(unsigned long)num); HandleOutOfMemory(); } } else { strcpy(rec->file,file); rec->line=line; rec->size=size*num; rec->type=type; OVHeap_HashAdd(I,rec); rec++; I->Count++; if(I->MaxCount<I->Count) I->MaxCount=I->Count; } return((void *) rec); } void *_OVHeap_Realloc(OVHeap *I,void *ptr,ov_size size, const char *file,int line,int type) { DebugRec *rec,*new_rec; if(!ptr) return(_OVHeap_Malloc(I,size,file,line,type)); else { rec=OVHeap_HashRemove(I,ptr); if(!rec) { fprintf(OVHeap_ERROR_LOG, "OVHeap_Realloc-Error: realloc() corrupted heap or bad ptr! (%s:%i @%p)\n", file,line,ptr); #ifdef OVHeap_ABORT_ON_ERROR OVHeap_Dump(false); abort(); #endif HandleError(); } else if(rec->type!=type) { fprintf(OVHeap_ERROR_LOG,"OVHeap_Realloc-Error: ptr %p of wrong type: %i!=%i (%s:%i)\n", ptr,rec->type,type,file,line); #ifdef OVHeap_ABORT_ON_ERROR OVHeap_Dump(false); abort(); #endif HandleError(); } else { new_rec=(DebugRec*)realloc(rec,size+sizeof(DebugRec)); if(!new_rec) { fprintf(OVHeap_ERROR_LOG,"OVHeap_Realloc-Error: realloc() failed! (%s:%i)\n", file,line); HandleOutOfMemory(); OVHeap_HashAdd(I,rec); /* put it back */ rec++; } else { rec=new_rec; OVHeap_HashAdd(I,rec); rec->size=size; rec++; return((void*)rec); } } } return(NULL); } void _OVHeap_Free(OVHeap *I,void *ptr,const char *file,int line,int type) { DebugRec *rec; if(!ptr) { fprintf(OVHeap_ERROR_LOG,"OVHeap_Free-Error: free() called with NULL pointer (%s:%i)\n", file,line); #ifdef OVHeap_ABORT_ON_ERROR OVHeap_Dump(false); abort(); #endif HandleError(); } rec=OVHeap_HashRemove(I,ptr); if(rec) { if(rec->type!=type) { fprintf(OVHeap_ERROR_LOG,"OVHeap_Free-Error: ptr %p type mismatch: %i!=%i (%s:%i)\n", ptr,rec->type,type,file,line); #ifdef OVHeap_ABORT_ON_ERROR OVHeap_Dump(false); abort(); #endif HandleError(); } free(rec); } else { fprintf(OVHeap_ERROR_LOG, "OVHeap_Free-Error: free(): corrupted tree or bad ptr! (%s:%i @%p)\n", file,line,ptr); HandleError(); } I->Count--; } #endif #endif