public MemoryChunkList(MemoryChunk initialMemoryChunk) { low = initialMemoryChunk; high = initialMemoryChunk; }
/// <summary> /// Allocate a memory from the MemoryChunk, at its highest address. /// The MemoryChunk is updated accordingly or is removed if it stays empty. /// </summary> /// <param name="memoryChunk"> the MemoryChunk where the memory should be allocated </param> /// <param name="size"> the size of the memory to be allocated </param> /// <param name="addrAlignment"> base address alignment of the requested block </param> /// <returns> the base address of the allocated memory </returns> private int allocHigh(MemoryChunk memoryChunk, int size, int addrAlignment) { int addr = Utilities.alignDown(memoryChunk.addr + memoryChunk.size, addrAlignment) - size; return(alloc(memoryChunk, addr, size)); }
/// <summary> /// Add a new MemoryChunk to the list. It is added in the list so that /// the addresses are kept in increasing order. /// The MemoryChunk might be merged into another adjacent MemoryChunk. /// </summary> /// <param name="memoryChunk"> the MemoryChunk to be added </param> public virtual void add(MemoryChunk memoryChunk) { // Scan the list to find the insertion point to keep the elements // ordered by increasing address. for (MemoryChunk scanChunk = low; scanChunk != null; scanChunk = scanChunk.next) { // Merge the MemoryChunk if it is adjacent to other elements in the list if (scanChunk.addr + scanChunk.size == memoryChunk.addr) { // The MemoryChunk is adjacent at its lowest address, // merge it into the previous one. scanChunk.size += memoryChunk.size; // Check if the gap to the next chunk has not been closed, // in which case, we can also merge the next chunk. MemoryChunk nextChunk = scanChunk.next; if (nextChunk != null) { if (scanChunk.addr + scanChunk.size == nextChunk.addr) { // Merge with nextChunk scanChunk.size += nextChunk.size; remove(nextChunk); } } return; } else if (memoryChunk.addr + memoryChunk.size == scanChunk.addr) { // The MemoryChunk is adjacent at its highest address, // merge it into the next one. scanChunk.addr = memoryChunk.addr; scanChunk.size += memoryChunk.size; // Check if the gap to the previous chunk has not been closed, // in which case, we can also merge the previous chunk. MemoryChunk previousChunk = scanChunk.previous; if (previousChunk != null) { if (previousChunk.addr + previousChunk.size == scanChunk.addr) { // Merge with previousChunk previousChunk.size += scanChunk.size; remove(scanChunk); } } return; } else if (scanChunk.addr > memoryChunk.addr) { // We have found the insertion point for the MemoryChunk, // add it before this element to keep the addresses in // increasing order. addBefore(memoryChunk, scanChunk); sanityChecks(); return; } } // The MemoryChunk has not yet been added, add it at the very end // of the list. if (high == null && low == null) { // The list is empty, add the element high = memoryChunk; low = memoryChunk; } else { addAfter(memoryChunk, high); } sanityChecks(); }
/// <summary> /// Allocate a memory from the MemoryChunk, at its lowest address. /// The MemoryChunk is updated accordingly or is removed if it stays empty. /// </summary> /// <param name="memoryChunk"> the MemoryChunk where the memory should be allocated </param> /// <param name="size"> the size of the memory to be allocated </param> /// <param name="addrAlignment"> base address alignment of the requested block </param> /// <returns> the base address of the allocated memory </returns> private int allocLow(MemoryChunk memoryChunk, int size, int addrAlignment) { int addr = Utilities.alignUp(memoryChunk.addr, addrAlignment); return(alloc(memoryChunk, addr, size)); }