- Timestamp:
- May 25, 2011, 2:16:18 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/ipp-20110505/psLib/src/sys/psMemory.c
r31152 r31568 328 328 // This is the root of the entire memory list 329 329 static psMemBlock *lastMemBlockAllocated = NULL; 330 static bool lastMemBlockInFlight = false; 330 331 331 332 /* Actually allocate memory … … 536 537 // Reallocate the memory 537 538 538 // we need to lock this whole section because we need to be able to adjust 539 // lastMemBlockAllocated if needed (ie, this IS lastMemBlockAllocated) 540 // this lock is frequently called in a given program 539 /* psRealloc and locks: 540 541 psRealloc calls 'realloc' to change the size of the memory block. This call is likely 542 to change the address of the memory block itself. This is a problem because the address 543 of the memory block is referred to by the neighbor blocks via their memBlock->nextBlock 544 and memBlock->previousBlock elements. If the current memBlock is the first one, then 545 this issue also applies to 'lastMemBlockAllocated'. The elements may also be modified 546 by psFree and psAlloc. Thus, we need to prevent multiple threads from calling psFree, 547 psAlloc, or psRealloc on neighbor memory blocks at the same time. 548 549 Unfortunately, unlike psAlloc and psFree, psRealloc cannot perform the (expensive) 550 system call operation (realloc) first and adjust the pointers in separate step (since 551 the value modified by realloc *is* one of those points. It is thus necessary to include 552 the realloc call within the locked segement, making psRealloc likely to serialize the 553 thread operations. 554 555 Alternatively, we can recognize that the lock only need be applied to operations which 556 are performed on neighboring memBlocks. We can thus reduce the contention by having a 557 per-memBlock boolean (inFlight) which says the memBlock or a neighbor is being 558 modified. If psFree and psAlloc respect that boolean, they will not modify a memBlock 559 which is already being realloced (or its neighbor). In this way, the 'realloc' call can 560 be performed outside of the locked region. 561 562 */ 563 564 // set a lock, then lock this memblock and its neighbors 541 565 MUTEX_LOCK(&memBlockListMutex); 542 566 … … 548 572 // lastMemBlockAllocated will be left with a bogus value 549 573 bool isBlockLast = (memBlock == lastMemBlockAllocated); 574 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 550 583 551 584 memBlock = (psMemBlock *)realloc(memBlock, sizeof(psMemBlock) + size + sizeof(void *)); … … 581 614 memAllocID += memAllocCallback(memBlock); 582 615 } 616 617 // 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; 583 623 584 624 MUTEX_UNLOCK(&memBlockListMutex);
Note:
See TracChangeset
for help on using the changeset viewer.
