private void FreePages(ulong address, ulong pagesCount) { ulong endAddr = address + pagesCount * KMemoryManager.PageSize; int blockIndex = _blockOrdersCount - 1; ulong addressRounded = 0; ulong endAddrTruncated = 0; for (; blockIndex >= 0; blockIndex--) { KMemoryRegionBlock allocInfo = _blocks[blockIndex]; int blockSize = 1 << allocInfo.Order; addressRounded = BitUtils.AlignUp(address, blockSize); endAddrTruncated = BitUtils.AlignDown(endAddr, blockSize); if (addressRounded < endAddrTruncated) { break; } } void FreeRegion(ulong currAddress) { for (int currBlockIndex = blockIndex; currBlockIndex < _blockOrdersCount && currAddress != 0; currBlockIndex++) { KMemoryRegionBlock block = _blocks[currBlockIndex]; block.FreeCount++; ulong freedBlocks = (currAddress - block.StartAligned) >> block.Order; int index = (int)freedBlocks; for (int level = block.MaxLevel - 1; level >= 0; level--, index /= 64) { long mask = block.Masks[level][index / 64]; block.Masks[level][index / 64] = mask | (1L << (index & 63)); if (mask != 0) { break; } } int blockSizeDelta = 1 << (block.NextOrder - block.Order); int freedBlocksTruncated = BitUtils.AlignDown((int)freedBlocks, blockSizeDelta); if (!block.TryCoalesce(freedBlocksTruncated, blockSizeDelta)) { break; } currAddress = block.StartAligned + ((ulong)freedBlocksTruncated << block.Order); } } //Free inside aligned region. ulong baseAddress = addressRounded; while (baseAddress < endAddrTruncated) { ulong blockSize = 1UL << _blocks[blockIndex].Order; FreeRegion(baseAddress); baseAddress += blockSize; } int nextBlockIndex = blockIndex - 1; //Free region between Address and aligned region start. baseAddress = addressRounded; for (blockIndex = nextBlockIndex; blockIndex >= 0; blockIndex--) { ulong blockSize = 1UL << _blocks[blockIndex].Order; while (baseAddress - blockSize >= address) { baseAddress -= blockSize; FreeRegion(baseAddress); } } //Free region between aligned region end and End Address. baseAddress = endAddrTruncated; for (blockIndex = nextBlockIndex; blockIndex >= 0; blockIndex--) { ulong blockSize = 1UL << _blocks[blockIndex].Order; while (baseAddress + blockSize <= endAddr) { FreeRegion(baseAddress); baseAddress += blockSize; } } }
private void FreePages(ulong Address, ulong PagesCount) { ulong EndAddr = Address + PagesCount * KMemoryManager.PageSize; int BlockIndex = BlockOrdersCount - 1; ulong AddressRounded = 0; ulong EndAddrTruncated = 0; for (; BlockIndex >= 0; BlockIndex--) { KMemoryRegionBlock AllocInfo = Blocks[BlockIndex]; int BlockSize = 1 << AllocInfo.Order; AddressRounded = BitUtils.AlignUp(Address, BlockSize); EndAddrTruncated = BitUtils.AlignDown(EndAddr, BlockSize); if (AddressRounded < EndAddrTruncated) { break; } } void FreeRegion(ulong CurrAddress) { for (int CurrBlockIndex = BlockIndex; CurrBlockIndex < BlockOrdersCount && CurrAddress != 0; CurrBlockIndex++) { KMemoryRegionBlock Block = Blocks[CurrBlockIndex]; Block.FreeCount++; ulong FreedBlocks = (CurrAddress - Block.StartAligned) >> Block.Order; int Index = (int)FreedBlocks; for (int Level = Block.MaxLevel - 1; Level >= 0; Level--, Index /= 64) { long Mask = Block.Masks[Level][Index / 64]; Block.Masks[Level][Index / 64] = Mask | (1L << (Index & 63)); if (Mask != 0) { break; } } int BlockSizeDelta = 1 << (Block.NextOrder - Block.Order); int FreedBlocksTruncated = BitUtils.AlignDown((int)FreedBlocks, BlockSizeDelta); if (!Block.TryCoalesce(FreedBlocksTruncated, BlockSizeDelta)) { break; } CurrAddress = Block.StartAligned + ((ulong)FreedBlocksTruncated << Block.Order); } } //Free inside aligned region. ulong BaseAddress = AddressRounded; while (BaseAddress < EndAddrTruncated) { ulong BlockSize = 1UL << Blocks[BlockIndex].Order; FreeRegion(BaseAddress); BaseAddress += BlockSize; } int NextBlockIndex = BlockIndex - 1; //Free region between Address and aligned region start. BaseAddress = AddressRounded; for (BlockIndex = NextBlockIndex; BlockIndex >= 0; BlockIndex--) { ulong BlockSize = 1UL << Blocks[BlockIndex].Order; while (BaseAddress - BlockSize >= Address) { BaseAddress -= BlockSize; FreeRegion(BaseAddress); } } //Free region between aligned region end and End Address. BaseAddress = EndAddrTruncated; for (BlockIndex = NextBlockIndex; BlockIndex >= 0; BlockIndex--) { ulong BlockSize = 1UL << Blocks[BlockIndex].Order; while (BaseAddress + BlockSize <= EndAddr) { FreeRegion(BaseAddress); BaseAddress += BlockSize; } } }