[NTOS]: Manage the PFN lists using the correct Flink/Blink semantics of the MMPFN...
authorSir Richard <sir_richard@svn.reactos.org>
Sat, 20 Feb 2010 14:40:21 +0000 (14:40 +0000)
committerSir Richard <sir_richard@svn.reactos.org>
Sat, 20 Feb 2010 14:40:21 +0000 (14:40 +0000)
[NTOS]: Zero pages starting at the head of the free list, insert them at the back.
[NTOS]: Add MiInsertPageInFreeList to build the colored lists (not yet used) in the ARM3 PFN database.
[NTOS]: Rename the ReactOS PFN lists for free/zero to their real names as used in Windows.

svn path=/trunk/; revision=45634

reactos/ntoskrnl/mm/ARM3/miarm.h
reactos/ntoskrnl/mm/ARM3/pfnlist.c [new file with mode: 0644]
reactos/ntoskrnl/mm/freelist.c
reactos/ntoskrnl/ntoskrnl-generic.rbuild

index 58660e0..f37bd29 100644 (file)
 #error Define these please!
 #endif
 
+//
+// PFN List Sentinel
+//
+#define LIST_HEAD 0xFFFFFFFF
+
 //
 // FIXFIX: These should go in ex.h after the pool merge
 //
@@ -211,6 +216,7 @@ extern ULONG MmSecondaryColorMask;
 extern ULONG MmNumberOfSystemPtes;
 extern ULONG MmMaximumNonPagedPoolPercent;
 extern ULONG MmLargeStackSize;
+extern PMMCOLOR_TABLES MmFreePagesByColor[FreePageList + 1];
 
 #define MI_PFN_TO_PFNENTRY(x)     (&MmPfnDatabase[1][x])
 #define MI_PFNENTRY_TO_PFN(x)     (x - MmPfnDatabase[1])
@@ -374,4 +380,30 @@ MiUnmapLockedPagesInUserSpace(
     IN PMDL Mdl
 );
 
+VOID
+NTAPI
+MiInsertInListTail(
+    IN PMMPFNLIST ListHead,
+    IN PMMPFN Entry
+);
+
+VOID
+NTAPI
+MiRemoveFromList(
+    IN PMMPFN Entry
+);
+
+PMMPFN
+NTAPI
+MiRemoveHeadList(
+    IN PMMPFNLIST ListHead
+);
+
+
+VOID
+NTAPI
+MiInsertPageInFreeList(
+    IN PFN_NUMBER PageFrameIndex
+);
+
 /* EOF */
