internal static void Initialize(UIntPtr systemMemorySize) { allocPtr = MemoryManager.AllocateMemory(systemMemorySize); limitPtr = allocPtr + systemMemorySize; if (GC.gcType != GCType.NullCollector) { PageManager.SetStaticDataPages(allocPtr, systemMemorySize); #if !SINGULARITY PageTable.SetProcess(PageTable.Page(allocPtr), PageTable.PageCount(systemMemorySize)); #endif } }
// Tell the GC that a certain data area is no longer allowed to // contain off-limits, non-moveable data. private static unsafe void SetUnallocatedPages(UIntPtr startAddr, UIntPtr size) { UIntPtr startPage = PageTable.Page(startAddr); UIntPtr endAddr = startAddr + size; UIntPtr endPage = PageTable.Page(endAddr); UIntPtr pageCount = endPage - startPage; if (pageCount == 1) { PageTable.SetExtra(startPage, 0); PageTable.SetType(startPage, PageType.Unallocated); PageTable.SetProcess(startPage, 0); } else { PageTable.SetExtra(startPage, pageCount, 0); PageTable.SetType(startPage, pageCount, PageType.Unallocated); PageTable.SetProcess(startPage, pageCount, 0); } }
// Low-level routines based on the operating system interface private static unsafe UIntPtr AllocateMemoryHelper(UIntPtr startAddr, UIntPtr size) { void *result = VirtualAlloc((void *)startAddr, size, MEM_RESERVE, PAGE_READWRITE); VTable.Assert (PageTable.Page((UIntPtr)result + size - 1) < PageTable.pageTableCount, "OutOfMemory: MemoryManager: memory doesn't fit in page table"); if (result != null) { Trace.Log(Trace.Area.Page, "VirtualAlloc {0} at {1}", __arglist(size, result)); VTable.Assert((startAddr == UIntPtr.Zero) || (result == (void *)startAddr)); void *area = VirtualAlloc(result, size, MEM_COMMIT, PAGE_READWRITE); if (PageTable.halPageDescriptor != null) { PageTable.CreateNewPageTablesIfNecessary(PageTable.Page((UIntPtr)result), PageTable.PageCount(size)); PageTable.SetProcess(PageTable.Page((UIntPtr)area), PageTable.PageCount(size)); } VTable.Assert(result == area); #if HIMEM // This assertion intends only to catch bugs in Bartok. But if // the system (windows) frees memory before, the memory // may be in low memory, and if we happen to get that // memory, this assertion itself may not hold VTable.Assert((UIntPtr)result >= PageTable.HIMEMStart, ("High memory is expected to be allocated in HIMEM mode")); #endif } return(new UIntPtr(result)); }
private static void SetPageTypeClean(UIntPtr startPage, UIntPtr pageCount, PageType newType) { UIntPtr *tableAddr = (UIntPtr *)PageTable.PageAddr(startPage); UIntPtr *tableCursor = tableAddr + 1; UIntPtr dirtyCount = UIntPtr.Zero; UIntPtr endPage = startPage + pageCount; for (UIntPtr i = startPage; i < endPage; i++) { PageType pageType = PageTable.Type(i); if (pageType == PageType.UnusedDirty) { PageTable.SetType(i, newType); UIntPtr j = i + 1; while (j < endPage && PageTable.Type(j) == PageType.UnusedDirty) { PageTable.SetType(j, newType); j++; } UIntPtr dirtyStartAddr = PageTable.PageAddr(i); UIntPtr dirtyEndAddr = PageTable.PageAddr(j); * tableCursor++ = dirtyStartAddr; * tableCursor++ = dirtyEndAddr - dirtyStartAddr; dirtyCount++; i = j - 1; } else { PageTable.SetType(i, newType); } } *tableAddr = dirtyCount; PageTable.SetProcess(startPage, pageCount); }
internal static UIntPtr EnsurePages(Thread currentThread, UIntPtr pageCount, PageType newType, ref bool fCleanPages) { if (currentThread != null) { GC.CheckForNeededGCWork(currentThread); } VTable.Deny(PageTable.IsUnusedPageType(newType)); // Try to find already allocated but unused pages UIntPtr foundPages = FindUnusedPages(currentThread, pageCount, newType); if (foundPages != UIntPtr.Zero) { if (fCleanPages) { CleanFoundPages(foundPages); } else { fCleanPages = FoundOnlyCleanPages(foundPages); } return(foundPages); } // We need to allocate new pages bool iflag = EnterMutex(currentThread); try { UIntPtr bytesNeeded = PageTable.RegionSize(pageCount); UIntPtr allocSize = Util.Pad(bytesNeeded, heap_commit_size); UIntPtr startAddr = MemoryManager.AllocateMemory(allocSize); if (startAddr == UIntPtr.Zero) { if (heap_commit_size > os_commit_size) { allocSize = Util.Pad(bytesNeeded, os_commit_size); startAddr = MemoryManager.AllocateMemory(allocSize); } } if (startAddr == UIntPtr.Zero) { // BUGBUG: if in CMS, should wait on one complete GC cycle and // the retry. for STW, we may get here even if the collector // hasn't triggered just prior. PageTable.Dump("Out of memory"); throw outOfMemoryException; } UIntPtr startPage = PageTable.Page(startAddr); PageTable.SetType(startPage, pageCount, newType); PageTable.SetProcess(startPage, pageCount); UIntPtr extraPages = PageTable.PageCount(allocSize) - pageCount; if (extraPages > 0) { // Mark the new memory pages as allocated-but-unused MarkUnusedPages(/* avoid recursive locking */ null, startPage + pageCount, extraPages, true); } return(startPage); } finally { LeaveMutex(currentThread, iflag); } }