예제 #1
0
        private KMemoryBlock SplitBlock(KMemoryBlock block, uint address, uint size)
        {
            Debug.Assert(size > 0);

            KMemoryBlock newBlock = new KMemoryBlock(this, address, size, false);

            LinkedListEntry <KMemoryBlock> blockEntry = Blocks.Find(block);

            Debug.Assert(blockEntry != null);

            if (address == block.Address)
            {
                // Bottom up - put right before free and shift free up
                block.Address += size;
                block.Size    -= size;

                Blocks.InsertBefore(newBlock, blockEntry);
            }
            else if (address == block.UpperBound - size)
            {
                // Top down - put right after and free shift free down
                block.Size -= size;

                Blocks.InsertAfter(newBlock, blockEntry);
            }
            else
            {
                // Middle - need a real split
                uint originalSize = block.Size;
                block.Size = newBlock.Address - block.Address;
                if (block.Size == 0)
                {
                    // Special case of block replacing block
                    Blocks.InsertAfter(newBlock, blockEntry);
                    // block will be removed below
                }
                else
                {
                    uint freeAddress = newBlock.Address + newBlock.Size;
                    uint freeSize    = originalSize - block.Size - newBlock.Size;

                    KMemoryBlock freeBlock = new KMemoryBlock(this, freeAddress, freeSize, true);

                    // Add free space after start block if needed
                    if (freeSize > 0)
                    {
                        LinkedListEntry <KMemoryBlock> blockEntryFree = FreeList.Find(block);
                        Blocks.InsertAfter(freeBlock, blockEntry);
                        FreeList.InsertAfter(freeBlock, blockEntryFree);
                    }

                    // Add after the block (but before the freeBlock if there was one)
                    Blocks.InsertAfter(newBlock, blockEntry);
                }
            }

            Debug.Assert(block.Size >= 0);

            // Remove old block if dead
            if (block.Size == 0)
            {
                Blocks.Remove(blockEntry);
                FreeList.Remove(block);
            }

            return(newBlock);
        }