internal static unsafe FreeNode *Create(PhysicalHeap *inHeap, UIntPtr addr, UIntPtr pages) { DebugStub.Assert(addr >= inHeap->startAddr); DebugStub.Assert((addr + (pages * MemoryManager.PageSize)) <= inHeap->heapLimit); FreeNode *node = (FreeNode *)addr; // This had better be a free page in the main table DebugStub.Assert(inHeap->PageWord(inHeap->PageIndex(addr)) == FreePage, "Creating a FreeNode for non-free page {0:x}", __arglist(addr)); node->signature = FreeNode.Signature; node->bytes = pages * MemoryManager.PageSize; node->prev = null; node->next = null; node->last = null; if (pages > 1) { node->last = LastNode.Create(inHeap, addr, node); } return(node); }
internal static unsafe LastNode *Create(PhysicalHeap *inHeap, UIntPtr addr, FreeNode *node) { LastNode *last = (LastNode *)(addr + node->bytes - MemoryManager.PageSize); DebugStub.Assert((UIntPtr)last >= inHeap->startAddr); DebugStub.Assert((UIntPtr)last <= inHeap->heapLimit); DebugStub.Assert(MemoryManager.IsPageAligned((UIntPtr)last)); last->signature = LastNode.Signature; last->node = node; return(last); }
internal unsafe void CreateAndInsert(PhysicalHeap *inHeap, UIntPtr addr, UIntPtr pages) { DebugStub.Assert(MemoryManager.IsPageAligned(addr), "PhysicalHeap.CreateAndInsert non page-aligned addr={0:x}", __arglist(addr)); FreeNode *node = FreeNode.Create(inHeap, addr, pages); DebugStub.Assert(MemoryManager.IsPageAligned(node->bytes), "PhysicalHeap.CreateAndInsert non page-sized node->bytes={0:x}", __arglist(node->bytes)); InsertBySize(node); }
internal static unsafe FreeNode *GetNodeFromLast(PhysicalHeap *inHeap, UIntPtr addr) { UIntPtr idx = inHeap->PageIndex(addr); // addr must specify a free page if (inHeap->PageWord(idx) != FreePage) { // addr does not specify a LastNode return(null); } // addr must specify a page such that the next page (if there // is one) is not free if ((idx != inHeap->pageCount - 1) && (inHeap->PageWord(idx + 1) == FreePage)) { return(null); } if (idx == 0) { // This is a one-page block DebugStub.Assert(((FreeNode *)addr)->signature == FreeNode.Signature); return((FreeNode *)addr); } // If the preceding page is free, then addr specifies // the last page in a multi-page block, otherwise it // specifies the only page in a one-page block. if (inHeap->PageWord(idx - 1) == FreePage) { DebugStub.Assert(((LastNode *)addr)->signature == Signature); return(((LastNode *)addr)->node); } else { DebugStub.Assert(((FreeNode *)addr)->signature == FreeNode.Signature); return((FreeNode *)addr); } }
internal static unsafe FreeNode *GetNodeAt(PhysicalHeap *inHeap, UIntPtr addr) { UIntPtr idx = inHeap->PageIndex(addr); if (inHeap->PageWord(idx) != FreePage) { // This address designates a page that is in use. return(null); } if ((idx > 0) && (inHeap->PageWord(idx - 1) == FreePage)) { // This address is in the middle of a free block; it does // not designate the beginning of a free block. return(null); } DebugStub.Assert(((FreeNode *)addr)->signature == Signature); return((FreeNode *)addr); }