public KMemoryBlock Allocate( string name, KAllocType type, uint address, uint size ) { KMemoryBlock newBlock = null; // Round size up to the next word //if( ( size & 0x3 ) != 0 ) // size += 4 - ( size & 0x3 ); if( ( type == KAllocType.LowAligned ) || ( type == KAllocType.HighAligned ) ) { // TODO: align at 'address' (like 4096, etc) address = 0; // Other logic is the same if( type == KAllocType.LowAligned ) type = KAllocType.Low; else if( type == KAllocType.HighAligned ) type = KAllocType.High; } // Quick check to see if we have the space free Debug.Assert( FreeSize >= size ); if( FreeSize < size ) return null; switch( type ) { case KAllocType.Specific: { Debug.Assert( address != 0 ); LinkedListEntry<KMemoryBlock> e = FreeList.HeadEntry; while( e != null ) { if( ( address >= e.Value.Address ) && ( address < e.Value.UpperBound ) ) { newBlock = this.SplitBlock( e.Value, address, size ); break; } e = e.Next; } } break; case KAllocType.Low: { KMemoryBlock targetBlock = null; uint maxContig = 0; if( address != 0 ) { // Specified lower limit, find the first block that fits LinkedListEntry<KMemoryBlock> e = FreeList.HeadEntry; while( e != null ) { if( ( address >= e.Value.Address ) && ( address < e.Value.UpperBound ) ) { targetBlock = e.Value; break; } maxContig = Math.Max( maxContig, e.Value.Size ); e = e.Next; } } else { // No lower limit - pick first free block that fits LinkedListEntry<KMemoryBlock> e = FreeList.HeadEntry; while( e != null ) { if( e.Value.Size >= size ) { targetBlock = e.Value; break; } maxContig = Math.Max( maxContig, e.Value.Size ); e = e.Next; } } Debug.Assert( targetBlock != null ); if( targetBlock == null ) { // Try again with a smaller size Log.WriteLine( Verbosity.Critical, Feature.Bios, "KPartition::Allocate could not find enough space" ); //return this.Allocate( KAllocType.Maximum, 0, maxContig ); return null; } Debug.Assert( targetBlock.Size >= size ); if( targetBlock.Size < size ) return null; newBlock = this.SplitBlock( targetBlock, ( address != 0 ) ? address : targetBlock.Address, size ); } break; case KAllocType.High: { Debug.Assert( address == 0 ); KMemoryBlock targetBlock = null; LinkedListEntry<KMemoryBlock> e = FreeList.TailEntry; while( e != null ) { if( e.Value.Size >= size ) { targetBlock = e.Value; break; } e = e.Previous; } Debug.Assert( targetBlock != null ); if( targetBlock == null ) { // Try again with a smaller size Log.WriteLine( Verbosity.Critical, Feature.Bios, "KPartition::Allocate could not find enough space" ); //return this.Allocate( KAllocType.Maximum, 0, maxContig ); return null; } Debug.Assert( ( int )targetBlock.UpperBound - ( int )size >= 0 ); newBlock = this.SplitBlock( targetBlock, targetBlock.UpperBound - size, size ); } break; } if( newBlock != null ) { newBlock.Name = name; newBlock.IsFree = false; FreeSize -= size; } this.Kernel.PrintMemoryInfo(); return newBlock; }
public KMemoryBlock Allocate(string name, KAllocType type, uint address, uint size) { KMemoryBlock newBlock = null; // Round size up to the next word //if( ( size & 0x3 ) != 0 ) // size += 4 - ( size & 0x3 ); if ((type == KAllocType.LowAligned) || (type == KAllocType.HighAligned)) { // TODO: align at 'address' (like 4096, etc) address = 0; // Other logic is the same if (type == KAllocType.LowAligned) { type = KAllocType.Low; } else if (type == KAllocType.HighAligned) { type = KAllocType.High; } } // Quick check to see if we have the space free Debug.Assert(FreeSize >= size); if (FreeSize < size) { return(null); } switch (type) { case KAllocType.Specific: { Debug.Assert(address != 0); LinkedListEntry <KMemoryBlock> e = FreeList.HeadEntry; while (e != null) { if ((address >= e.Value.Address) && (address < e.Value.UpperBound)) { newBlock = this.SplitBlock(e.Value, address, size); break; } e = e.Next; } } break; case KAllocType.Low: { KMemoryBlock targetBlock = null; uint maxContig = 0; if (address != 0) { // Specified lower limit, find the first block that fits LinkedListEntry <KMemoryBlock> e = FreeList.HeadEntry; while (e != null) { if ((address >= e.Value.Address) && (address < e.Value.UpperBound)) { targetBlock = e.Value; break; } maxContig = Math.Max(maxContig, e.Value.Size); e = e.Next; } } else { // No lower limit - pick first free block that fits LinkedListEntry <KMemoryBlock> e = FreeList.HeadEntry; while (e != null) { if (e.Value.Size >= size) { targetBlock = e.Value; break; } maxContig = Math.Max(maxContig, e.Value.Size); e = e.Next; } } Debug.Assert(targetBlock != null); if (targetBlock == null) { // Try again with a smaller size Log.WriteLine(Verbosity.Critical, Feature.Bios, "KPartition::Allocate could not find enough space"); //return this.Allocate( KAllocType.Maximum, 0, maxContig ); return(null); } Debug.Assert(targetBlock.Size >= size); if (targetBlock.Size < size) { return(null); } newBlock = this.SplitBlock(targetBlock, (address != 0) ? address : targetBlock.Address, size); } break; case KAllocType.High: { Debug.Assert(address == 0); KMemoryBlock targetBlock = null; LinkedListEntry <KMemoryBlock> e = FreeList.TailEntry; while (e != null) { if (e.Value.Size >= size) { targetBlock = e.Value; break; } e = e.Previous; } Debug.Assert(targetBlock != null); if (targetBlock == null) { // Try again with a smaller size Log.WriteLine(Verbosity.Critical, Feature.Bios, "KPartition::Allocate could not find enough space"); //return this.Allocate( KAllocType.Maximum, 0, maxContig ); return(null); } Debug.Assert(( int )targetBlock.UpperBound - ( int )size >= 0); newBlock = this.SplitBlock(targetBlock, targetBlock.UpperBound - size, size); } break; } if (newBlock != null) { newBlock.Name = name; newBlock.IsFree = false; FreeSize -= size; } this.Kernel.PrintMemoryInfo(); return(newBlock); }