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