Changeset 8525
- Timestamp:
- Aug 23, 2006, 12:53:09 PM (20 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/sys/psMemory.c (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/sys/psMemory.c
r8440 r8525 8 8 * @author Robert Lupton, Princeton University 9 9 * 10 * @version $Revision: 1.7 7$ $Name: not supported by cvs2svn $11 * @date $Date: 2006-08-2 1 21:50:09 $10 * @version $Revision: 1.78 $ $Name: not supported by cvs2svn $ 11 * @date $Date: 2006-08-23 22:53:09 $ 12 12 * 13 13 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 36 36 #include "psRegion.h" 37 37 38 39 38 #define P_PS_MEMMAGIC (psPtr )0xdeadbeef // Magic number in psMemBlock header 40 39 … … 46 45 static pthread_mutex_t memIdMutex = PTHREAD_MUTEX_INITIALIZER; 47 46 48 static pthread_mutex_t recycleMemBlockListMutex = PTHREAD_MUTEX_INITIALIZER;49 50 47 //private boolean for enabling/disabling thread safety. Default = enabled. 51 48 static bool safeThreads = true; … … 54 51 static bool memory_is_persistent = false; 55 52 56 #define N_RECYCLE_BINS 14 // number of recycle bins 57 static const psS32 recycleBins = N_RECYCLE_BINS; 58 static const psS32 recycleBinSize[N_RECYCLE_BINS] = 53 #ifdef PS_MEM_USE_RECYCLE // Only use recycling if this is set 54 #define N_RECYCLE_BINS 14 // number of recycle bins 55 #define MAX_RECYCLE 100 // Maximum number permitted in a recycle bin 56 static pthread_mutex_t recycleMemBlockListMutex = PTHREAD_MUTEX_INITIALIZER; // Mutex for recycle bins 57 static const psS32 recycleBinSize[N_RECYCLE_BINS] = // Size of each bin 59 58 { 60 59 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, P_PS_LARGE_BLOCK_SIZE 61 60 }; 62 63 61 // N.B. recycleBinSize should be terminated by P_PS_LARGE_BLOCK_SIZE (simplifies search loops) 64 static psMemBlock* recycleMemBlockList[N_RECYCLE_BINS] = { 65 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL 66 }; 62 static psS32 recycleBinNums[N_RECYCLE_BINS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // Number in each bin 63 static psMemBlock* recycleMemBlockList[N_RECYCLE_BINS] = // Contents of the bins 64 { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; 65 #endif // #ifdef PS_MEM_USE_RECYCLE 67 66 68 67 #ifdef PS_MEM_DEBUG … … 80 79 static psPtr memExhaustedCallbackDefault(size_t size) 81 80 { 81 #if PS_MEM_USE_RECYCLE 82 82 psPtr ptr = NULL; 83 83 if (safeThreads) { 84 84 pthread_mutex_lock(&recycleMemBlockListMutex); 85 85 } 86 psS32 level = recycleBins - 1;87 88 while (level >= 0 && ptr == NULL) { 89 while (recycleMemBlockList[level] != NULL&& ptr == NULL) {90 psMemBlock* old = recycleMemBlockList[level];91 92 recycleMemBlockList[ level] = recycleMemBlockList[level]->nextBlock;86 // Attempt to free up everything I can find so I can alloc my ptr 87 int bin = N_RECYCLE_BINS - 1; // Recycle bin 88 89 while (bin >= 0 && ptr == NULL) { 90 while (recycleMemBlockList[bin] != NULL && ptr == NULL) { 91 psMemBlock *old = recycleMemBlockList[bin]; 92 recycleMemBlockList[bin] = recycleMemBlockList[bin]->nextBlock; 93 93 free(old); 94 94 ptr = malloc(size); 95 95 } 96 level--;96 bin--; 97 97 } 98 98 … … 100 100 pthread_mutex_unlock(&recycleMemBlockListMutex); 101 101 } 102 103 102 return ptr; 103 #else // #ifdef PS_MEM_USE_RECYCLE 104 105 return NULL; 106 #endif // #ifdef PS_MEM_USE_RECYCLE 104 107 } 105 108 … … 336 339 } 337 340 341 #ifdef PS_MEM_USE_RECYCLE 342 // Return the appropriate recycle bin number 343 static int getRecycleBin(size_t size) 344 { 345 if (size >= P_PS_LARGE_BLOCK_SIZE) { 346 return N_RECYCLE_BINS; 347 } 348 int binNum = 0; // Recycle bin number 349 while (size > recycleBinSize[binNum]) { 350 binNum++; 351 } 352 return binNum; 353 } 354 355 // Push a pointer onto the recycle bin 356 static void recyclePush(psMemBlock *mb, // Pointer to push 357 int bin // Recycling bin 358 ) 359 { 360 assert(mb); 361 assert(bin < N_RECYCLE_BINS); 362 363 mb->previousBlock = NULL; 364 365 if (safeThreads) { 366 pthread_mutex_lock(&recycleMemBlockListMutex); 367 } 368 369 mb->nextBlock = recycleMemBlockList[bin]; 370 if (recycleMemBlockList[bin] != NULL) { 371 recycleMemBlockList[bin]->previousBlock = mb; 372 } 373 recycleMemBlockList[bin] = mb; 374 recycleBinNums[bin]++; 375 376 if (safeThreads) { 377 pthread_mutex_unlock(&recycleMemBlockListMutex); 378 } 379 380 return; 381 } 382 383 // Pop a pointer from the recycle bin 384 static psMemBlock *recyclePop(int bin // Recycling bin 385 ) 386 { 387 if (bin >= N_RECYCLE_BINS) { 388 return NULL; 389 } 390 391 if (safeThreads) { 392 pthread_mutex_lock(&recycleMemBlockListMutex); 393 } 394 395 psMemBlock *mb = recycleMemBlockList[bin]; // Pointer popped from recycle bin 396 397 if (mb) { 398 // We pull it off the list 399 recycleMemBlockList[bin] = mb->nextBlock; 400 if (recycleMemBlockList[bin] != NULL) { 401 recycleMemBlockList[bin]->previousBlock = NULL; 402 } 403 recycleBinNums[bin]--; 404 } 405 406 if (safeThreads) { 407 pthread_mutex_unlock(&recycleMemBlockListMutex); 408 } 409 410 return mb; 411 } 412 #endif // #ifdef PS_MEM_USE_RECYCLE 413 338 414 /* 339 415 * Actually allocate memory … … 344 420 { 345 421 346 psMemBlock* ptr = NULL; 347 348 size = (size < recycleBinSize[0]) ? recycleBinSize[0] : size; // set the minimum size to allocate 349 350 // memory is of the size I want to bother recycling? 351 if (size < P_PS_LARGE_BLOCK_SIZE) { 352 // find the bin we need. 353 psS32 level = 0; 354 355 while (size > recycleBinSize[level]) { 356 level++; 357 } 358 // Are we in one of the bins 359 if (level < recycleBins) { 360 361 size = recycleBinSize[level]; // round-up size to next sized bin. 362 363 if (safeThreads) { 364 pthread_mutex_lock(&recycleMemBlockListMutex); 365 } 366 367 if (recycleMemBlockList[level] != NULL) { 368 ptr = recycleMemBlockList[level]; 369 recycleMemBlockList[level] = ptr->nextBlock; 370 if (recycleMemBlockList[level] != NULL) { 371 recycleMemBlockList[level]->previousBlock = NULL; 372 } 373 size = ptr->userMemorySize; 374 } 375 376 if (safeThreads) { 377 pthread_mutex_unlock(&recycleMemBlockListMutex); 378 } 379 } 380 } 422 psMemBlock *ptr = NULL; 423 424 #ifdef PS_MEM_USE_RECYCLE 425 // Are we in one of the recycle bins? 426 int bin = getRecycleBin(size); 427 if (bin < N_RECYCLE_BINS) { 428 size = recycleBinSize[bin]; // round-up size to next sized bin. 429 ptr = recyclePop(bin); // grab out of the recycle bin 430 } 431 #endif // #ifdef PS_MEM_USE_RECYCLE 381 432 382 433 if (ptr == NULL) { … … 443 494 unsigned int lineno) 444 495 { 445 size = (size < recycleBinSize[0]) ? recycleBinSize[0] : size; // set the minimum size to allocate446 447 496 if (vptr == NULL) { 448 497 return p_psAlloc(size, file, lineno); 449 } else { 450 psMemBlock* ptr = ((psMemBlock* ) vptr) - 1; 451 psBool isBlockLast = false; 452 453 if (checkMemBlock(ptr, __func__) != 0) { 454 memProblemCallback(ptr, file, lineno); 455 psAbort(file, "Realloc detected a memory corruption (id %lu @ %s:%d).", 456 (unsigned long)ptr->id, ptr->file, ptr->lineno); 457 } 458 459 if (size <= ptr->userMemorySize) { 460 ; // nothing to do 461 } else { 462 isBlockLast = (ptr == lastMemBlockAllocated); 463 464 psPtr *nvptr = p_psAlloc(size, file, lineno); 465 psMemBlock *nptr = ((psMemBlock *)nvptr) - 1; 466 memcpy(nvptr, vptr, ptr->userMemorySize < size ? ptr->userMemorySize : size); 467 *(psMemId *)&nptr->id = ptr->id; 468 nptr->persistent = ptr->persistent; 469 470 psFree(vptr); 471 ptr = nptr; 472 } 473 474 // Did the user ask to be informed about this allocation? 475 if (ptr->id == p_psMemAllocID) { 476 p_psMemAllocID += memAllocCallback(ptr); 477 } 478 479 return ptr + 1; // usr memory 480 } 498 } 499 500 psMemBlock *ptr = ((psMemBlock*)vptr) - 1; 501 502 if (checkMemBlock(ptr, __func__) != 0) { 503 memProblemCallback(ptr, file, lineno); 504 psAbort(file, "Realloc detected a memory corruption (id %lu @ %s:%d).", 505 (unsigned long)ptr->id, ptr->file, ptr->lineno); 506 } 507 508 #ifdef PS_MEM_USE_RECYCLE 509 // Ensure the size matches that of the recycle bin 510 int bin = getRecycleBin(size); 511 if (bin < N_RECYCLE_BINS) { 512 size = recycleBinSize[bin]; // round-up size to next sized bin. 513 } 514 #endif // #ifdef PS_MEM_USE_RECYCLE 515 516 if (size == ptr->userMemorySize) { 517 // Nothing to do 518 return vptr; 519 } 520 521 // Reallocate the memory 522 523 if (safeThreads) { 524 pthread_mutex_lock(&memBlockListMutex); 525 } 526 527 bool isBlockLast = (ptr == lastMemBlockAllocated); // Is this the last block we allocated? 528 ptr = (psMemBlock *)realloc(ptr, sizeof(psMemBlock) + size + sizeof(psPtr)); 529 if (ptr == NULL) { 530 ptr = memExhaustedCallback(size); 531 if (ptr == NULL) { 532 psAbort(__func__, "Failed to reallocate %ld bytes at %s:%d", size, file, lineno); 533 } 534 } 535 536 ptr->userMemorySize = size; 537 *(psPtr *)((int8_t *) (ptr + 1) + size) = P_PS_MEMMAGIC; 538 539 if (isBlockLast) { 540 lastMemBlockAllocated = ptr; 541 } 542 543 // the block location may have changed, so fix the linked list addresses. 544 if (ptr->nextBlock != NULL) { 545 ptr->nextBlock->previousBlock = ptr; 546 } 547 if (ptr->previousBlock != NULL) { 548 ptr->previousBlock->nextBlock = ptr; 549 } 550 551 if (safeThreads) { 552 pthread_mutex_unlock(&memBlockListMutex); 553 } 554 555 // Did the user ask to be informed about this allocation? 556 if (ptr->id == p_psMemAllocID) { 557 p_psMemAllocID += memAllocCallback(ptr); 558 } 559 560 return ptr + 1; // usr memory 481 561 } 482 562 … … 728 808 } 729 809 730 // do we need to recycle? 731 if (ptr->userMemorySize < P_PS_LARGE_BLOCK_SIZE) { 732 733 psS32 level = 1; 734 735 while (ptr->userMemorySize >= recycleBinSize[level]) { 736 level++; 737 } 738 level--; 739 810 #ifdef PS_MEM_USE_RECYCLE 811 // do we recycle? 812 int bin = getRecycleBin(ptr->userMemorySize); 813 if (bin < N_RECYCLE_BINS && recycleBinNums[bin] < MAX_RECYCLE) { 740 814 ptr->refCounter = 0; 741 ptr->previousBlock = NULL; 742 743 if (safeThreads) { 744 pthread_mutex_lock(&recycleMemBlockListMutex); 745 } 746 ptr->nextBlock = recycleMemBlockList[level]; 747 if (recycleMemBlockList[level] != NULL) { 748 recycleMemBlockList[level]->previousBlock = ptr; 749 } 750 recycleMemBlockList[level] = ptr; 751 if (safeThreads) { 752 pthread_mutex_unlock(&recycleMemBlockListMutex); 753 } 754 755 } else { 756 // memory is larger than I want to recycle. 757 #ifdef PS_MEM_DEBUG 758 (void)p_psRealloc(vptr, 0, file, lineno); 759 ptr->previousBlock = NULL; 760 ptr->nextBlock = deadBlockList; 761 if (deadBlockList != NULL) { 815 recyclePush(ptr, bin); 816 } else 817 #endif // #ifdef PS_MEM_USE_RECYCLE 818 { 819 // memory is larger than I want to recycle. 820 #ifdef PS_MEM_DEBUG 821 (void)p_psRealloc(vptr, 0, file, lineno); 822 ptr->previousBlock = NULL; 823 ptr->nextBlock = deadBlockList; 824 if (deadBlockList != NULL) { 762 825 deadBlockList->previous = ptr; 763 826 } 764 deadBlockList = ptr;765 #else // #ifdef PS_MEM_DEBUG766 767 if (safeThreads) {768 pthread_mutex_destroy(&ptr->refCounterMutex);827 deadBlockList = ptr; 828 #else // #ifdef PS_MEM_DEBUG 829 830 if (safeThreads) { 831 pthread_mutex_destroy(&ptr->refCounterMutex); 769 832 } 770 833 free(ptr); … … 1201 1264 *freelist = 0; 1202 1265 int nblock_tot = 0; 1203 for (int i = 0; ; i++) { 1204 if (recycleBinSize[i] == P_PS_LARGE_BLOCK_SIZE) { 1205 break; 1206 } 1266 #ifdef PS_MEM_USE_RECYCLE 1267 1268 for (int i = 0; recycleBinSize[i] < P_PS_LARGE_BLOCK_SIZE; i++) { 1207 1269 size_t bin_contents = 0; 1208 1270 size_t nblock = 0; … … 1218 1280 } 1219 1281 } 1282 #endif // #ifdef PS_MEM_USE_RECYCLE 1283 1220 1284 if (print) { 1221 1285 printf("Freelist %6s %10d %8d\n", "", *freelist, nblock_tot); 1222 1286 } 1223 1287 1288 1224 1289 if (safeThreads) { 1225 1290 pthread_mutex_unlock(&memBlockListMutex);
Note:
See TracChangeset
for help on using the changeset viewer.
