// _Defragment void BlockAllocator::Area::_Defragment() { D(SanityCheck()); //PRINT(("BlockAllocator::Area::_Defragment()\n")); // A trivial strategy for now: Keep the last free block and move the // others so that they can be joined with it. This is done iteratively // by moving the first free block to adjoin to the second one and // coalescing them. A free block is moved by moving the data blocks in // between. TFreeBlock *nextFree = NULL; while (fFirstFree && (nextFree = fFirstFree->GetNextFreeBlock()) != NULL) { Block *prevBlock = fFirstFree->GetPreviousBlock(); Block *nextBlock = fFirstFree->GetNextBlock(); size_t size = fFirstFree->GetSize(); // Used blocks are relatively position independed. We can move them // en bloc and only need to adjust the previous pointer of the first // one. if (!nextBlock->IsFree()) { // move the used blocks size_t chunkSize = (char*)nextFree - (char*)nextBlock; Block *nextFreePrev = nextFree->GetPreviousBlock(); Block *movedBlock = fFirstFree; memmove(movedBlock, nextBlock, chunkSize); movedBlock->SetPreviousBlock(prevBlock); // init the first free block Block *movedNextFreePrev = (Block*)((char*)nextFreePrev - size); fFirstFree = _MakeFreeBlock(movedBlock, chunkSize, movedNextFreePrev, size, true, NULL, nextFree); nextFree->SetPreviousFreeBlock(fFirstFree); // fix the references of the moved blocks for (Block *block = movedBlock; block != fFirstFree; block = block->GetNextBlock()) { block->FixReference(); } } else { // uncoalesced adjoining free block: That should never happen, // since we always coalesce as early as possible. INFORM(("Warning: Found uncoalesced adjoining free blocks!\n")); } // coalesce the first two blocks D(SanityCheck()); _CoalesceWithNext(fFirstFree); D(SanityCheck()); } //D(SanityCheck()); //PRINT(("BlockAllocator::Area::_Defragment() done\n")); }
// _CoalesceWithNext bool BlockAllocator::Area::_CoalesceWithNext(TFreeBlock *block) { bool result = false; TFreeBlock *nextFree = NULL; if (block && (nextFree = block->GetNextFreeBlock()) != NULL && block->GetNextBlock() == nextFree) { _RemoveFreeBlock(nextFree); Block *nextBlock = nextFree->GetNextBlock(); block->SetSize(block->GetSize() + nextFree->GetSize(), nextBlock); if (nextBlock) nextBlock->SetPreviousBlock(block); else fLastBlock = block; result = true; } return result; }