diff --git a/reactos/ntoskrnl/mm/ARM3/pfnlist.c b/reactos/ntoskrnl/mm/ARM3/pfnlist.c
new file mode 100644 (file)
index 0000000..5765d92
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            ntoskrnl/mm/ARM3/pfnlist.c
+ * PURPOSE:         ARM Memory Manager PFN List Manipulation
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+
+#line 15 "ARMĀ³::PFNLIST"
+#define MODULE_INVOLVED_IN_ARM3
+#include "../ARM3/miarm.h"
+
+/* GLOBALS ********************************************************************/
+
+MMPFNLIST MmZeroedPageListHead;
+MMPFNLIST MmFreePageListHead;
+MMPFNLIST MmStandbyPageListHead;
+MMPFNLIST MmModifiedPageListHead;
+MMPFNLIST MmModifiedNoWritePageListHead;
+
+/* FUNCTIONS ******************************************************************/
+
+VOID
+NTAPI
+MiInsertInListTail(IN PMMPFNLIST ListHead,
+                   IN PMMPFN Entry)
+{
+    PFN_NUMBER OldBlink, EntryIndex = MiGetPfnEntryIndex(Entry);
+
+    /* Get the back link */
+    OldBlink = ListHead->Blink;
+    if (OldBlink != LIST_HEAD)
+    {
+        /* Set the back pointer to point to us now */
+        MiGetPfnEntry(OldBlink)->u1.Flink = EntryIndex;
+    }
+    else
+    {
+        /* Set the list to point to us */
+        ListHead->Flink = EntryIndex;
+    }
+    
+    /* Set the entry to point to the list head forwards, and the old page backwards */
+    Entry->u1.Flink = LIST_HEAD;
+    Entry->u2.Blink = OldBlink;
+    
+    /* And now the head points back to us, since we are last */
+    ListHead->Blink = EntryIndex;
+    ListHead->Total++;
+}
+
+VOID
+NTAPI
+MiRemoveFromList(IN PMMPFN Entry)
+{
+    PFN_NUMBER OldFlink, OldBlink;
+    PMMPFNLIST ListHead;
+    
+    /* Find the list for this */
+    if (Entry->u3.e1.PageLocation == ZeroedPageList)
+    {
+        ListHead = &MmZeroedPageListHead;
+    }
+    else if (Entry->u3.e1.PageLocation == FreePageList)
+    {
+        ListHead = &MmFreePageListHead;
+    }
+    else
+    {
+        ListHead = NULL;
+        ASSERT(ListHead != NULL);
+    }
+    
+    /* Get the forward and back pointers */
+    OldFlink = Entry->u1.Flink;
+    OldBlink = Entry->u2.Blink;
+    
+    /* Check if the next entry is the list head */
+    if (OldFlink != LIST_HEAD)
+    {
+        /* It is not, so set the backlink of the actual entry, to our backlink */
+        MiGetPfnEntry(OldFlink)->u2.Blink = OldBlink;
+    }
+    else
+    {
+        /* Set the list head's backlink instead */
+        ListHead->Blink = OldFlink;
+    }
+    
+    /* Check if the back entry is the list head */
+    if (OldBlink != LIST_HEAD)
+    {
+        /* It is not, so set the backlink of the actual entry, to our backlink */
+        MiGetPfnEntry(OldBlink)->u1.Flink = OldFlink;
+    }
+    else
+    {
+        /* Set the list head's backlink instead */
+        ListHead->Flink = OldFlink;
+    }
+    
+    /* We are not on a list anymore */
+    ListHead->Total--;
+    Entry->u1.Flink = Entry->u2.Blink = 0;
+}
+
+PMMPFN
+NTAPI
+MiRemoveHeadList(IN PMMPFNLIST ListHead)
+{
+    PFN_NUMBER Entry, Flink;
+    PMMPFN Pfn1;
+    
+    /* Get the entry that's currently first on the list */
+    Entry = ListHead->Flink;
+    Pfn1 = MiGetPfnEntry(Entry);
+    
+    /* Make the list point to the entry following the first one */
+    Flink = Pfn1->u1.Flink;
+    ListHead->Flink = Flink;
+
+    /* Check if the next entry is actually the list head */
+    if (ListHead->Flink != LIST_HEAD)
+    {
+        /* It isn't, so therefore whoever is coming next points back to the head */
+        MiGetPfnEntry(Flink)->u2.Blink = LIST_HEAD;
+    }
+    else
+    {
+        /* Then the list is empty, so the backlink should point back to us */
+        ListHead->Blink = LIST_HEAD;
+    }
+  
+    /* We are not on a list anymore */
+    Pfn1->u1.Flink = Pfn1->u2.Blink = 0;
+    ListHead->Total--;
+    
+    /* Return the head element */
+    return Pfn1;
+}
+
+VOID
+NTAPI
+MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
+{
+    MMLISTS ListName;
+    PMMPFNLIST ListHead;
+    PFN_NUMBER LastPage;
+    PMMPFN Pfn1, Blink;
+    ULONG Color;
+    PMMCOLOR_TABLES ColorHead;
+
+    /* Make sure the page index is valid */
+    ASSERT((PageFrameIndex != 0) &&
+           (PageFrameIndex <= MmHighestPhysicalPage) &&
+           (PageFrameIndex >= MmLowestPhysicalPage));
+
+    /* Get the PFN entry */
+    Pfn1 = MI_PFN_TO_PFNENTRY(PageFrameIndex);
+
+    /* Sanity checks that a right kind of page is being inserted here */
+    ASSERT(Pfn1->u4.MustBeCached == 0);
+    ASSERT(Pfn1->u3.e1.Rom != 1);
+    ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
+    ASSERT(Pfn1->u4.VerifierAllocation == 0);
+    ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
+
+    /* Get the free page list and increment its count */
+    ListHead = &MmFreePageListHead;
+    ListName = FreePageList;
+    ListHead->Total++;
+
+    /* Get the last page on the list */
+    LastPage = ListHead->Blink;
+    if (LastPage != -1)
+    {
+        /* Link us with the previous page, so we're at the end now */
+        MI_PFN_TO_PFNENTRY(LastPage)->u1.Flink = PageFrameIndex;
+    }
+    else
+    {
+        /* The list is empty, so we are the first page */
+        ListHead->Flink = PageFrameIndex;
+    }
+
+    /* Now make the list head point back to us (since we go at the end) */
+    ListHead->Blink = PageFrameIndex;
+    
+    /* And initialize our own list pointers */
+    Pfn1->u1.Flink = -1;
+    Pfn1->u2.Blink = LastPage;
+
+    /* Set the list name and default priority */
+    Pfn1->u3.e1.PageLocation = ListName;
+    Pfn1->u4.Priority = 3;
+    
+    /* Clear some status fields */
+    Pfn1->u4.InPageError = 0;
+    Pfn1->u4.AweAllocation = 0;
+
+    /* FIXME: More work to be done regarding page accounting */
+
+    /* Get the page color */
+    Color = PageFrameIndex & MmSecondaryColorMask;
+
+    /* Get the first page on the color list */
+    ColorHead = &MmFreePagesByColor[ListName][Color];
+    if (ColorHead->Flink == -1)
+    {
+        /* The list is empty, so we are the first page */
+        Pfn1->u4.PteFrame = -1;
+        ColorHead->Flink = PageFrameIndex;
+    }
+    else
+    {
+        /* Get the previous page */
+        Blink = (PMMPFN)ColorHead->Blink;
+        
+        /* Make it link to us */
+        Pfn1->u4.PteFrame = MI_PFNENTRY_TO_PFN(Blink);
+        Blink->OriginalPte.u.Long = PageFrameIndex;
+    }
+    
+    /* Now initialize our own list pointers */
+    ColorHead->Blink = Pfn1;
+    Pfn1->OriginalPte.u.Long = -1;
+    
+    /* And increase the count in the colored list */
+    ColorHead->Count++;
+    
+    /* FIXME: Notify zero page thread if enough pages are on the free list now */
+}
+
+/* EOF */
index 25e57ef..6175fad 100644 (file)
@@ -31,9 +31,6 @@
 //
 #define RmapListHead         AweReferenceCount
 #define SavedSwapEntry       u4.EntireFrame
