Changeset 1360 for trunk/psLib/src/sys/psMemory.c
- Timestamp:
- Jul 30, 2004, 4:28:29 PM (22 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/sys/psMemory.c (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/sys/psMemory.c
r1240 r1360 1 1 /** @file psMemory.c 2 *3 * @brief Contains the definitions for the memory management system4 *5 * psMemory.h has additional information and documentation of the routines found in this file.6 *7 * @author Robert DeSonia, MHPCC8 * @author Robert Lupton, Princeton University9 *10 * @version $Revision: 1.29$ $Name: not supported by cvs2svn $11 * @date $Date: 2004-07-19 20:45:53$12 *13 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii14 */2 * 3 * @brief Contains the definitions for the memory management system 4 * 5 * psMemory.h has additional information and documentation of the routines found in this file. 6 * 7 * @author Robert DeSonia, MHPCC 8 * @author Robert Lupton, Princeton University 9 * 10 * @version $Revision: 1.30 $ $Name: not supported by cvs2svn $ 11 * @date $Date: 2004-07-31 02:28:10 $ 12 * 13 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii 14 */ 15 15 16 16 #define PS_ALLOW_MALLOC // we're allowed to call malloc() … … 30 30 #define P_PS_LARGE_BLOCK_SIZE 65536 // size where under, we try to recycle 31 31 32 static int checkMemBlock( const psMemBlock *m, const char* funcName);32 static int checkMemBlock( const psMemBlock *m, const char* funcName ); 33 33 static psMemBlock *lastMemBlockAllocated = NULL; 34 34 static pthread_mutex_t memBlockListMutex = PTHREAD_MUTEX_INITIALIZER; … … 38 38 39 39 static int recycleBins = 13; 40 static int recycleBinSize[14] = {8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,P_PS_LARGE_BLOCK_SIZE}; 40 static int recycleBinSize[ 14 ] = 41 { 42 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, P_PS_LARGE_BLOCK_SIZE 43 }; 41 44 // N.B. recycleBinSize should be terminated by P_PS_LARGE_BLOCK_SIZE (simplifies search loops) 42 static psMemBlock* recycleMemBlockList[13] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; 43 45 static psMemBlock* recycleMemBlockList[ 13 ] = 46 { 47 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL 48 }; 49 44 50 #ifdef PS_MEM_DEBUG 45 51 static psMemBlock* deadBlockList; // a place to put dead memBlocks in debug mode. … … 53 59 * Default memExhausted callback. 54 60 */ 55 static void *memExhaustedCallbackDefault( size_t size)56 { 57 void * ptr = NULL;58 59 pthread_mutex_lock( &recycleMemBlockListMutex);60 int level =recycleBins-1;61 while ( level >= 0 && ptr == NULL) {62 while (recycleMemBlockList[level] != NULL && ptr == NULL) {63 psMemBlock* old = recycleMemBlockList[level];64 recycleMemBlockList[level] = recycleMemBlockList[level]->nextBlock;65 free(old);66 ptr = malloc(size);67 }68 level--;69 }70 pthread_mutex_unlock( &recycleMemBlockListMutex);71 61 static void *memExhaustedCallbackDefault( size_t size ) 62 { 63 void * ptr = NULL; 64 65 pthread_mutex_lock( &recycleMemBlockListMutex ); 66 int level = recycleBins - 1; 67 while ( level >= 0 && ptr == NULL ) { 68 while ( recycleMemBlockList[ level ] != NULL && ptr == NULL ) { 69 psMemBlock * old = recycleMemBlockList[ level ]; 70 recycleMemBlockList[ level ] = recycleMemBlockList[ level ] ->nextBlock; 71 free( old ); 72 ptr = malloc( size ); 73 } 74 level--; 75 } 76 pthread_mutex_unlock( &recycleMemBlockListMutex ); 77 72 78 return ptr; 73 79 } … … 75 81 static psMemExhaustedCallback memExhaustedCallback = memExhaustedCallbackDefault; 76 82 77 psMemExhaustedCallback psMemExhaustedCallbackSet( psMemExhaustedCallback func)83 psMemExhaustedCallback psMemExhaustedCallbackSet( psMemExhaustedCallback func ) 78 84 { 79 85 psMemExhaustedCallback old = memExhaustedCallback; 80 81 if ( func != NULL) {82 memExhaustedCallback = func;83 } else {84 memExhaustedCallback = memExhaustedCallbackDefault;85 }86 86 87 if ( func != NULL ) { 88 memExhaustedCallback = func; 89 } else { 90 memExhaustedCallback = memExhaustedCallbackDefault; 91 } 92 87 93 return old; 88 94 } 89 95 90 static void memProblemCallbackDefault( const psMemBlock *ptr,91 const char *file, int lineno)92 { 93 if ( ptr->refCounter < 1) {94 psError(__func__,95 "Block %ld allocated at %s:%d freed more than once at %s:%d\n",96 ptr->id, ptr->file, ptr->lineno, file, lineno);97 }98 99 if ( lineno > 0) {100 psAbort(__func__, "Detected a problem in the memory system at %s:%d", file, lineno);101 }96 static void memProblemCallbackDefault( const psMemBlock *ptr, 97 const char *file, int lineno ) 98 { 99 if ( ptr->refCounter < 1 ) { 100 psError( __func__, 101 "Block %ld allocated at %s:%d freed more than once at %s:%d\n", 102 ptr->id, ptr->file, ptr->lineno, file, lineno ); 103 } 104 105 if ( lineno > 0 ) { 106 psAbort( __func__, "Detected a problem in the memory system at %s:%d", file, lineno ); 107 } 102 108 } 103 109 static psMemProblemCallback memProblemCallback = memProblemCallbackDefault; 104 110 105 psMemProblemCallback psMemProblemCallbackSet( psMemProblemCallback func)111 psMemProblemCallback psMemProblemCallbackSet( psMemProblemCallback func ) 106 112 { 107 113 psMemProblemCallback old = memProblemCallback; 108 109 if ( func != NULL) {110 memProblemCallback = func;111 } else {112 memProblemCallback = memProblemCallbackDefault;113 }114 114 115 if ( func != NULL ) { 116 memProblemCallback = func; 117 } else { 118 memProblemCallback = memProblemCallbackDefault; 119 } 120 115 121 return old; 116 122 } … … 123 129 psMemoryId p_psMemFreeID = 0; // notify user this block is freed 124 130 125 psMemoryId psMemAllocateCallbackSetID( psMemoryId id)131 psMemoryId psMemAllocateCallbackSetID( psMemoryId id ) 126 132 { 127 133 psMemoryId old = p_psMemAllocateID; 128 134 p_psMemAllocateID = id; 129 135 130 136 return old; 131 137 } 132 138 133 psMemoryId psMemFreeCallbackSetID( psMemoryId id)139 psMemoryId psMemFreeCallbackSetID( psMemoryId id ) 134 140 { 135 141 psMemoryId old = p_psMemFreeID; 136 142 p_psMemFreeID = id; 137 143 138 144 return old; 139 145 } … … 145 151 * isn't resignalled) 146 152 */ 147 static psMemoryId memAllocateCallbackDefault( const psMemBlock *ptr)153 static psMemoryId memAllocateCallbackDefault( const psMemBlock *ptr ) 148 154 { 149 155 static psMemoryId incr = 0; // "p_psMemAllocateID += incr" 150 156 151 157 return incr; 152 158 } 153 159 154 static psMemoryId memFreeCallbackDefault( const psMemBlock *ptr)160 static psMemoryId memFreeCallbackDefault( const psMemBlock *ptr ) 155 161 { 156 162 static psMemoryId incr = 0; // "p_psMemFreeID += incr" 157 163 158 164 return incr; 159 165 } … … 165 171 static psMemFreeCallback memFreeCallback = memFreeCallbackDefault; 166 172 167 psMemAllocateCallback psMemAllocateCallbackSet( psMemAllocateCallback func)173 psMemAllocateCallback psMemAllocateCallbackSet( psMemAllocateCallback func ) 168 174 { 169 175 psMemFreeCallback old = memAllocateCallback; 170 171 if ( func != NULL) {172 memAllocateCallback =func;173 } else {174 memAllocateCallback = memAllocateCallbackDefault;175 }176 176 177 if ( func != NULL ) { 178 memAllocateCallback = func; 179 } else { 180 memAllocateCallback = memAllocateCallbackDefault; 181 } 182 177 183 return old; 178 184 } 179 185 180 psMemFreeCallback psMemFreeCallbackSet( psMemFreeCallback func)186 psMemFreeCallback psMemFreeCallbackSet( psMemFreeCallback func ) 181 187 { 182 188 psMemFreeCallback old = memFreeCallback; 183 184 if ( func != NULL) {185 memFreeCallback = func;186 } else {187 memFreeCallback = memFreeCallbackDefault;188 }189 189 190 if ( func != NULL ) { 191 memFreeCallback = func; 192 } else { 193 memFreeCallback = memFreeCallbackDefault; 194 } 195 190 196 return old; 191 197 } … … 194 200 * Return memory ID counter for next block to be allocated 195 201 */ 196 psMemoryId psMemGetId( void)202 psMemoryId psMemGetId( void ) 197 203 { 198 204 psMemoryId id; 199 pthread_mutex_lock( &memIdMutex);205 pthread_mutex_lock( &memIdMutex ); 200 206 id = memid + 1; 201 pthread_mutex_unlock( &memIdMutex);202 207 pthread_mutex_unlock( &memIdMutex ); 208 203 209 return id; 204 210 } … … 210 216 */ 211 217 212 static int checkMemBlock( const psMemBlock *m, const char* funcName)218 static int checkMemBlock( const psMemBlock *m, const char* funcName ) 213 219 { 214 220 // n.b. since this is called by psMemCheckCorruption while the memblock list is mutex locked, 215 221 // we shouldn't call such things as p_psAlloc/p_psFree here. 216 217 if ( m == NULL) {218 psError(funcName,"Memory Corruption: NULL memory block found.");219 return 1;220 }221 222 if ( m->refCounter == 0) {223 // using an unreferenced block of memory, are you?224 psError(__func__,"Memory Corruption: memory block %ld was freed but still used.",225 m->id);226 return 1;227 }228 229 if ( m->startblock != P_PS_MEMMAGIC || m->endblock != P_PS_MEMMAGIC) {230 psError(funcName, "Memory Corruption: memory block %ld is corrupted (buffer underflow)",231 m->id);232 return 1;233 }234 if ( *(void**)((int8_t*)(m+1)+m->userMemorySize) != P_PS_MEMMAGIC) {235 psError(funcName, "Memory Corruption: memory block %ld is corrupted (buffer overflow)",236 m->id);237 return 1;238 }239 222 223 if ( m == NULL ) { 224 psError( funcName, "Memory Corruption: NULL memory block found." ); 225 return 1; 226 } 227 228 if ( m->refCounter == 0 ) { 229 // using an unreferenced block of memory, are you? 230 psError( __func__, "Memory Corruption: memory block %ld was freed but still used.", 231 m->id ); 232 return 1; 233 } 234 235 if ( m->startblock != P_PS_MEMMAGIC || m->endblock != P_PS_MEMMAGIC ) { 236 psError( funcName, "Memory Corruption: memory block %ld is corrupted (buffer underflow)", 237 m->id ); 238 return 1; 239 } 240 if ( *( void** ) ( ( int8_t* ) ( m + 1 ) + m->userMemorySize ) != P_PS_MEMMAGIC ) { 241 psError( funcName, "Memory Corruption: memory block %ld is corrupted (buffer overflow)", 242 m->id ); 243 return 1; 244 } 245 240 246 return 0; 241 247 } 242 248 243 int psMemCheckCorruption( bool abort_on_error)249 int psMemCheckCorruption( bool abort_on_error ) 244 250 { 245 251 int nbad = 0; // number of bad blocks 246 252 247 253 // get exclusive access to the memBlock list to avoid it changing on us while we use it. 248 pthread_mutex_lock( &memBlockListMutex);249 250 for ( psMemBlock* iter=lastMemBlockAllocated; iter != NULL; iter=iter->nextBlock) {251 if (checkMemBlock(iter, __func__)) {252 nbad++;253 254 memProblemCallback(iter, __func__, __LINE__);255 256 if (abort_on_error) {257 // release the lock on the memblock list258 pthread_mutex_unlock(&memBlockListMutex);259 psAbort(__func__, "Detected memory corruption");260 return nbad;261 }262 }263 }264 254 pthread_mutex_lock( &memBlockListMutex ); 255 256 for ( psMemBlock * iter = lastMemBlockAllocated; iter != NULL; iter = iter->nextBlock ) { 257 if ( checkMemBlock( iter, __func__ ) ) { 258 nbad++; 259 260 memProblemCallback( iter, __func__, __LINE__ ); 261 262 if ( abort_on_error ) { 263 // release the lock on the memblock list 264 pthread_mutex_unlock( &memBlockListMutex ); 265 psAbort( __func__, "Detected memory corruption" ); 266 return nbad; 267 } 268 } 269 } 270 265 271 // release the lock on the memblock list 266 pthread_mutex_unlock( &memBlockListMutex);272 pthread_mutex_unlock( &memBlockListMutex ); 267 273 return nbad; 268 274 } 269 275 270 void *p_psAlloc( size_t size, const char *file, int lineno)271 { 272 273 psMemBlock * ptr = NULL;274 276 void *p_psAlloc( size_t size, const char *file, int lineno ) 277 { 278 279 psMemBlock * ptr = NULL; 280 275 281 // memory is of the size I want to bother recycling? 276 if ( size < P_PS_LARGE_BLOCK_SIZE) {277 // find the bin we need.278 int level = 0;279 while (size > recycleBinSize[level]) {280 level++;281 }282 // Are we in one of the bins283 if (level<recycleBins) {284 285 size = recycleBinSize[level]; // round-up size to next sized bin.286 287 pthread_mutex_lock(&recycleMemBlockListMutex);288 289 if (recycleMemBlockList[level] != NULL) {290 ptr = recycleMemBlockList[level];291 recycleMemBlockList[level] = ptr->nextBlock;292 if (recycleMemBlockList[level] != NULL) {293 recycleMemBlockList[level]->previousBlock = NULL;294 }295 size = ptr->userMemorySize;296 }297 298 pthread_mutex_unlock(&recycleMemBlockListMutex);299 }300 }301 302 if ( ptr == NULL) {303 ptr = malloc(sizeof(psMemBlock) + size + sizeof(void*));304 305 if (ptr == NULL) {306 ptr = memExhaustedCallback(size);307 if (ptr == NULL) {308 psAbort(__func__, "Failed to allocate %u bytes at %s:%d",309 size, file, lineno);310 }311 }312 313 ptr->startblock = P_PS_MEMMAGIC;314 ptr->endblock = P_PS_MEMMAGIC;315 ptr->userMemorySize = size;316 pthread_mutex_init(&ptr->refCounterMutex, NULL);317 }318 282 if ( size < P_PS_LARGE_BLOCK_SIZE ) { 283 // find the bin we need. 284 int level = 0; 285 while ( size > recycleBinSize[ level ] ) { 286 level++; 287 } 288 // Are we in one of the bins 289 if ( level < recycleBins ) { 290 291 size = recycleBinSize[ level ]; // round-up size to next sized bin. 292 293 pthread_mutex_lock( &recycleMemBlockListMutex ); 294 295 if ( recycleMemBlockList[ level ] != NULL ) { 296 ptr = recycleMemBlockList[ level ]; 297 recycleMemBlockList[ level ] = ptr->nextBlock; 298 if ( recycleMemBlockList[ level ] != NULL ) { 299 recycleMemBlockList[ level ] ->previousBlock = NULL; 300 } 301 size = ptr->userMemorySize; 302 } 303 304 pthread_mutex_unlock( &recycleMemBlockListMutex ); 305 } 306 } 307 308 if ( ptr == NULL ) { 309 ptr = malloc( sizeof( psMemBlock ) + size + sizeof( void* ) ); 310 311 if ( ptr == NULL ) { 312 ptr = memExhaustedCallback( size ); 313 if ( ptr == NULL ) { 314 psAbort( __func__, "Failed to allocate %u bytes at %s:%d", 315 size, file, lineno ); 316 } 317 } 318 319 ptr->startblock = P_PS_MEMMAGIC; 320 ptr->endblock = P_PS_MEMMAGIC; 321 ptr->userMemorySize = size; 322 pthread_mutex_init( &ptr->refCounterMutex, NULL ); 323 } 324 319 325 // increment the memory id safely. 320 pthread_mutex_lock( &memBlockListMutex);321 *( psMemoryId*)&ptr->id = ++memid;322 pthread_mutex_unlock( &memBlockListMutex);323 326 pthread_mutex_lock( &memBlockListMutex ); 327 *( psMemoryId* ) & ptr->id = ++memid; 328 pthread_mutex_unlock( &memBlockListMutex ); 329 324 330 ptr->file = file; 325 331 ptr->freeFcn = NULL; 326 *( unsigned int*)&ptr->lineno = lineno;327 *( void**)((int8_t*)(ptr+1)+size) = P_PS_MEMMAGIC;332 *( unsigned int* ) & ptr->lineno = lineno; 333 *( void** ) ( ( int8_t* ) ( ptr + 1 ) + size ) = P_PS_MEMMAGIC; 328 334 ptr->previousBlock = NULL; 329 335 330 336 ptr->refCounter = 1; // one user so far 331 337 332 338 // need exclusive access of the memory block list now... 333 pthread_mutex_lock( &memBlockListMutex);334 339 pthread_mutex_lock( &memBlockListMutex ); 340 335 341 // insert the new block to the front of the memBlock linked-list 336 342 ptr->nextBlock = lastMemBlockAllocated; 337 if ( ptr->nextBlock != NULL) {338 ptr->nextBlock->previousBlock = ptr;339 }343 if ( ptr->nextBlock != NULL ) { 344 ptr->nextBlock->previousBlock = ptr; 345 } 340 346 lastMemBlockAllocated = ptr; 341 342 pthread_mutex_unlock( &memBlockListMutex);343 347 348 pthread_mutex_unlock( &memBlockListMutex ); 349 344 350 // Did the user ask to be informed about this allocation? 345 if ( ptr->id == p_psMemAllocateID) {346 p_psMemAllocateID += memAllocateCallback(ptr);347 }348 351 if ( ptr->id == p_psMemAllocateID ) { 352 p_psMemAllocateID += memAllocateCallback( ptr ); 353 } 354 349 355 // And return the user the memory that they allocated 350 356 return ptr + 1; // user memory 351 357 } 352 358 353 void *p_psRealloc( void *vptr, size_t size, const char *file, int lineno)354 { 355 if ( vptr == NULL) {356 return p_psAlloc(size, file, lineno);357 } else {358 psMemBlock *ptr = ((psMemBlock *)vptr) - 1;359 bool isBlockLast = false;360 361 if (checkMemBlock(ptr, __func__) != 0) {362 memProblemCallback(ptr, file, lineno);363 psAbort(file,"Realloc detected a memory corruption (id %ld @ %s:%d).",364 ptr->id,ptr->file,ptr->lineno);365 }366 367 pthread_mutex_lock(&memBlockListMutex);368 369 isBlockLast = (ptr == lastMemBlockAllocated);370 371 ptr = (psMemBlock*)realloc(ptr, sizeof(psMemBlock) + size + sizeof(void*));372 373 if (ptr == NULL) {374 psAbort(__func__, "Failed to reallocate %ld bytes at %s:%d",375 size, file, lineno);376 }377 378 ptr->userMemorySize = size;379 *(void**)((int8_t*)(ptr+1)+size) = P_PS_MEMMAGIC;380 381 if (isBlockLast) {382 lastMemBlockAllocated = ptr;383 }384 385 // the block location may have changed, so fix the linked list addresses.386 if (ptr->nextBlock != NULL) {387 ptr->nextBlock->previousBlock = ptr;388 }389 if (ptr->previousBlock != NULL) {390 ptr->previousBlock->nextBlock = ptr;391 }392 393 pthread_mutex_unlock(&memBlockListMutex);394 395 // Did the user ask to be informed about this allocation?396 if (ptr->id == p_psMemAllocateID) {397 p_psMemAllocateID += memAllocateCallback(ptr);398 }399 400 return ptr + 1; // usr memory401 }402 } 403 404 void p_psFree( void *vptr, const char *file, int lineno)405 { 406 ( void)p_psMemDecrRefCounter(vptr,file,lineno); // this handles the free, if required.359 void *p_psRealloc( void *vptr, size_t size, const char *file, int lineno ) 360 { 361 if ( vptr == NULL ) { 362 return p_psAlloc( size, file, lineno ); 363 } else { 364 psMemBlock *ptr = ( ( psMemBlock * ) vptr ) - 1; 365 bool isBlockLast = false; 366 367 if ( checkMemBlock( ptr, __func__ ) != 0 ) { 368 memProblemCallback( ptr, file, lineno ); 369 psAbort( file, "Realloc detected a memory corruption (id %ld @ %s:%d).", 370 ptr->id, ptr->file, ptr->lineno ); 371 } 372 373 pthread_mutex_lock( &memBlockListMutex ); 374 375 isBlockLast = ( ptr == lastMemBlockAllocated ); 376 377 ptr = ( psMemBlock* ) realloc( ptr, sizeof( psMemBlock ) + size + sizeof( void* ) ); 378 379 if ( ptr == NULL ) { 380 psAbort( __func__, "Failed to reallocate %ld bytes at %s:%d", 381 size, file, lineno ); 382 } 383 384 ptr->userMemorySize = size; 385 *( void** ) ( ( int8_t* ) ( ptr + 1 ) + size ) = P_PS_MEMMAGIC; 386 387 if ( isBlockLast ) { 388 lastMemBlockAllocated = ptr; 389 } 390 391 // the block location may have changed, so fix the linked list addresses. 392 if ( ptr->nextBlock != NULL ) { 393 ptr->nextBlock->previousBlock = ptr; 394 } 395 if ( ptr->previousBlock != NULL ) { 396 ptr->previousBlock->nextBlock = ptr; 397 } 398 399 pthread_mutex_unlock( &memBlockListMutex ); 400 401 // Did the user ask to be informed about this allocation? 402 if ( ptr->id == p_psMemAllocateID ) { 403 p_psMemAllocateID += memAllocateCallback( ptr ); 404 } 405 406 return ptr + 1; // usr memory 407 } 408 } 409 410 void p_psFree( void *vptr, const char *file, int lineno ) 411 { 412 ( void ) p_psMemDecrRefCounter( vptr, file, lineno ); // this handles the free, if required. 407 413 } 408 414 … … 410 416 * Check for memory leaks. 411 417 */ 412 int psMemCheckLeaks( psMemoryId id0,psMemBlock ***arr,FILE *fd)418 int psMemCheckLeaks( psMemoryId id0, psMemBlock ***arr, FILE *fd ) 413 419 { 414 420 int nleak = 0; 415 421 int j = 0; 416 422 psMemBlock* topBlock = lastMemBlockAllocated; 417 418 pthread_mutex_lock( &memBlockListMutex);419 420 for ( psMemBlock* iter = topBlock; iter != NULL; iter=iter->nextBlock) {421 if ( (psMemGetRefCounter(iter+1) > 0) && (iter->id >= id0) ) {422 nleak++;423 424 if (fd != NULL) {425 if (nleak == 1) {426 fprintf(fd, " %20s:line ID\n", "file");427 }428 429 fprintf(fd, " %20s:%-4d %ld\n", iter->file, iter->lineno, iter->id);430 }431 }432 }433 434 pthread_mutex_unlock( &memBlockListMutex);435 436 if ( nleak == 0 || arr == NULL) {437 return nleak;438 }439 440 *arr = p_psAlloc( nleak*sizeof(psMemBlock), __FILE__, __LINE__);441 pthread_mutex_lock( &memBlockListMutex);442 443 for ( psMemBlock* iter = topBlock; iter != NULL; iter=iter->nextBlock) {444 if ( (psMemGetRefCounter(iter+1) > 0) && (iter->id >= id0) ) {445 (*arr)[j++] = iter;446 if (j == nleak) { // found them all447 break;448 }449 }450 }451 452 pthread_mutex_unlock( &memBlockListMutex);453 423 424 pthread_mutex_lock( &memBlockListMutex ); 425 426 for ( psMemBlock * iter = topBlock; iter != NULL; iter = iter->nextBlock ) { 427 if ( ( psMemGetRefCounter( iter + 1 ) > 0 ) && ( iter->id >= id0 ) ) { 428 nleak++; 429 430 if ( fd != NULL ) { 431 if ( nleak == 1 ) { 432 fprintf( fd, " %20s:line ID\n", "file" ); 433 } 434 435 fprintf( fd, " %20s:%-4d %ld\n", iter->file, iter->lineno, iter->id ); 436 } 437 } 438 } 439 440 pthread_mutex_unlock( &memBlockListMutex ); 441 442 if ( nleak == 0 || arr == NULL ) { 443 return nleak; 444 } 445 446 *arr = p_psAlloc( nleak * sizeof( psMemBlock ), __FILE__, __LINE__ ); 447 pthread_mutex_lock( &memBlockListMutex ); 448 449 for ( psMemBlock * iter = topBlock; iter != NULL; iter = iter->nextBlock ) { 450 if ( ( psMemGetRefCounter( iter + 1 ) > 0 ) && ( iter->id >= id0 ) ) { 451 ( *arr ) [ j++ ] = iter; 452 if ( j == nleak ) { // found them all 453 break; 454 } 455 } 456 } 457 458 pthread_mutex_unlock( &memBlockListMutex ); 459 454 460 return nleak; 455 461 } … … 457 463 /* 458 464 * Reference counting APIs 459 */ 465 */ 460 466 // return refCounter 461 psReferenceCount psMemGetRefCounter( void *vptr)462 { 463 psMemBlock * ptr;467 psReferenceCount psMemGetRefCounter( void *vptr ) 468 { 469 psMemBlock * ptr; 464 470 unsigned int refCount; 465 466 if ( vptr == NULL) {467 return 0;468 }469 470 ptr = ( (psMemBlock *)vptr) - 1;471 472 if ( checkMemBlock(ptr, __func__) != 0) {473 memProblemCallback(ptr, __func__, __LINE__);474 }475 476 pthread_mutex_lock( &ptr->refCounterMutex);471 472 if ( vptr == NULL ) { 473 return 0; 474 } 475 476 ptr = ( ( psMemBlock * ) vptr ) - 1; 477 478 if ( checkMemBlock( ptr, __func__ ) != 0 ) { 479 memProblemCallback( ptr, __func__, __LINE__ ); 480 } 481 482 pthread_mutex_lock( &ptr->refCounterMutex ); 477 483 refCount = ptr->refCounter; 478 pthread_mutex_unlock( &ptr->refCounterMutex);479 484 pthread_mutex_unlock( &ptr->refCounterMutex ); 485 480 486 return refCount; 481 487 } 482 488 // increment and return refCounter 483 void* p_psMemIncrRefCounter( void *vptr, const char *file, int lineno)484 { 485 psMemBlock * ptr;486 487 if ( vptr == NULL) {488 return vptr;489 }490 491 ptr = ( (psMemBlock *)vptr) - 1;492 493 if ( checkMemBlock(ptr, __func__)) {494 memProblemCallback(ptr, file,lineno);495 }496 497 pthread_mutex_lock( &ptr->refCounterMutex);489 void* p_psMemIncrRefCounter( void *vptr, const char *file, int lineno ) 490 { 491 psMemBlock * ptr; 492 493 if ( vptr == NULL ) { 494 return vptr; 495 } 496 497 ptr = ( ( psMemBlock * ) vptr ) - 1; 498 499 if ( checkMemBlock( ptr, __func__ ) ) { 500 memProblemCallback( ptr, file, lineno ); 501 } 502 503 pthread_mutex_lock( &ptr->refCounterMutex ); 498 504 ptr->refCounter++; 499 pthread_mutex_unlock( &ptr->refCounterMutex);500 505 pthread_mutex_unlock( &ptr->refCounterMutex ); 506 501 507 return vptr; 502 508 } 503 509 504 510 // decrement and return refCounter 505 void* p_psMemDecrRefCounter(void *vptr,const char *file, int lineno) 506 { 507 if (vptr == NULL) { 508 return NULL; 509 } 510 511 psMemBlock *ptr = ((psMemBlock *)vptr) - 1; 512 513 if (checkMemBlock(ptr, __func__) != 0) { 514 memProblemCallback(ptr, file, lineno); 515 return NULL; 516 } 517 518 pthread_mutex_lock(&ptr->refCounterMutex); 519 520 if (ptr->refCounter > 1) { 521 /// XXX - Probably should have another mutex here. 522 ptr->refCounter--; // multiple references, just decrement the count. 523 pthread_mutex_unlock(&ptr->refCounterMutex); 524 525 } else { 526 pthread_mutex_unlock(&ptr->refCounterMutex); 527 528 // Did the user ask to be informed about this deallocation? 529 if (ptr->id == p_psMemFreeID) { 530 p_psMemFreeID += memFreeCallback(ptr); 531 } 532 533 if (ptr->freeFcn != NULL) { 534 ptr->freeFcn(vptr); 535 } 536 537 pthread_mutex_lock(&memBlockListMutex); 538 539 // cut the memBlock out of the memBlock list 540 if (ptr->nextBlock != NULL) { 541 ptr->nextBlock->previousBlock = ptr->previousBlock; 542 } 543 if (ptr->previousBlock != NULL) { 544 ptr->previousBlock->nextBlock = ptr->nextBlock; 545 } 546 if (lastMemBlockAllocated == ptr) { 547 lastMemBlockAllocated = ptr->nextBlock; 548 } 549 550 pthread_mutex_unlock(&memBlockListMutex); 551 552 553 // do we need to recycle? 554 if (ptr->userMemorySize < P_PS_LARGE_BLOCK_SIZE) { 555 556 int level = 1; 557 while (ptr->userMemorySize >= recycleBinSize[level]) { 558 level++; 559 } 560 level--; 561 562 ptr->refCounter = 0; 563 ptr->previousBlock = NULL; 564 565 pthread_mutex_lock(&recycleMemBlockListMutex); 566 ptr->nextBlock = recycleMemBlockList[level]; 567 if (recycleMemBlockList[level] != NULL) { 568 recycleMemBlockList[level]->previousBlock = ptr; 569 } 570 recycleMemBlockList[level] = ptr; 571 pthread_mutex_unlock(&recycleMemBlockListMutex); 572 511 void* p_psMemDecrRefCounter( void *vptr, const char *file, int lineno ) 512 { 513 if ( vptr == NULL ) { 514 return NULL; 515 } 516 517 psMemBlock *ptr = ( ( psMemBlock * ) vptr ) - 1; 518 519 if ( checkMemBlock( ptr, __func__ ) != 0 ) { 520 memProblemCallback( ptr, file, lineno ); 521 return NULL; 522 } 523 524 pthread_mutex_lock( &ptr->refCounterMutex ); 525 526 if ( ptr->refCounter > 1 ) { 527 /// XXX - Probably should have another mutex here. 528 ptr->refCounter--; // multiple references, just decrement the count. 529 pthread_mutex_unlock( &ptr->refCounterMutex ); 530 573 531 } else { 574 // memory is larger than I want to recycle. 575 #ifdef PS_MEM_DEBUG 576 (void)p_psRealloc(vptr,0,file,lineno); 577 ptr->previousBlock = NULL; 578 ptr->nextBlock = deadBlockList; 579 if (deadBlockList != NULL) { 580 deadBlockList->previous = ptr; 581 } 582 deadBlockList = ptr; 583 #else 584 585 pthread_mutex_destroy(&ptr->refCounterMutex); 586 free(ptr); 587 #endif 588 589 } 590 591 592 pthread_mutex_destroy(&ptr->refCounterMutex); 593 594 595 vptr = NULL; // since we freed it, make sure we return NULL. 596 } 597 532 pthread_mutex_unlock( &ptr->refCounterMutex ); 533 534 // Did the user ask to be informed about this deallocation? 535 if ( ptr->id == p_psMemFreeID ) { 536 p_psMemFreeID += memFreeCallback( ptr ); 537 } 538 539 if ( ptr->freeFcn != NULL ) { 540 ptr->freeFcn( vptr ); 541 } 542 543 pthread_mutex_lock( &memBlockListMutex ); 544 545 // cut the memBlock out of the memBlock list 546 if ( ptr->nextBlock != NULL ) { 547 ptr->nextBlock->previousBlock = ptr->previousBlock; 548 } 549 if ( ptr->previousBlock != NULL ) { 550 ptr->previousBlock->nextBlock = ptr->nextBlock; 551 } 552 if ( lastMemBlockAllocated == ptr ) { 553 lastMemBlockAllocated = ptr->nextBlock; 554 } 555 556 pthread_mutex_unlock( &memBlockListMutex ); 557 558 559 // do we need to recycle? 560 if ( ptr->userMemorySize < P_PS_LARGE_BLOCK_SIZE ) { 561 562 int level = 1; 563 while ( ptr->userMemorySize >= recycleBinSize[ level ] ) { 564 level++; 565 } 566 level--; 567 568 ptr->refCounter = 0; 569 ptr->previousBlock = NULL; 570 571 pthread_mutex_lock( &recycleMemBlockListMutex ); 572 ptr->nextBlock = recycleMemBlockList[ level ]; 573 if ( recycleMemBlockList[ level ] != NULL ) { 574 recycleMemBlockList[ level ] ->previousBlock = ptr; 575 } 576 recycleMemBlockList[ level ] = ptr; 577 pthread_mutex_unlock( &recycleMemBlockListMutex ); 578 579 } else { 580 // memory is larger than I want to recycle. 581 #ifdef PS_MEM_DEBUG 582 ( void ) p_psRealloc( vptr, 0, file, lineno ); 583 ptr->previousBlock = NULL; 584 ptr->nextBlock = deadBlockList; 585 if ( deadBlockList != NULL ) { 586 deadBlockList->previous = ptr; 587 } 588 deadBlockList = ptr; 589 #else 590 591 pthread_mutex_destroy( &ptr->refCounterMutex ); 592 free( ptr ); 593 #endif 594 595 } 596 597 vptr = NULL; // since we freed it, make sure we return NULL. 598 } 599 598 600 return vptr; 599 601 } 600 602 601 void p_psMemSetDeallocator( void* vptr, psFreeFcn freeFcn)602 { 603 if ( vptr == NULL) {604 return;605 }606 607 psMemBlock *ptr = ( (psMemBlock *)vptr) - 1;608 609 if ( checkMemBlock(ptr, __func__) != 0) {610 memProblemCallback(ptr, __func__, __LINE__);611 }612 603 void p_psMemSetDeallocator( void* vptr, psFreeFcn freeFcn ) 604 { 605 if ( vptr == NULL ) { 606 return ; 607 } 608 609 psMemBlock *ptr = ( ( psMemBlock * ) vptr ) - 1; 610 611 if ( checkMemBlock( ptr, __func__ ) != 0 ) { 612 memProblemCallback( ptr, __func__, __LINE__ ); 613 } 614 613 615 ptr->freeFcn = freeFcn; 614 615 } 616 psFreeFcn p_psMemGetDeallocator( void* vptr)617 { 618 if ( vptr == NULL) {619 return NULL;620 }621 622 psMemBlock *ptr = ( (psMemBlock *)vptr) - 1;623 624 if ( checkMemBlock(ptr, __func__) != 0) {625 memProblemCallback(ptr, __func__, __LINE__);626 }627 616 617 } 618 psFreeFcn p_psMemGetDeallocator( void* vptr ) 619 { 620 if ( vptr == NULL ) { 621 return NULL; 622 } 623 624 psMemBlock *ptr = ( ( psMemBlock * ) vptr ) - 1; 625 626 if ( checkMemBlock( ptr, __func__ ) != 0 ) { 627 memProblemCallback( ptr, __func__, __LINE__ ); 628 } 629 628 630 return ptr->freeFcn; 629 631 }
Note:
See TracChangeset
for help on using the changeset viewer.
