Esempio n. 1
0
// _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"));
}
Esempio n. 2
0
// _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;
}