-#define RemoveEntryList(x)   RemoveEntryList((PLIST_ENTRY)x)
-#define InsertTailList(x, y) InsertTailList(x, (PLIST_ENTRY)y)
-#define ListEntry            u1
 #define PHYSICAL_PAGE        MMPFN
 #define PPHYSICAL_PAGE       PMMPFN
 
@@ -52,25 +49,8 @@ SIZE_T MmPagedPoolCommit;
 SIZE_T MmPeakCommitment; 
 SIZE_T MmtotalCommitLimitMaximum;
 
-MMPFNLIST MmZeroedPageListHead;
-MMPFNLIST MmFreePageListHead;
-MMPFNLIST MmStandbyPageListHead;
-MMPFNLIST MmModifiedPageListHead;
-MMPFNLIST MmModifiedNoWritePageListHead;
-
-/* List of pages zeroed by the ZPW (MmZeroPageThreadMain) */
-static LIST_ENTRY FreeZeroedPageListHead;
-/* List of free pages, filled by MmGetReferenceCountPage and
- * and MmInitializePageList */
-static LIST_ENTRY FreeUnzeroedPageListHead;
-
 static KEVENT ZeroPageThreadEvent;
 static BOOLEAN ZeroPageThreadShouldTerminate = FALSE;
-
-static ULONG UnzeroedPageCount = 0;
-
-/* FUNCTIONS *************************************************************/
-
 static RTL_BITMAP MiUserPfnBitMap;
 
 /* FUNCTIONS *************************************************************/
@@ -153,7 +133,7 @@ NTAPI
 MiIsPfnInUse(IN PMMPFN Pfn1)
 {
     return ((Pfn1->u3.e1.PageLocation != FreePageList) &&
-            (Pfn1->u3.e1.PageLocation != ZeroedPageList));    
+            (Pfn1->u3.e1.PageLocation != ZeroedPageList));
 }
 
 PFN_NUMBER
