Changeset 97927 in vbox for trunk/src/VBox/Additions/common
- Timestamp:
- Dec 31, 2022 12:54:35 AM (2 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR0LibPhysHeap.cpp
r97926 r97927 60 60 * 61 61 * When freeing blocks, two subsequent free blocks are always merged together. 62 * Current implementation merges blocks only when there is a free block after 63 * the just freed one, never when there is one before it as that's too 64 * expensive. 62 * 63 * Since the free list isn't sorted by address or anything, it is expensive to 64 * determine whether the block before us is free and we should merge with it. 65 * The current implementation merges blocks only when there is a free block 66 * after the just freed one, never when there is one before it as that's too 67 * expensive. So, to counter this free list fragmentation, we will occasionally 68 * scan chunks with a majority of free blocks and merge adjacent ones. 65 69 */ 66 70 … … 440 444 441 445 RTMemContFree(pChunk, pChunk->cbSize); 446 } 447 448 449 /** 450 * Worker for VbglR0PhysHeapFree that merges adjacent free nodes in @a pChunk. 451 * 452 * The caller has check that there must be 1 or more such. 453 */ 454 static void vbglR0PhysHeapMergeAdjacentFreeBlocksInChunk(VBGLPHYSHEAPCHUNK *pChunk) 455 { 456 uintptr_t const uEnd = (uintptr_t)pChunk + pChunk->cbSize; 457 VBGLPHYSHEAPBLOCK *pPrevBlock = NULL; 458 VBGLPHYSHEAPBLOCK *pCurBlock = (VBGLPHYSHEAPBLOCK *)(pChunk + 1); 459 while ((uintptr_t)pCurBlock < uEnd) 460 { 461 VBGLPHYSHEAPBLOCK * const pNextBlock = (VBGLPHYSHEAPBLOCK *)((uintptr_t)(pCurBlock + 1) + pCurBlock->cbDataSize); 462 463 AssertReturnVoid(pCurBlock->u32Signature == VBGL_PH_BLOCKSIGNATURE); 464 AssertReturnVoid(pCurBlock->pChunk == pChunk); 465 if ( !pCurBlock->fAllocated 466 && pPrevBlock 467 && !pPrevBlock->fAllocated) 468 { 469 /* Adjust size of the previous memory block. */ 470 pPrevBlock->cbDataSize += sizeof(*pCurBlock) + pCurBlock->cbDataSize; 471 472 /* Unlink the current block and invalid it. */ 473 vbglPhysHeapUnlinkBlock(pCurBlock); 474 475 pCurBlock->u32Signature = ~VBGL_PH_BLOCKSIGNATURE; 476 pCurBlock->cbDataSize = UINT32_MAX / 4; 477 478 /* The previous node remains the same as we advance to the next one. */ 479 } 480 else 481 pPrevBlock = pCurBlock; 482 pCurBlock = pNextBlock; 483 } 442 484 } 443 485 … … 657 699 * Check if the block after this one is also free and we can merge it into 658 700 * this one. 659 *660 * Because the free list isn't sorted by address we cannot cheaply do the661 * same for the block before us, so we have to hope for the best for now.662 701 */ 663 /** @todo When the free:used ration in chunk is too skewed, scan the whole664 * chunk and merge adjacent blocks that way every so often. Always do so665 * when this is the last used one and we end up with more than 1 free666 * node afterwards. */667 702 pChunk = pBlock->pChunk; 668 703 pNeighbour = (VBGLPHYSHEAPBLOCK *)((uintptr_t)(pBlock + 1) + pBlock->cbDataSize); … … 705 740 vbglPhysHeapChunkDelete(pChunk); 706 741 pNeighbour = pBlock = NULL; /* invalid */ 742 pChunk = NULL; 707 743 break; 708 744 } 709 745 } 746 } 747 } 748 749 /* 750 * Hack to counter the lack of merging with the node before us, scan 751 * the chunk and merge adjacent free nodes. 752 */ 753 if (pChunk) 754 { 755 int32_t const cAllocBlocks = pChunk->acBlocks[1 /*alloc*/]; 756 int32_t const cApproxExcess = pChunk->acBlocks[0 /*free*/] - cAllocBlocks - 1; 757 if ( cApproxExcess > 0 /* there are too many free nodes */ 758 && cAllocBlocks >= 0 /* sanity check */) 759 { 760 /* Just do the merging if there aren't that many blocks: */ 761 if (cAllocBlocks <= 4) 762 vbglR0PhysHeapMergeAdjacentFreeBlocksInChunk(pChunk); 763 /* Do the merging if we're above a 1:2 ratio: */ 764 else if (cApproxExcess >= cAllocBlocks) 765 vbglR0PhysHeapMergeAdjacentFreeBlocksInChunk(pChunk); 710 766 } 711 767 }
Note:
See TracChangeset
for help on using the changeset viewer.