|
Blender
V2.59
|
00001 /* 00002 * $Id: mallocn.c 36276 2011-04-21 15:53:30Z campbellbarton $ 00003 * ***** BEGIN GPL LICENSE BLOCK ***** 00004 * 00005 * This program is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU General Public License 00007 * as published by the Free Software Foundation; either version 2 00008 * of the License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software Foundation, 00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 * 00019 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00020 * All rights reserved. 00021 * 00022 * The Original Code is: all of this file. 00023 * 00024 * Contributor(s): none yet. 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00041 #include <stdlib.h> 00042 #include <string.h> /* memcpy */ 00043 #include <stdarg.h> 00044 #include <sys/types.h> 00045 /* Blame Microsoft for LLP64 and no inttypes.h, quick workaround needed: */ 00046 #if defined(WIN64) 00047 #define SIZET_FORMAT "%I64u" 00048 #define SIZET_ARG(a) ((unsigned long long)(a)) 00049 #else 00050 #define SIZET_FORMAT "%lu" 00051 #define SIZET_ARG(a) ((unsigned long)(a)) 00052 #endif 00053 00054 /* mmap exception */ 00055 #if defined(WIN32) 00056 #include "mmap_win.h" 00057 #else 00058 #include <sys/mman.h> 00059 #endif 00060 00061 #include "MEM_guardedalloc.h" 00062 00063 /* Only for debugging: 00064 * lets you count the allocations so as to find the allocator of unfreed memory 00065 * in situations where the leak is predictable */ 00066 00067 // #define DEBUG_MEMCOUNTER 00068 00069 #ifdef DEBUG_MEMCOUNTER 00070 #define DEBUG_MEMCOUNTER_ERROR_VAL 0 /* set this to the value that isnt being freed */ 00071 static int _mallocn_count = 0; 00072 00073 /* breakpoint here */ 00074 static void memcount_raise(const char *name) 00075 { 00076 fprintf(stderr, "%s: memcount-leak, %d\n", name, _mallocn_count); 00077 } 00078 #endif 00079 00080 /* --------------------------------------------------------------------- */ 00081 /* Data definition */ 00082 /* --------------------------------------------------------------------- */ 00083 /* all memory chunks are put in linked lists */ 00084 typedef struct localLink 00085 { 00086 struct localLink *next,*prev; 00087 } localLink; 00088 00089 typedef struct localListBase 00090 { 00091 void *first, *last; 00092 } localListBase; 00093 00094 /* note: keep this struct aligned (e.g., irix/gcc) - Hos */ 00095 typedef struct MemHead { 00096 int tag1; 00097 size_t len; 00098 struct MemHead *next,*prev; 00099 const char * name; 00100 const char * nextname; 00101 int tag2; 00102 int mmap; /* if true, memory was mmapped */ 00103 #ifdef DEBUG_MEMCOUNTER 00104 int _count; 00105 #endif 00106 } MemHead; 00107 00108 typedef struct MemTail { 00109 int tag3, pad; 00110 } MemTail; 00111 00112 00113 /* --------------------------------------------------------------------- */ 00114 /* local functions */ 00115 /* --------------------------------------------------------------------- */ 00116 00117 static void addtail(volatile localListBase *listbase, void *vlink); 00118 static void remlink(volatile localListBase *listbase, void *vlink); 00119 static void rem_memblock(MemHead *memh); 00120 static void MemorY_ErroR(const char *block, const char *error); 00121 static const char *check_memlist(MemHead *memh); 00122 00123 /* --------------------------------------------------------------------- */ 00124 /* locally used defines */ 00125 /* --------------------------------------------------------------------- */ 00126 00127 #if defined( __sgi) || defined (__sun) || defined (__sun__) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || (defined (__APPLE__) && !defined(__LITTLE_ENDIAN__)) 00128 #define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) ) 00129 #else 00130 #define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) ) 00131 #endif 00132 00133 #define MEMTAG1 MAKE_ID('M', 'E', 'M', 'O') 00134 #define MEMTAG2 MAKE_ID('R', 'Y', 'B', 'L') 00135 #define MEMTAG3 MAKE_ID('O', 'C', 'K', '!') 00136 #define MEMFREE MAKE_ID('F', 'R', 'E', 'E') 00137 00138 #define MEMNEXT(x) ((MemHead *)(((char *) x) - ((char *) & (((MemHead *)0)->next)))) 00139 00140 /* --------------------------------------------------------------------- */ 00141 /* vars */ 00142 /* --------------------------------------------------------------------- */ 00143 00144 00145 static volatile int totblock= 0; 00146 static volatile uintptr_t mem_in_use= 0, mmap_in_use= 0, peak_mem = 0; 00147 00148 static volatile struct localListBase _membase; 00149 static volatile struct localListBase *membase = &_membase; 00150 static void (*error_callback)(const char *) = NULL; 00151 static void (*thread_lock_callback)(void) = NULL; 00152 static void (*thread_unlock_callback)(void) = NULL; 00153 00154 static int malloc_debug_memset= 0; 00155 00156 #ifdef malloc 00157 #undef malloc 00158 #endif 00159 00160 #ifdef calloc 00161 #undef calloc 00162 #endif 00163 00164 #ifdef free 00165 #undef free 00166 #endif 00167 00168 00169 /* --------------------------------------------------------------------- */ 00170 /* implementation */ 00171 /* --------------------------------------------------------------------- */ 00172 00173 static void print_error(const char *str, ...) 00174 { 00175 char buf[512]; 00176 va_list ap; 00177 00178 va_start(ap, str); 00179 vsnprintf(buf, sizeof(buf), str, ap); 00180 va_end(ap); 00181 buf[sizeof(buf) - 1] = '\0'; 00182 00183 if (error_callback) error_callback(buf); 00184 } 00185 00186 static void mem_lock_thread(void) 00187 { 00188 if (thread_lock_callback) 00189 thread_lock_callback(); 00190 } 00191 00192 static void mem_unlock_thread(void) 00193 { 00194 if (thread_unlock_callback) 00195 thread_unlock_callback(); 00196 } 00197 00198 int MEM_check_memory_integrity(void) 00199 { 00200 const char* err_val = NULL; 00201 MemHead* listend; 00202 /* check_memlist starts from the front, and runs until it finds 00203 * the requested chunk. For this test, that's the last one. */ 00204 listend = membase->last; 00205 00206 err_val = check_memlist(listend); 00207 00208 if (err_val == NULL) return 0; 00209 return 1; 00210 } 00211 00212 00213 void MEM_set_error_callback(void (*func)(const char *)) 00214 { 00215 error_callback = func; 00216 } 00217 00218 void MEM_set_lock_callback(void (*lock)(void), void (*unlock)(void)) 00219 { 00220 thread_lock_callback = lock; 00221 thread_unlock_callback = unlock; 00222 } 00223 00224 void MEM_set_memory_debug(void) 00225 { 00226 malloc_debug_memset= 1; 00227 } 00228 00229 size_t MEM_allocN_len(void *vmemh) 00230 { 00231 if (vmemh) { 00232 MemHead *memh= vmemh; 00233 00234 memh--; 00235 return memh->len; 00236 } else 00237 return 0; 00238 } 00239 00240 void *MEM_dupallocN(void *vmemh) 00241 { 00242 void *newp= NULL; 00243 00244 if (vmemh) { 00245 MemHead *memh= vmemh; 00246 memh--; 00247 00248 if(memh->mmap) 00249 newp= MEM_mapallocN(memh->len, "dupli_mapalloc"); 00250 else 00251 newp= MEM_mallocN(memh->len, "dupli_alloc"); 00252 00253 if (newp == NULL) return NULL; 00254 00255 memcpy(newp, vmemh, memh->len); 00256 } 00257 00258 return newp; 00259 } 00260 00261 void *MEM_reallocN(void *vmemh, size_t len) 00262 { 00263 void *newp= NULL; 00264 00265 if (vmemh) { 00266 MemHead *memh= vmemh; 00267 memh--; 00268 00269 newp= MEM_mallocN(len, memh->name); 00270 if(newp) { 00271 if(len < memh->len) 00272 memcpy(newp, vmemh, len); 00273 else 00274 memcpy(newp, vmemh, memh->len); 00275 } 00276 00277 MEM_freeN(vmemh); 00278 } 00279 00280 return newp; 00281 } 00282 00283 static void make_memhead_header(MemHead *memh, size_t len, const char *str) 00284 { 00285 MemTail *memt; 00286 00287 memh->tag1 = MEMTAG1; 00288 memh->name = str; 00289 memh->nextname = NULL; 00290 memh->len = len; 00291 memh->mmap = 0; 00292 memh->tag2 = MEMTAG2; 00293 00294 memt = (MemTail *)(((char *) memh) + sizeof(MemHead) + len); 00295 memt->tag3 = MEMTAG3; 00296 00297 addtail(membase,&memh->next); 00298 if (memh->next) memh->nextname = MEMNEXT(memh->next)->name; 00299 00300 totblock++; 00301 mem_in_use += len; 00302 00303 peak_mem = mem_in_use > peak_mem ? mem_in_use : peak_mem; 00304 } 00305 00306 void *MEM_mallocN(size_t len, const char *str) 00307 { 00308 MemHead *memh; 00309 00310 mem_lock_thread(); 00311 00312 len = (len + 3 ) & ~3; /* allocate in units of 4 */ 00313 00314 memh= (MemHead *)malloc(len+sizeof(MemHead)+sizeof(MemTail)); 00315 00316 if(memh) { 00317 make_memhead_header(memh, len, str); 00318 mem_unlock_thread(); 00319 if(malloc_debug_memset && len) 00320 memset(memh+1, 255, len); 00321 00322 #ifdef DEBUG_MEMCOUNTER 00323 if(_mallocn_count==DEBUG_MEMCOUNTER_ERROR_VAL) 00324 memcount_raise("MEM_mallocN"); 00325 memh->_count= _mallocn_count++; 00326 #endif 00327 return (++memh); 00328 } 00329 mem_unlock_thread(); 00330 print_error("Malloc returns null: len=" SIZET_FORMAT " in %s, total %u\n", SIZET_ARG(len), str, mem_in_use); 00331 return NULL; 00332 } 00333 00334 void *MEM_callocN(size_t len, const char *str) 00335 { 00336 MemHead *memh; 00337 00338 mem_lock_thread(); 00339 00340 len = (len + 3 ) & ~3; /* allocate in units of 4 */ 00341 00342 memh= (MemHead *)calloc(len+sizeof(MemHead)+sizeof(MemTail),1); 00343 00344 if(memh) { 00345 make_memhead_header(memh, len, str); 00346 mem_unlock_thread(); 00347 #ifdef DEBUG_MEMCOUNTER 00348 if(_mallocn_count==DEBUG_MEMCOUNTER_ERROR_VAL) 00349 memcount_raise("MEM_callocN"); 00350 memh->_count= _mallocn_count++; 00351 #endif 00352 return (++memh); 00353 } 00354 mem_unlock_thread(); 00355 print_error("Calloc returns null: len=" SIZET_FORMAT " in %s, total %u\n", SIZET_ARG(len), str, mem_in_use); 00356 return NULL; 00357 } 00358 00359 /* note; mmap returns zero'd memory */ 00360 void *MEM_mapallocN(size_t len, const char *str) 00361 { 00362 MemHead *memh; 00363 00364 mem_lock_thread(); 00365 00366 len = (len + 3 ) & ~3; /* allocate in units of 4 */ 00367 00368 #ifdef __sgi 00369 { 00370 #include <fcntl.h> 00371 00372 int fd; 00373 fd = open("/dev/zero", O_RDWR); 00374 00375 memh= mmap(0, len+sizeof(MemHead)+sizeof(MemTail), 00376 PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 00377 close(fd); 00378 } 00379 #else 00380 memh= mmap(NULL, len+sizeof(MemHead)+sizeof(MemTail), 00381 PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0); 00382 #endif 00383 00384 if(memh!=(MemHead *)-1) { 00385 make_memhead_header(memh, len, str); 00386 memh->mmap= 1; 00387 mmap_in_use += len; 00388 peak_mem = mmap_in_use > peak_mem ? mmap_in_use : peak_mem; 00389 mem_unlock_thread(); 00390 #ifdef DEBUG_MEMCOUNTER 00391 if(_mallocn_count==DEBUG_MEMCOUNTER_ERROR_VAL) 00392 memcount_raise("MEM_mapallocN"); 00393 memh->_count= _mallocn_count++; 00394 #endif 00395 return (++memh); 00396 } 00397 else { 00398 mem_unlock_thread(); 00399 print_error("Mapalloc returns null, fallback to regular malloc: len=" SIZET_FORMAT " in %s, total %u\n", SIZET_ARG(len), str, mmap_in_use); 00400 return MEM_callocN(len, str); 00401 } 00402 } 00403 00404 /* Memory statistics print */ 00405 typedef struct MemPrintBlock { 00406 const char *name; 00407 uintptr_t len; 00408 int items; 00409 } MemPrintBlock; 00410 00411 static int compare_name(const void *p1, const void *p2) 00412 { 00413 const MemPrintBlock *pb1= (const MemPrintBlock*)p1; 00414 const MemPrintBlock *pb2= (const MemPrintBlock*)p2; 00415 00416 return strcmp(pb1->name, pb2->name); 00417 } 00418 00419 static int compare_len(const void *p1, const void *p2) 00420 { 00421 const MemPrintBlock *pb1= (const MemPrintBlock*)p1; 00422 const MemPrintBlock *pb2= (const MemPrintBlock*)p2; 00423 00424 if(pb1->len < pb2->len) 00425 return 1; 00426 else if(pb1->len == pb2->len) 00427 return 0; 00428 else 00429 return -1; 00430 } 00431 00432 void MEM_printmemlist_stats() 00433 { 00434 MemHead *membl; 00435 MemPrintBlock *pb, *printblock; 00436 int totpb, a, b; 00437 00438 mem_lock_thread(); 00439 00440 /* put memory blocks into array */ 00441 printblock= malloc(sizeof(MemPrintBlock)*totblock); 00442 00443 pb= printblock; 00444 totpb= 0; 00445 00446 membl = membase->first; 00447 if (membl) membl = MEMNEXT(membl); 00448 00449 while(membl) { 00450 pb->name= membl->name; 00451 pb->len= membl->len; 00452 pb->items= 1; 00453 00454 totpb++; 00455 pb++; 00456 00457 if(membl->next) 00458 membl= MEMNEXT(membl->next); 00459 else break; 00460 } 00461 00462 /* sort by name and add together blocks with the same name */ 00463 qsort(printblock, totpb, sizeof(MemPrintBlock), compare_name); 00464 for(a=0, b=0; a<totpb; a++) { 00465 if(a == b) { 00466 continue; 00467 } 00468 else if(strcmp(printblock[a].name, printblock[b].name) == 0) { 00469 printblock[b].len += printblock[a].len; 00470 printblock[b].items++; 00471 } 00472 else { 00473 b++; 00474 memcpy(&printblock[b], &printblock[a], sizeof(MemPrintBlock)); 00475 } 00476 } 00477 totpb= b+1; 00478 00479 /* sort by length and print */ 00480 qsort(printblock, totpb, sizeof(MemPrintBlock), compare_len); 00481 printf("\ntotal memory len: %.3f MB\n", (double)mem_in_use/(double)(1024*1024)); 00482 printf(" ITEMS TOTAL-MiB AVERAGE-KiB TYPE\n"); 00483 for(a=0, pb=printblock; a<totpb; a++, pb++) 00484 printf("%6d (%8.3f %8.3f) %s\n", pb->items, (double)pb->len/(double)(1024*1024), (double)pb->len/1024.0/(double)pb->items, pb->name); 00485 00486 free(printblock); 00487 00488 mem_unlock_thread(); 00489 00490 #if 0 /* GLIBC only */ 00491 malloc_stats(); 00492 #endif 00493 } 00494 00495 /* Prints in python syntax for easy */ 00496 static void MEM_printmemlist_internal( int pydict ) 00497 { 00498 MemHead *membl; 00499 00500 mem_lock_thread(); 00501 00502 membl = membase->first; 00503 if (membl) membl = MEMNEXT(membl); 00504 00505 if (pydict) { 00506 print_error("# membase_debug.py\n"); 00507 print_error("membase = [\\\n"); 00508 } 00509 while(membl) { 00510 if (pydict) { 00511 fprintf(stderr, "{'len':" SIZET_FORMAT ", 'name':'''%s''', 'pointer':'%p'},\\\n", SIZET_ARG(membl->len), membl->name, (void *)(membl+1)); 00512 } else { 00513 #ifdef DEBUG_MEMCOUNTER 00514 print_error("%s len: " SIZET_FORMAT " %p, count: %d\n", membl->name, SIZET_ARG(membl->len), membl+1, membl->_count); 00515 #else 00516 print_error("%s len: " SIZET_FORMAT " %p\n", membl->name, SIZET_ARG(membl->len), membl+1); 00517 #endif 00518 } 00519 if(membl->next) 00520 membl= MEMNEXT(membl->next); 00521 else break; 00522 } 00523 if (pydict) { 00524 fprintf(stderr, "]\n\n"); 00525 fprintf(stderr, 00526 "mb_userinfo = {}\n" 00527 "totmem = 0\n" 00528 "for mb_item in membase:\n" 00529 "\tmb_item_user_size = mb_userinfo.setdefault(mb_item['name'], [0,0])\n" 00530 "\tmb_item_user_size[0] += 1 # Add a user\n" 00531 "\tmb_item_user_size[1] += mb_item['len'] # Increment the size\n" 00532 "\ttotmem += mb_item['len']\n" 00533 "print '(membase) items:', len(membase), '| unique-names:', len(mb_userinfo), '| total-mem:', totmem\n" 00534 "mb_userinfo_sort = mb_userinfo.items()\n" 00535 "for sort_name, sort_func in (('size', lambda a: -a[1][1]), ('users', lambda a: -a[1][0]), ('name', lambda a: a[0])):\n" 00536 "\tprint '\\nSorting by:', sort_name\n" 00537 "\tmb_userinfo_sort.sort(key = sort_func)\n" 00538 "\tfor item in mb_userinfo_sort:\n" 00539 "\t\tprint 'name:%%s, users:%%i, len:%%i' %% (item[0], item[1][0], item[1][1])\n" 00540 ); 00541 } 00542 00543 mem_unlock_thread(); 00544 } 00545 00546 void MEM_callbackmemlist(void (*func)(void*)) { 00547 MemHead *membl; 00548 00549 mem_lock_thread(); 00550 00551 membl = membase->first; 00552 if (membl) membl = MEMNEXT(membl); 00553 00554 while(membl) { 00555 func(membl+1); 00556 if(membl->next) 00557 membl= MEMNEXT(membl->next); 00558 else break; 00559 } 00560 00561 mem_unlock_thread(); 00562 } 00563 00564 short MEM_testN(void *vmemh) { 00565 MemHead *membl; 00566 00567 mem_lock_thread(); 00568 00569 membl = membase->first; 00570 if (membl) membl = MEMNEXT(membl); 00571 00572 while(membl) { 00573 if (vmemh == membl+1) { 00574 mem_unlock_thread(); 00575 return 1; 00576 } 00577 00578 if(membl->next) 00579 membl= MEMNEXT(membl->next); 00580 else break; 00581 } 00582 00583 mem_unlock_thread(); 00584 00585 print_error("Memoryblock %p: pointer not in memlist\n", vmemh); 00586 return 0; 00587 } 00588 00589 void MEM_printmemlist( void ) { 00590 MEM_printmemlist_internal(0); 00591 } 00592 void MEM_printmemlist_pydict( void ) { 00593 MEM_printmemlist_internal(1); 00594 } 00595 00596 short MEM_freeN(void *vmemh) /* anders compileertie niet meer */ 00597 { 00598 short error = 0; 00599 MemTail *memt; 00600 MemHead *memh= vmemh; 00601 const char *name; 00602 00603 if (memh == NULL){ 00604 MemorY_ErroR("free","attempt to free NULL pointer"); 00605 /* print_error(err_stream, "%d\n", (memh+4000)->tag1); */ 00606 return(-1); 00607 } 00608 00609 if(sizeof(intptr_t)==8) { 00610 if (((intptr_t) memh) & 0x7) { 00611 MemorY_ErroR("free","attempt to free illegal pointer"); 00612 return(-1); 00613 } 00614 } 00615 else { 00616 if (((intptr_t) memh) & 0x3) { 00617 MemorY_ErroR("free","attempt to free illegal pointer"); 00618 return(-1); 00619 } 00620 } 00621 00622 memh--; 00623 if(memh->tag1 == MEMFREE && memh->tag2 == MEMFREE) { 00624 MemorY_ErroR(memh->name,"double free"); 00625 return(-1); 00626 } 00627 00628 mem_lock_thread(); 00629 if ((memh->tag1 == MEMTAG1) && (memh->tag2 == MEMTAG2) && ((memh->len & 0x3) == 0)) { 00630 memt = (MemTail *)(((char *) memh) + sizeof(MemHead) + memh->len); 00631 if (memt->tag3 == MEMTAG3){ 00632 00633 memh->tag1 = MEMFREE; 00634 memh->tag2 = MEMFREE; 00635 memt->tag3 = MEMFREE; 00636 /* after tags !!! */ 00637 rem_memblock(memh); 00638 00639 mem_unlock_thread(); 00640 00641 return(0); 00642 } 00643 error = 2; 00644 MemorY_ErroR(memh->name,"end corrupt"); 00645 name = check_memlist(memh); 00646 if (name != NULL){ 00647 if (name != memh->name) MemorY_ErroR(name,"is also corrupt"); 00648 } 00649 } else{ 00650 error = -1; 00651 name = check_memlist(memh); 00652 if (name == NULL) 00653 MemorY_ErroR("free","pointer not in memlist"); 00654 else 00655 MemorY_ErroR(name,"error in header"); 00656 } 00657 00658 totblock--; 00659 /* here a DUMP should happen */ 00660 00661 mem_unlock_thread(); 00662 00663 return(error); 00664 } 00665 00666 /* --------------------------------------------------------------------- */ 00667 /* local functions */ 00668 /* --------------------------------------------------------------------- */ 00669 00670 static void addtail(volatile localListBase *listbase, void *vlink) 00671 { 00672 struct localLink *link= vlink; 00673 00674 if (link == NULL) return; 00675 if (listbase == NULL) return; 00676 00677 link->next = NULL; 00678 link->prev = listbase->last; 00679 00680 if (listbase->last) ((struct localLink *)listbase->last)->next = link; 00681 if (listbase->first == NULL) listbase->first = link; 00682 listbase->last = link; 00683 } 00684 00685 static void remlink(volatile localListBase *listbase, void *vlink) 00686 { 00687 struct localLink *link= vlink; 00688 00689 if (link == NULL) return; 00690 if (listbase == NULL) return; 00691 00692 if (link->next) link->next->prev = link->prev; 00693 if (link->prev) link->prev->next = link->next; 00694 00695 if (listbase->last == link) listbase->last = link->prev; 00696 if (listbase->first == link) listbase->first = link->next; 00697 } 00698 00699 static void rem_memblock(MemHead *memh) 00700 { 00701 remlink(membase,&memh->next); 00702 if (memh->prev) { 00703 if (memh->next) 00704 MEMNEXT(memh->prev)->nextname = MEMNEXT(memh->next)->name; 00705 else 00706 MEMNEXT(memh->prev)->nextname = NULL; 00707 } 00708 00709 totblock--; 00710 mem_in_use -= memh->len; 00711 00712 if(memh->mmap) { 00713 mmap_in_use -= memh->len; 00714 if (munmap(memh, memh->len + sizeof(MemHead) + sizeof(MemTail))) 00715 printf("Couldn't unmap memory %s\n", memh->name); 00716 } 00717 else { 00718 if(malloc_debug_memset && memh->len) 00719 memset(memh+1, 255, memh->len); 00720 free(memh); 00721 } 00722 } 00723 00724 static void MemorY_ErroR(const char *block, const char *error) 00725 { 00726 print_error("Memoryblock %s: %s\n",block, error); 00727 } 00728 00729 static const char *check_memlist(MemHead *memh) 00730 { 00731 MemHead *forw,*back,*forwok,*backok; 00732 const char *name; 00733 00734 forw = membase->first; 00735 if (forw) forw = MEMNEXT(forw); 00736 forwok = NULL; 00737 while(forw){ 00738 if (forw->tag1 != MEMTAG1 || forw->tag2 != MEMTAG2) break; 00739 forwok = forw; 00740 if (forw->next) forw = MEMNEXT(forw->next); 00741 else forw = NULL; 00742 } 00743 00744 back = (MemHead *) membase->last; 00745 if (back) back = MEMNEXT(back); 00746 backok = NULL; 00747 while(back){ 00748 if (back->tag1 != MEMTAG1 || back->tag2 != MEMTAG2) break; 00749 backok = back; 00750 if (back->prev) back = MEMNEXT(back->prev); 00751 else back = NULL; 00752 } 00753 00754 if (forw != back) return ("MORE THAN 1 MEMORYBLOCK CORRUPT"); 00755 00756 if (forw == NULL && back == NULL){ 00757 /* geen foute headers gevonden dan maar op zoek naar memblock*/ 00758 00759 forw = membase->first; 00760 if (forw) forw = MEMNEXT(forw); 00761 forwok = NULL; 00762 while(forw){ 00763 if (forw == memh) break; 00764 if (forw->tag1 != MEMTAG1 || forw->tag2 != MEMTAG2) break; 00765 forwok = forw; 00766 if (forw->next) forw = MEMNEXT(forw->next); 00767 else forw = NULL; 00768 } 00769 if (forw == NULL) return NULL; 00770 00771 back = (MemHead *) membase->last; 00772 if (back) back = MEMNEXT(back); 00773 backok = NULL; 00774 while(back){ 00775 if (back == memh) break; 00776 if (back->tag1 != MEMTAG1 || back->tag2 != MEMTAG2) break; 00777 backok = back; 00778 if (back->prev) back = MEMNEXT(back->prev); 00779 else back = NULL; 00780 } 00781 } 00782 00783 if (forwok) name = forwok->nextname; 00784 else name = "No name found"; 00785 00786 if (forw == memh){ 00787 /* voor alle zekerheid wordt dit block maar uit de lijst gehaald */ 00788 if (forwok){ 00789 if (backok){ 00790 forwok->next = (MemHead *)&backok->next; 00791 backok->prev = (MemHead *)&forwok->next; 00792 forwok->nextname = backok->name; 00793 } else{ 00794 forwok->next = NULL; 00795 membase->last = (struct localLink *) &forwok->next; 00796 /* membase->last = (struct Link *) &forwok->next; */ 00797 } 00798 } else{ 00799 if (backok){ 00800 backok->prev = NULL; 00801 membase->first = &backok->next; 00802 } else{ 00803 membase->first = membase->last = NULL; 00804 } 00805 } 00806 } else{ 00807 MemorY_ErroR(name,"Additional error in header"); 00808 return("Additional error in header"); 00809 } 00810 00811 return(name); 00812 } 00813 00814 uintptr_t MEM_get_peak_memory(void) 00815 { 00816 uintptr_t _peak_mem; 00817 00818 mem_lock_thread(); 00819 _peak_mem = peak_mem; 00820 mem_unlock_thread(); 00821 00822 return _peak_mem; 00823 } 00824 00825 void MEM_reset_peak_memory(void) 00826 { 00827 mem_lock_thread(); 00828 peak_mem = 0; 00829 mem_unlock_thread(); 00830 } 00831 00832 uintptr_t MEM_get_memory_in_use(void) 00833 { 00834 uintptr_t _mem_in_use; 00835 00836 mem_lock_thread(); 00837 _mem_in_use= mem_in_use; 00838 mem_unlock_thread(); 00839 00840 return _mem_in_use; 00841 } 00842 00843 uintptr_t MEM_get_mapped_memory_in_use(void) 00844 { 00845 uintptr_t _mmap_in_use; 00846 00847 mem_lock_thread(); 00848 _mmap_in_use= mmap_in_use; 00849 mem_unlock_thread(); 00850 00851 return _mmap_in_use; 00852 } 00853 00854 int MEM_get_memory_blocks_in_use(void) 00855 { 00856 int _totblock; 00857 00858 mem_lock_thread(); 00859 _totblock= totblock; 00860 mem_unlock_thread(); 00861 00862 return _totblock; 00863 } 00864 00865 #ifndef NDEBUG 00866 const char *MEM_name_ptr(void *vmemh) 00867 { 00868 if (vmemh) { 00869 MemHead *memh= vmemh; 00870 memh--; 00871 return memh->name; 00872 } 00873 else { 00874 return "MEM_name_ptr(NULL)"; 00875 } 00876 } 00877 #endif 00878 00879 /* eof */