Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / reactos / ntoskrnl / mm / freelist.c
diff --git a/reactos/ntoskrnl/mm/freelist.c b/reactos/ntoskrnl/mm/freelist.c
deleted file mode 100644 (file)
index 9cff79c..0000000
+++ /dev/null
@@ -1,599 +0,0 @@
-/*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
- * FILE:            ntoskrnl/mm/freelist.c
- * PURPOSE:         Handle the list of free physical pages
- *
- * PROGRAMMERS:     David Welch (welch@cwcom.net)
- *                  Robert Bergkvist
- */
-
-/* INCLUDES ****************************************************************/
-
-#include <ntoskrnl.h>
-#define NDEBUG
-#include <debug.h>
-
-#define MODULE_INVOLVED_IN_ARM3
-#include "ARM3/miarm.h"
-
-#define ASSERT_IS_ROS_PFN(x) ASSERT(MI_IS_ROS_PFN(x) == TRUE);
-
-/* GLOBALS ****************************************************************/
-
-PMMPFN MmPfnDatabase;
-
-PFN_NUMBER MmAvailablePages;
-PFN_NUMBER MmResidentAvailablePages;
-PFN_NUMBER MmResidentAvailableAtInit;
-
-SIZE_T MmTotalCommittedPages;
-SIZE_T MmSharedCommit;
-SIZE_T MmDriverCommit;
-SIZE_T MmProcessCommit;
-SIZE_T MmPagedPoolCommit;
-SIZE_T MmPeakCommitment;
-SIZE_T MmtotalCommitLimitMaximum;
-
-static RTL_BITMAP MiUserPfnBitMap;
-
-/* FUNCTIONS *************************************************************/
-
-VOID
-NTAPI
-MiInitializeUserPfnBitmap(VOID)
-{
-    PVOID Bitmap;
-
-    /* Allocate enough buffer for the PFN bitmap and align it on 32-bits */
-    Bitmap = ExAllocatePoolWithTag(NonPagedPool,
-                                   (((MmHighestPhysicalPage + 1) + 31) / 32) * 4,
-                                   TAG_MM);
-    ASSERT(Bitmap);
-
-    /* Initialize it and clear all the bits to begin with */
-    RtlInitializeBitMap(&MiUserPfnBitMap,
-                        Bitmap,
-                        (ULONG)MmHighestPhysicalPage + 1);
-    RtlClearAllBits(&MiUserPfnBitMap);
-}
-
-PFN_NUMBER
-NTAPI
-MmGetLRUFirstUserPage(VOID)
-{
-    ULONG Position;
-    KIRQL OldIrql;
-
-    /* Find the first user page */
-    OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-    Position = RtlFindSetBits(&MiUserPfnBitMap, 1, 0);
-    KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
-    if (Position == 0xFFFFFFFF) return 0;
-
-    /* Return it */
-    ASSERT(Position != 0);
-    ASSERT_IS_ROS_PFN(MiGetPfnEntry(Position));
-    return Position;
-}
-
-VOID
-NTAPI
-MmInsertLRULastUserPage(PFN_NUMBER Pfn)
-{
-    KIRQL OldIrql;
-
-    /* Set the page as a user page */
-    ASSERT(Pfn != 0);
-    ASSERT_IS_ROS_PFN(MiGetPfnEntry(Pfn));
-    ASSERT(!RtlCheckBit(&MiUserPfnBitMap, (ULONG)Pfn));
-    OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-    RtlSetBit(&MiUserPfnBitMap, (ULONG)Pfn);
-    KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
-}
-
-PFN_NUMBER
-NTAPI
-MmGetLRUNextUserPage(PFN_NUMBER PreviousPfn)
-{
-    ULONG Position;
-    KIRQL OldIrql;
-
-    /* Find the next user page */
-    OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-    Position = RtlFindSetBits(&MiUserPfnBitMap, 1, (ULONG)PreviousPfn + 1);
-    KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
-    if (Position == 0xFFFFFFFF) return 0;
-
-    /* Return it */
-    ASSERT(Position != 0);
-    ASSERT_IS_ROS_PFN(MiGetPfnEntry(Position));
-    return Position;
-}
-
-VOID
-NTAPI
-MmRemoveLRUUserPage(PFN_NUMBER Page)
-{
-    KIRQL OldIrql;
-
-    /* Unset the page as a user page */
-    ASSERT(Page != 0);
-    ASSERT_IS_ROS_PFN(MiGetPfnEntry(Page));
-    ASSERT(RtlCheckBit(&MiUserPfnBitMap, (ULONG)Page));
-    OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-    RtlClearBit(&MiUserPfnBitMap, (ULONG)Page);
-    KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
-}
-
-BOOLEAN
-NTAPI
-MiIsPfnFree(IN PMMPFN Pfn1)
-{
-    /* Must be a free or zero page, with no references, linked */
-    return ((Pfn1->u3.e1.PageLocation <= StandbyPageList) &&
-            (Pfn1->u1.Flink) &&
-            (Pfn1->u2.Blink) &&
-            !(Pfn1->u3.e2.ReferenceCount));
-}
-
-BOOLEAN
-NTAPI
-MiIsPfnInUse(IN PMMPFN Pfn1)
-{
-    /* Standby list or higher, unlinked, and with references */
-    return !MiIsPfnFree(Pfn1);
-}
-
-PMDL
-NTAPI
-MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress,
-                      IN PHYSICAL_ADDRESS HighAddress,
-                      IN PHYSICAL_ADDRESS SkipBytes,
-                      IN SIZE_T TotalBytes,
-                      IN MI_PFN_CACHE_ATTRIBUTE CacheAttribute,
-                      IN ULONG MdlFlags)
-{
-    PMDL Mdl;
-    PFN_NUMBER PageCount, LowPage, HighPage, SkipPages, PagesFound = 0, Page;
-    PPFN_NUMBER MdlPage, LastMdlPage;
-    KIRQL OldIrql;
-    PMMPFN Pfn1;
-    INT LookForZeroedPages;
-    ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
-    DPRINT1("ARM3-DEBUG: Being called with %I64x %I64x %I64x %lx %d %lu\n", LowAddress, HighAddress, SkipBytes, TotalBytes, CacheAttribute, MdlFlags);
-
-    //
-    // Convert the low address into a PFN
-    //
-    LowPage = (PFN_NUMBER)(LowAddress.QuadPart >> PAGE_SHIFT);
-
-    //
-    // Convert, and normalize, the high address into a PFN
-    //
-    HighPage = (PFN_NUMBER)(HighAddress.QuadPart >> PAGE_SHIFT);
-    if (HighPage > MmHighestPhysicalPage) HighPage = MmHighestPhysicalPage;
-
-    //
-    // Validate skipbytes and convert them into pages
-    //
-    if (BYTE_OFFSET(SkipBytes.LowPart)) return NULL;
-    SkipPages = (PFN_NUMBER)(SkipBytes.QuadPart >> PAGE_SHIFT);
-
-    /* This isn't supported at all */
-    if (SkipPages) DPRINT1("WARNING: Caller requesting SkipBytes, MDL might be mismatched\n");
-
-    //
-    // Now compute the number of pages the MDL will cover
-    //
-    PageCount = (PFN_NUMBER)ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, TotalBytes);
-    do
-    {
-        //
-        // Try creating an MDL for these many pages
-        //
-        Mdl = MmCreateMdl(NULL, NULL, PageCount << PAGE_SHIFT);
-        if (Mdl) break;
-
-        //
-        // This function is not required to return the amount of pages requested
-        // In fact, it can return as little as 1 page, and callers are supposed
-        // to deal with this scenario. So re-attempt the allocation with less
-        // pages than before, and see if it worked this time.
-        //
-        PageCount -= (PageCount >> 4);
-    } while (PageCount);
-
-    //
-    // Wow, not even a single page was around!
-    //
-    if (!Mdl) return NULL;
-
-    //
-    // This is where the page array starts....
-    //
-    MdlPage = (PPFN_NUMBER)(Mdl + 1);
-
-    //
-    // Lock the PFN database
-    //
-    OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-
-    //
-    // Are we looking for any pages, without discriminating?
-    //
-    if ((LowPage == 0) && (HighPage == MmHighestPhysicalPage))
-    {
-        //
-        // Well then, let's go shopping
-        //
-        while (PagesFound < PageCount)
-        {
-            /* Grab a page */
-            MI_SET_USAGE(MI_USAGE_MDL);
-            MI_SET_PROCESS2("Kernel");
-
-            /* FIXME: This check should be smarter */
-            Page = 0;
-            if (MmAvailablePages != 0)
-                Page = MiRemoveAnyPage(0);
-
-            if (Page == 0)
-            {
-                /* This is not good... hopefully we have at least SOME pages */
-                ASSERT(PagesFound);
-                break;
-            }
-
-            /* Grab the page entry for it */
-            Pfn1 = MiGetPfnEntry(Page);
-
-            //
-            // Make sure it's really free
-            //
-            ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
-
-            /* Now setup the page and mark it */
-            Pfn1->u3.e2.ReferenceCount = 1;
-            Pfn1->u2.ShareCount = 1;
-            MI_SET_PFN_DELETED(Pfn1);
-            Pfn1->u4.PteFrame = 0x1FFEDCB;
-            Pfn1->u3.e1.StartOfAllocation = 1;
-            Pfn1->u3.e1.EndOfAllocation = 1;
-            Pfn1->u4.VerifierAllocation = 0;
-
-            //
-            // Save it into the MDL
-            //
-            *MdlPage++ = MiGetPfnEntryIndex(Pfn1);
-            PagesFound++;
-        }
-    }
-    else
-    {
-        //
-        // You want specific range of pages. We'll do this in two runs
-        //
-        for (LookForZeroedPages = 1; LookForZeroedPages >= 0; LookForZeroedPages--)
-        {
-            //
-            // Scan the range you specified
-            //
-            for (Page = LowPage; Page < HighPage; Page++)
-            {
-                //
-                // Get the PFN entry for this page
-                //
-                Pfn1 = MiGetPfnEntry(Page);
-                ASSERT(Pfn1);
-
-                //
-                // Make sure it's free and if this is our first pass, zeroed
-                //
-                if (MiIsPfnInUse(Pfn1)) continue;
-                if ((Pfn1->u3.e1.PageLocation == ZeroedPageList) != LookForZeroedPages) continue;
-
-                /* Remove the page from the free or zero list */
-                ASSERT(Pfn1->u3.e1.ReadInProgress == 0);
-                MI_SET_USAGE(MI_USAGE_MDL);
-                MI_SET_PROCESS2("Kernel");
-                MiUnlinkFreeOrZeroedPage(Pfn1);
-
-                //
-                // Sanity checks
-                //
-                ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
-
-                //
-                // Now setup the page and mark it
-                //
-                Pfn1->u3.e2.ReferenceCount = 1;
-                Pfn1->u2.ShareCount = 1;
-                MI_SET_PFN_DELETED(Pfn1);
-                Pfn1->u4.PteFrame = 0x1FFEDCB;
-                Pfn1->u3.e1.StartOfAllocation = 1;
-                Pfn1->u3.e1.EndOfAllocation = 1;
-                Pfn1->u4.VerifierAllocation = 0;
-
-                //
-                // Save this page into the MDL
-                //
-                *MdlPage++ = Page;
-                if (++PagesFound == PageCount) break;
-            }
-
-            //
-            // If the first pass was enough, don't keep going, otherwise, go again
-            //
-            if (PagesFound == PageCount) break;
-        }
-    }
-
-    //
-    // Now release the PFN count
-    //
-    KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
-
-    //
-    // We might've found less pages, but not more ;-)
-    //
-    if (PagesFound != PageCount) ASSERT(PagesFound < PageCount);
-    if (!PagesFound)
-    {
-        //
-        // If we didn' tfind any pages at all, fail
-        //
-        DPRINT1("NO MDL PAGES!\n");
-        ExFreePoolWithTag(Mdl, TAG_MDL);
-        return NULL;
-    }
-
-    //
-    // Write out how many pages we found
-    //
-    Mdl->ByteCount = (ULONG)(PagesFound << PAGE_SHIFT);
-
-    //
-    // Terminate the MDL array if there's certain missing pages
-    //
-    if (PagesFound != PageCount) *MdlPage = LIST_HEAD;
-
-    //
-    // Now go back and loop over all the MDL pages
-    //
-    MdlPage = (PPFN_NUMBER)(Mdl + 1);
-    LastMdlPage = MdlPage + PagesFound;
-    while (MdlPage < LastMdlPage)
-    {
-        //
-        // Check if we've reached the end
-        //
-        Page = *MdlPage++;
-        if (Page == LIST_HEAD) break;
-
-        //
-        // Get the PFN entry for the page and check if we should zero it out
-        //
-        Pfn1 = MiGetPfnEntry(Page);
-        ASSERT(Pfn1);
-        if (Pfn1->u3.e1.PageLocation != ZeroedPageList) MiZeroPhysicalPage(Page);
-        Pfn1->u3.e1.PageLocation = ActiveAndValid;
-    }
-
-    //
-    // We're done, mark the pages as locked
-    //
-    Mdl->Process = NULL;
-    Mdl->MdlFlags |= MDL_PAGES_LOCKED;
-    return Mdl;
-}
-
-VOID
-NTAPI
-MmSetRmapListHeadPage(PFN_NUMBER Pfn, PMM_RMAP_ENTRY ListHead)
-{
-    KIRQL oldIrql;
-    PMMPFN Pfn1;
-
-    oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-    Pfn1 = MiGetPfnEntry(Pfn);
-    ASSERT(Pfn1);
-    ASSERT_IS_ROS_PFN(Pfn1);
-
-    if (ListHead)
-    {
-        /* Should not be trying to insert an RMAP for a non-active page */
-        ASSERT(MiIsPfnInUse(Pfn1) == TRUE);
-
-        /* Set the list head address */
-        Pfn1->RmapListHead = ListHead;
-    }
-    else
-    {
-        /* ReactOS semantics dictate the page is STILL active right now */
-        ASSERT(MiIsPfnInUse(Pfn1) == TRUE);
-
-        /* In this case, the RMAP is actually being removed, so clear field */
-        Pfn1->RmapListHead = NULL;
-
-        /* ReactOS semantics will now release the page, which will make it free and enter a colored list */
-    }
-
-    KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
-}
-
-PMM_RMAP_ENTRY
-NTAPI
-MmGetRmapListHeadPage(PFN_NUMBER Pfn)
-{
-    KIRQL oldIrql;
-    PMM_RMAP_ENTRY ListHead;
-    PMMPFN Pfn1;
-
-    /* Lock PFN database */
-    oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-
-    /* Get the entry */
-    Pfn1 = MiGetPfnEntry(Pfn);
-    ASSERT(Pfn1);
-    ASSERT_IS_ROS_PFN(Pfn1);
-
-    /* Get the list head */
-    ListHead = Pfn1->RmapListHead;
-
-    /* Should not have an RMAP for a non-active page */
-    ASSERT(MiIsPfnInUse(Pfn1) == TRUE);
-
-    /* Release PFN database and return rmap list head */
-    KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
-    return ListHead;
-}
-
-VOID
-NTAPI
-MmSetSavedSwapEntryPage(PFN_NUMBER Pfn,  SWAPENTRY SwapEntry)
-{
-    KIRQL oldIrql;
-    PMMPFN Pfn1;
-
-    Pfn1 = MiGetPfnEntry(Pfn);
-    ASSERT(Pfn1);
-    ASSERT_IS_ROS_PFN(Pfn1);
-
-    oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-    Pfn1->u1.SwapEntry = SwapEntry;
-    KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
-}
-
-SWAPENTRY
-NTAPI
-MmGetSavedSwapEntryPage(PFN_NUMBER Pfn)
-{
-    SWAPENTRY SwapEntry;
-    KIRQL oldIrql;
-    PMMPFN Pfn1;
-
-    Pfn1 = MiGetPfnEntry(Pfn);
-    ASSERT(Pfn1);
-    ASSERT_IS_ROS_PFN(Pfn1);
-
-    oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-    SwapEntry = Pfn1->u1.SwapEntry;
-    KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
-
-    return(SwapEntry);
-}
-
-VOID
-NTAPI
-MmReferencePage(PFN_NUMBER Pfn)
-{
-    PMMPFN Pfn1;
-
-    DPRINT("MmReferencePage(PysicalAddress %x)\n", Pfn << PAGE_SHIFT);
-
-    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
-    ASSERT(Pfn != 0);
-    ASSERT(Pfn <= MmHighestPhysicalPage);
-
-    Pfn1 = MiGetPfnEntry(Pfn);
-    ASSERT(Pfn1);
-    ASSERT_IS_ROS_PFN(Pfn1);
-
-    ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
-    Pfn1->u3.e2.ReferenceCount++;
-}
-
-ULONG
-NTAPI
-MmGetReferenceCountPage(PFN_NUMBER Pfn)
-{
-    KIRQL oldIrql;
-    ULONG RCount;
-    PMMPFN Pfn1;
-
-    DPRINT("MmGetReferenceCountPage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
-
-    oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-    Pfn1 = MiGetPfnEntry(Pfn);
-    ASSERT(Pfn1);
-    ASSERT_IS_ROS_PFN(Pfn1);
-
-    RCount = Pfn1->u3.e2.ReferenceCount;
-
-    KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
-    return(RCount);
-}
-
-BOOLEAN
-NTAPI
-MmIsPageInUse(PFN_NUMBER Pfn)
-{
-    return MiIsPfnInUse(MiGetPfnEntry(Pfn));
-}
-
-VOID
-NTAPI
-MmDereferencePage(PFN_NUMBER Pfn)
-{
-    PMMPFN Pfn1;
-    KIRQL OldIrql;
-    DPRINT("MmDereferencePage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
-
-    OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-
-    Pfn1 = MiGetPfnEntry(Pfn);
-    ASSERT(Pfn1);
-    ASSERT_IS_ROS_PFN(Pfn1);
-
-    ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
-    Pfn1->u3.e2.ReferenceCount--;
-    if (Pfn1->u3.e2.ReferenceCount == 0)
-    {
-        /* Mark the page temporarily as valid, we're going to make it free soon */
-        Pfn1->u3.e1.PageLocation = ActiveAndValid;
-
-        /* It's not a ROS PFN anymore */
-        Pfn1->u4.AweAllocation = FALSE;
-
-        /* Bring it back into the free list */
-        DPRINT("Legacy free: %lx\n", Pfn);
-        MiInsertPageInFreeList(Pfn);
-    }
-
-    KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
-}
-
-PFN_NUMBER
-NTAPI
-MmAllocPage(ULONG Type)
-{
-    PFN_NUMBER PfnOffset;
-    PMMPFN Pfn1;
-    KIRQL OldIrql;
-
-    OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-
-    PfnOffset = MiRemoveZeroPage(MI_GET_NEXT_COLOR());
-    if (!PfnOffset)
-    {
-        KeBugCheck(NO_PAGES_AVAILABLE);
-    }
-
-    DPRINT("Legacy allocate: %lx\n", PfnOffset);
-    Pfn1 = MiGetPfnEntry(PfnOffset);
-    Pfn1->u3.e2.ReferenceCount = 1;
-    Pfn1->u3.e1.PageLocation = ActiveAndValid;
-
-    /* This marks the PFN as a ReactOS PFN */
-    Pfn1->u4.AweAllocation = TRUE;
-
-    /* Allocate the extra ReactOS Data and zero it out */
-    Pfn1->u1.SwapEntry = 0;
-    Pfn1->RmapListHead = NULL;
-
-    KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
-    return PfnOffset;
-}
-
-/* EOF */