/// <summary> /// Marks a range of memory as consumed by removing it from the tree. /// This function will split memory regions if there is available space. /// </summary> /// <param name="va">Virtual address at which to allocate</param> /// <param name="size">Size of the allocation in bytes</param> /// <param name="referenceAddress">Reference to the address of memory where the allocation can take place</param> #region Memory Allocation public void AllocateRange(ulong va, ulong size, ulong referenceAddress = InvalidAddress) { lock (_tree) { Logger.Debug?.Print(LogClass.ServiceNv, $"Allocating range from 0x{va:X} to 0x{(va + size):X}."); if (referenceAddress != InvalidAddress) { ulong endAddress = va + size; ulong referenceEndAddress = _tree.Get(referenceAddress); if (va >= referenceAddress) { // Need Left Node if (va > referenceAddress) { ulong leftEndAddress = va; // Overwrite existing block with its new smaller range. _tree.Add(referenceAddress, leftEndAddress); Logger.Debug?.Print(LogClass.ServiceNv, $"Created smaller address range from 0x{referenceAddress:X} to 0x{leftEndAddress:X}."); } else { // We need to get rid of the large chunk. _tree.Remove(referenceAddress); } ulong rightSize = referenceEndAddress - endAddress; // If leftover space, create a right node. if (rightSize > 0) { Logger.Debug?.Print(LogClass.ServiceNv, $"Created smaller address range from 0x{endAddress:X} to 0x{referenceEndAddress:X}."); _tree.Add(endAddress, referenceEndAddress); LinkedListNode <ulong> node = _list.AddAfter(_dictionary[referenceAddress], endAddress); _dictionary[endAddress] = node; } if (va == referenceAddress) { _list.Remove(_dictionary[referenceAddress]); _dictionary.Remove(referenceAddress); } } } } }