Esempio n. 1
0
        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
            }
        }
Esempio n. 2
0
        // 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);
            }
        }
Esempio n. 3
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));
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
        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);
            }
        }