@@ -265,11 +245,6 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
                         EndPfn = Pfn1 - SizeInPages + 1;
                         do
                         {
-                            //
-                            // If this was an unzeroed page, there are now less
-                            //
-                            if (Pfn1->u3.e1.PageLocation == ZeroedPageList) UnzeroedPageCount--;
-                            
                             //
                             // One less free page
                             //
@@ -278,7 +253,7 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
                             //
                             // This PFN is now a used page, set it up
                             //
-                            RemoveEntryList(&Pfn1->ListEntry);
+                            MiRemoveFromList(Pfn1);
                             Pfn1->u3.e2.ReferenceCount = 1;
                             Pfn1->SavedSwapEntry = 0;
                             
@@ -368,7 +343,6 @@ MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress,
     PFN_NUMBER PageCount, LowPage, HighPage, SkipPages, PagesFound = 0, Page;
     PPFN_NUMBER MdlPage, LastMdlPage;
     KIRQL OldIrql;
-    PLIST_ENTRY ListEntry;
     PPHYSICAL_PAGE Pfn1;
     INT LookForZeroedPages;
     ASSERT (KeGetCurrentIrql() <= APC_LEVEL);
@@ -439,20 +413,19 @@ MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress,
             //
             // Do we have zeroed pages?
             //
-            if (!IsListEmpty(&FreeZeroedPageListHead))
+            if (MmZeroedPageListHead.Total)
             {
                 //
                 // Grab a zero page
                 //
-                ListEntry = RemoveTailList(&FreeZeroedPageListHead);
+                Pfn1 = MiRemoveHeadList(&MmZeroedPageListHead);
             }
-            else if (!IsListEmpty(&FreeUnzeroedPageListHead))
+            else if (MmFreePageListHead.Total)
             {
                 //
                 // Nope, grab an unzeroed page
                 //
-                ListEntry = RemoveTailList(&FreeUnzeroedPageListHead);
-                UnzeroedPageCount--;
+                Pfn1 = MiRemoveHeadList(&MmFreePageListHead);
             }
             else
             {
@@ -463,11 +436,6 @@ MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress,
                 break;
             }
             
-            //
-            // Get the PFN entry for this page
-            //
-            Pfn1 = CONTAINING_RECORD(ListEntry, PHYSICAL_PAGE, ListEntry);
-            
             //
             // Make sure it's really free
             //
@@ -530,12 +498,7 @@ MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress,
                 Pfn1->u3.e1.StartOfAllocation = 1;
                 Pfn1->u3.e1.EndOfAllocation = 1;
                 Pfn1->SavedSwapEntry = 0;
-                
-                //
-                // If this page was unzeroed, we've consumed such a page
-                //
-                if (Pfn1->u3.e1.PageLocation != ZeroedPageList) UnzeroedPageCount--;
-                
+                                
                 //
                 // Decrease available pages
                 //
@@ -681,8 +644,10 @@ MmInitializePageList(VOID)
     ULONG NrSystemPages = 0;
 
     /* Initialize the page lists */
-    InitializeListHead(&FreeUnzeroedPageListHead);
-    InitializeListHead(&FreeZeroedPageListHead);
+     MmFreePageListHead.Flink = MmFreePageListHead.Blink = LIST_HEAD;
+     MmZeroedPageListHead.Flink = MmZeroedPageListHead.Blink = LIST_HEAD;
+     MmZeroedPageListHead.Total = 0;
+     MmFreePageListHead.Total = 0;
 
     /* This is what a used page looks like */
     RtlZeroMemory(&UsedPage, sizeof(UsedPage));
@@ -694,12 +659,10 @@ MmInitializePageList(VOID)
          NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
          NextEntry = NextEntry->Flink)
     {
-#undef ListEntry
         /* Get the descriptor */
         Md = CONTAINING_RECORD(NextEntry,
                                MEMORY_ALLOCATION_DESCRIPTOR,
                                ListEntry);
-#define ListEntry            u1        
 
         /* Skip bad memory */
         if ((Md->MemoryType == LoaderFirmwarePermanent) ||
@@ -722,9 +685,8 @@ MmInitializePageList(VOID)
             {
                 /* Mark it as a free page */
                 MmPfnDatabase[0][Md->BasePage + i].u3.e1.PageLocation = FreePageList;
-                InsertTailList(&FreeUnzeroedPageListHead,
-                               &MmPfnDatabase[0][Md->BasePage + i].ListEntry);
-                UnzeroedPageCount++;
+                MiInsertInListTail(&MmFreePageListHead,
+                                   &MmPfnDatabase[0][Md->BasePage + i]);
                 MmAvailablePages++;
             }
         }
@@ -873,10 +835,8 @@ MmDereferencePage(PFN_TYPE Pfn)
    {
       MmAvailablePages++;
       Page->u3.e1.PageLocation = FreePageList;
-      InsertTailList(&FreeUnzeroedPageListHead,
-                     &Page->ListEntry);
-      UnzeroedPageCount++;
-      if (UnzeroedPageCount > 8 && 0 == KeReadStateEvent(&ZeroPageThreadEvent))
+      MiInsertInListTail(&MmFreePageListHead, Page);
+      if (MmFreePageListHead.Total > 8 && 0 == KeReadStateEvent(&ZeroPageThreadEvent))
       {
          KeSetEvent(&ZeroPageThreadEvent, IO_NO_INCREMENT, FALSE);
       }
@@ -888,16 +848,15 @@ NTAPI
 MmAllocPage(ULONG Type, SWAPENTRY SwapEntry)
 {
    PFN_TYPE PfnOffset;
-   PLIST_ENTRY ListEntry;
    PPHYSICAL_PAGE PageDescriptor;
    BOOLEAN NeedClear = FALSE;
 
    DPRINT("MmAllocPage()\n");
 
-   if (IsListEmpty(&FreeZeroedPageListHead))
+   if (MmZeroedPageListHead.Total == 0)
    {
-      if (IsListEmpty(&FreeUnzeroedPageListHead))
-      {
+       if (MmFreePageListHead.Total == 0)
+       {
          /* Check if this allocation is for the PFN DB itself */
          if (MmNumberOfPhysicalPages == 0) 
          {
@@ -907,18 +866,13 @@ MmAllocPage(ULONG Type, SWAPENTRY SwapEntry)
          DPRINT1("MmAllocPage(): Out of memory\n");
          return 0;
       }
-      ListEntry = RemoveTailList(&FreeUnzeroedPageListHead);
-      UnzeroedPageCount--;
-
-      PageDescriptor = CONTAINING_RECORD(ListEntry, PHYSICAL_PAGE, ListEntry);
+      PageDescriptor = MiRemoveHeadList(&MmFreePageListHead);
 
       NeedClear = TRUE;
    }
    else
    {
-      ListEntry = RemoveTailList(&FreeZeroedPageListHead);
-
-      PageDescriptor = CONTAINING_RECORD(ListEntry, PHYSICAL_PAGE, ListEntry);
+      PageDescriptor = MiRemoveHeadList(&MmZeroedPageListHead);
    }
 
    PageDescriptor->u3.e2.ReferenceCount = 1;
@@ -931,7 +885,7 @@ MmAllocPage(ULONG Type, SWAPENTRY SwapEntry)
    {
       MiZeroPage(PfnOffset);
    }
-   
+     
    PageDescriptor->u3.e1.PageLocation = ActiveAndValid;
    return PfnOffset;
 }
@@ -961,7 +915,6 @@ MmZeroPageThreadMain(PVOID Ignored)
 {
    NTSTATUS Status;
    KIRQL oldIrql;
-   PLIST_ENTRY ListEntry;
    PPHYSICAL_PAGE PageDescriptor;
    PFN_TYPE Pfn;
    ULONG Count;
@@ -988,11 +941,9 @@ MmZeroPageThreadMain(PVOID Ignored)
       }
       Count = 0;
       oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-      while (!IsListEmpty(&FreeUnzeroedPageListHead))
+      while (MmFreePageListHead.Total)
       {
-         ListEntry = RemoveTailList(&FreeUnzeroedPageListHead);
-         UnzeroedPageCount--;
-         PageDescriptor = CONTAINING_RECORD(ListEntry, PHYSICAL_PAGE, ListEntry);
+         PageDescriptor = MiRemoveHeadList(&MmFreePageListHead);
          /* We set the page to used, because MmCreateVirtualMapping failed with unused pages */
          KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
          Pfn = PageDescriptor - MmPfnDatabase[0];
@@ -1001,15 +952,14 @@ MmZeroPageThreadMain(PVOID Ignored)
          oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
          if (NT_SUCCESS(Status))
          {
-            InsertHeadList(&FreeZeroedPageListHead, ListEntry);
+            MiInsertInListTail(&MmZeroedPageListHead, PageDescriptor);
             PageDescriptor->u3.e1.PageLocation = ZeroedPageList;
             Count++;
          }
          else
          {
-            InsertHeadList(&FreeUnzeroedPageListHead, ListEntry);
+            MiInsertInListTail(&MmFreePageListHead, PageDescriptor);
             PageDescriptor->u3.e1.PageLocation = FreePageList;
-            UnzeroedPageCount++;
          }
 
       }
index 7a438c1..abf3219 100644 (file)
                        <file>mmsup.c</file>
                        <file>ncache.c</file>
                        <file>pagfault.c</file>
+                       <file>pfnlist.c</file>
                        <file>pool.c</file>
                        <file>procsup.c</file>
                        <file>syspte.c</file>