Changeset 31569
- Timestamp:
- May 26, 2011, 10:47:40 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/ipp-20110505/psLib/src/sys/psMemory.c
r31568 r31569 35 35 #include "psError.h" // for psErrorStackPrint() only 36 36 #include "psMemory.h" 37 #include "psAbort.h" 37 38 38 39 // Magic number in psMemBlock header … … 325 326 } 326 327 328 /** BLOCK_LOCK, BLOCK_UNLOCK, BLOCKSET_LOCK, BLOCKSET_UNLOCK are used to set per-memBlock locks 329 ** to allow psRealloc to release the global lock before performing the expensive system 330 ** call 'realloc' 331 **/ 332 333 // if HARDLOCKS is set, revert to global locking for realloc 334 # define HARDLOCKS 1 335 336 // memBlock->inFlight is a 'soft' lock. if true, the lock is set 337 void BLOCK_LOCK (psMemBlock *memBlock, bool keepMutex) { 338 339 # if (HARDLOCKS) 340 MUTEX_LOCK(&memBlockListMutex); 341 # else 342 343 psAssert (memBlock || keepMutex, "trying to set a soft lock on a non-existent memBlock"); 344 345 // if memBlock is not defined, we are just asking for a m 346 if (!memBlock) { 347 MUTEX_LOCK(&memBlockListMutex); 348 return; 349 } 350 351 while (true) { 352 // we cannot set the lock on the marker while the lock is held 353 while (memBlock->inFlight) { usleep (10000); } 354 355 // set a lock, then lock this memblock and its neighbors 356 MUTEX_LOCK(&memBlockListMutex); 357 358 // did we beat the race condition? is the lock still clear? 359 if (memBlock->inFlight) { 360 // nope, we need to try again 361 MUTEX_UNLOCK(&memBlockListMutex); 362 continue; 363 } 364 365 // the marker is ours! 366 memBlock->inFlight = true; 367 if (keepMutex) return; 368 369 MUTEX_UNLOCK(&memBlockListMutex); 370 return; 371 } 372 # endif 373 } 374 375 void BLOCK_UNLOCK (psMemBlock *memBlock, bool haveMutex) { 376 377 # if (HARDLOCKS) 378 MUTEX_UNLOCK(&memBlockListMutex); 379 # else 380 381 psAssert (memBlock || haveMutex, "trying to clear a soft lock on a non-existent memBlock"); 382 383 // if memBlock is not defined, we are just asking for a regular lock 384 if (!memBlock) { 385 MUTEX_UNLOCK(&memBlockListMutex); 386 return; 387 } 388 389 // need to lock before clearing the marker 390 if (!haveMutex) { 391 MUTEX_LOCK(&memBlockListMutex); 392 } 393 memBlock->inFlight = false; 394 MUTEX_UNLOCK(&memBlockListMutex); 395 return; 396 # endif 397 } 398 399 // attempt to grab the markers on the given memBlock and its two neighbors. the only times the 400 // two neighbors do not exist is if we are at the beginning or end of the list (or the list is 401 // new). 402 void BLOCKSET_LOCK (psMemBlock *memBlock, bool keepMutex) { 403 404 # if (HARDLOCKS) 405 MUTEX_LOCK(&memBlockListMutex); 406 # else 407 408 psAssert (memBlock, "trying to set a soft lock on a non-existent memBlock"); 409 410 while (true) { 411 // we cannot set the lock on the marker while the lock is held 412 // wait until all three markers are clear: 413 while (memBlock->inFlight) { usleep (10000); } 414 if (memBlock->nextBlock) { 415 while (memBlock->nextBlock->inFlight) { usleep (10000); } 416 } 417 if (memBlock->previousBlock) { 418 while (memBlock->previousBlock->inFlight) { usleep (10000); } 419 } 420 421 // set a lock, then lock this memblock and its neighbors 422 MUTEX_LOCK(&memBlockListMutex); 423 424 // did we beat the race condition? are all three locks still clear? 425 if (memBlock->inFlight) { 426 // nope, we need to try again 427 MUTEX_UNLOCK(&memBlockListMutex); 428 continue; 429 } 430 if (memBlock->nextBlock && memBlock->nextBlock->inFlight) { 431 // nope, we need to try again 432 MUTEX_UNLOCK(&memBlockListMutex); 433 continue; 434 } 435 if (memBlock->previousBlock && memBlock->previousBlock->inFlight) { 436 // nope, we need to try again 437 MUTEX_UNLOCK(&memBlockListMutex); 438 continue; 439 } 440 441 // the markers are ours! 442 memBlock->inFlight = true; 443 if (memBlock->nextBlock) { 444 memBlock->nextBlock->inFlight = true; 445 } 446 if (memBlock->previousBlock) { 447 memBlock->previousBlock->inFlight = true; 448 } 449 if (keepMutex) return; 450 451 MUTEX_UNLOCK(&memBlockListMutex); 452 return; 453 } 454 # endif 455 } 456 457 void BLOCKSET_UNLOCK (psMemBlock *memBlock, bool haveMutex) { 458 459 # if (HARDLOCKS) 460 MUTEX_UNLOCK(&memBlockListMutex); 461 # else 462 463 // need to lock before clearing the marker 464 if (!haveMutex) { 465 MUTEX_LOCK(&memBlockListMutex); 466 } 467 memBlock->inFlight = false; 468 if (memBlock->nextBlock) { 469 memBlock->nextBlock->inFlight = false; 470 } 471 if (memBlock->previousBlock) { 472 memBlock->previousBlock->inFlight = false; 473 } 474 MUTEX_UNLOCK(&memBlockListMutex); 475 return; 476 # endif 477 } 478 327 479 // pointer to the last mem block that was allocated. 328 480 // This is the root of the entire memory list 329 481 static psMemBlock *lastMemBlockAllocated = NULL; 330 static bool lastMemBlockInFlight = false;331 482 332 483 /* Actually allocate memory … … 366 517 // function 367 518 memBlock->func = func; 519 520 // per-block lock (off by default) 521 memBlock->inFlight = false; 368 522 369 523 #if defined(PS_MEM_BACKTRACE) && defined(HAVE_BACKTRACE) … … 397 551 // need exclusive access of the memory block list now... 398 552 // this lock is very frequently called in a given program 399 MUTEX_LOCK(&memBlockListMutex); 400 401 // increment the memory id only after we've grabbed the memBlockListMutex 553 // lastMemBlockAllocated is always true except the first allocation 554 BLOCK_LOCK (lastMemBlockAllocated, true); 555 556 // increment the memory id only after we've grabbed the memBlockListMutex this value is 557 // returned by psMemGetID and psMemGetLastID, but only ever modified here 402 558 *(psMemId* )&memBlock->id = ++memid; 403 559 … … 416 572 } 417 573 418 MUTEX_UNLOCK(&memBlockListMutex);574 BLOCK_UNLOCK (memBlock->nextBlock, true); 419 575 420 576 // And return the user the memory that they allocated … … 562 718 */ 563 719 564 // set a lock, then lock this memblock and its neighbors 565 MUTEX_LOCK(&memBlockListMutex); 720 // set a lock, then lock this memblock and its neighbors. at the end of this call, 721 // the global mutex is released, but the memBlock and its neighbors are protected 722 BLOCKSET_LOCK (memBlock, false); 566 723 567 724 psMemBlock *nextBlock = memBlock->nextBlock; … … 573 730 bool isBlockLast = (memBlock == lastMemBlockAllocated); 574 731 575 memBlock->inFlight = true; 576 nextBlock->inFlight = true; 577 previousBlock->inFlight = true; 578 if (isBlockLast) lastMemBlockInFlight = true; 579 580 MUTEX_UNLOCK(&memBlockListMutex); 581 582 // now that the per-memBlock locks are set, we can unlock the threads and realloc the data 583 732 // do the expensive system call. other threads can continue to modify other memBlocks 733 // except this one and its two neighbors 584 734 memBlock = (psMemBlock *)realloc(memBlock, sizeof(psMemBlock) + size + sizeof(void *)); 585 735 if (memBlock == NULL) { … … 616 766 617 767 // all of the list modifications are done; set the lock and clear the per-memBlock locks 618 MUTEX_LOCK(&memBlockListMutex); 619 memBlock->inFlight = false; 620 nextBlock->inFlight = false; 621 previousBlock->inFlight = false; 622 if (isBlockLast) lastMemBlockInFlight = false; 623 624 MUTEX_UNLOCK(&memBlockListMutex); 768 BLOCKSET_UNLOCK(memBlock, false); 769 770 psAssert (!memBlock->inFlight, "unreleased lock?"); 771 psAssert (!nextBlock || !nextBlock->inFlight, "unreleased lock?"); 772 psAssert (!previousBlock || !previousBlock->inFlight, "unreleased lock?"); 625 773 626 774 return memBlock + 1; // usr memory … … 848 996 // if we have multiple references, just decrement the count and return. 849 997 // we need a MUTEX_LOCK here: otherwise, two functions can race on refCounter--; 850 MUTEX_LOCK(&memBlockListMutex);998 BLOCK_LOCK (memBlock, true); 851 999 if (memBlock->refCounter > 1) { 852 1000 memBlock->refCounter--; … … 856 1004 memFreeID += memFreeCallback(memBlock); 857 1005 } 858 MUTEX_UNLOCK(&memBlockListMutex);1006 BLOCK_UNLOCK(memBlock, true); 859 1007 return ptr; 860 1008 } 861 MUTEX_UNLOCK(&memBlockListMutex);1009 BLOCK_UNLOCK(memBlock, true); 862 1010 863 1011 // we can't invoke freeFunc() while we're holding memBlockListMutex as it … … 868 1016 869 1017 // this lock is frequently set in a given program 870 MUTEX_LOCK(&memBlockListMutex);1018 BLOCKSET_LOCK (memBlock, true); 871 1019 872 1020 // Did the user ask to be informed about this deallocation? … … 881 1029 if (nextBlock != NULL) { 882 1030 nextBlock->previousBlock = previousBlock; 1031 nextBlock->inFlight = false; 883 1032 } 884 1033 if (previousBlock != NULL) { 885 1034 previousBlock->nextBlock = nextBlock; 1035 previousBlock->inFlight = false; 886 1036 } 887 1037 if (lastMemBlockAllocated == memBlock) { … … 893 1043 memBlock->previousBlock = NULL; 894 1044 895 MUTEX_UNLOCK(&memBlockListMutex); 1045 BLOCKSET_UNLOCK (memBlock, true); 1046 1047 // XXX these are slightly dangerous : someone else may grab the lock in the meanwhile... 1048 psAssert (!memBlock->inFlight, "unreleased lock?"); 1049 psAssert (!nextBlock || !nextBlock->inFlight, "unreleased lock?"); 1050 psAssert (!previousBlock || !previousBlock->inFlight, "unreleased lock?"); 896 1051 897 1052 // invoke free only after we've released the block list lock as free()
Note:
See TracChangeset
for help on using the changeset viewer.
