[NTOS]: When expanding paged pool, use MiRemoveAnyPage, not MmAllocPage.
[reactos.git] / reactos / ntoskrnl / mm / ARM3 / pfnlist.c
index b70e191..00afacf 100644 (file)
 #define MODULE_INVOLVED_IN_ARM3
 #include "../ARM3/miarm.h"
 
+#if DBG
+#define ASSERT_LIST_INVARIANT(x) \
+do { \
+       ASSERT(((x)->Total == 0 && \
+            (x)->Flink == LIST_HEAD && \
+                       (x)->Blink == LIST_HEAD) || \
+                  ((x)->Total != 0 && \
+                       (x)->Flink != LIST_HEAD && \
+                       (x)->Blink != LIST_HEAD)); \
+} while (0)
+#else
+#define ASSERT_LIST_INVARIANT(x)
+#endif
+
 /* GLOBALS ********************************************************************/
 
 BOOLEAN MmDynamicPfn;
@@ -48,6 +62,8 @@ MiInsertInListTail(IN PMMPFNLIST ListHead,
                    IN PMMPFN Entry)
 {
     PFN_NUMBER OldBlink, EntryIndex = MiGetPfnEntryIndex(Entry);
+    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+    ASSERT_LIST_INVARIANT(ListHead);
 
     /* Get the back link */
     OldBlink = ListHead->Blink;
@@ -69,6 +85,7 @@ MiInsertInListTail(IN PMMPFNLIST ListHead,
     /* And now the head points back to us, since we are last */
     ListHead->Blink = EntryIndex;
     ListHead->Total++;
+       ASSERT_LIST_INVARIANT(ListHead);
 }
 
 VOID
@@ -97,6 +114,7 @@ MiInsertZeroListAtBack(IN PFN_NUMBER EntryIndex)
     
     /* Use the zero list */
     ListHead = &MmZeroedPageListHead;
+    ASSERT_LIST_INVARIANT(ListHead);
     ListHead->Total++;
 
     /* Get the back link */
@@ -118,6 +136,7 @@ MiInsertZeroListAtBack(IN PFN_NUMBER EntryIndex)
     
     /* And now the head points back to us, since we are last */
     ListHead->Blink = EntryIndex;
+       ASSERT_LIST_INVARIANT(ListHead);
     
     /* Update the page location */
     Pfn1->u3.e1.PageLocation = ZeroedPageList;
@@ -136,6 +155,7 @@ MiInsertZeroListAtBack(IN PFN_NUMBER EntryIndex)
         /* Otherwise check if we reached the high threshold and signal the event */
         KeSetEvent(MiHighMemoryEvent, 0, FALSE);
     }
+
 #if 0
     /* Get the page color */
     Color = EntryIndex & MmSecondaryColorMask;
@@ -177,7 +197,7 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry)
     
     /* Make sure the PFN lock is held */
     ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
-    
+
     /* Make sure the PFN entry isn't in-use */
     ASSERT(Entry->u3.e1.WriteInProgress == 0);
     ASSERT(Entry->u3.e1.ReadInProgress == 0);
@@ -187,7 +207,8 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry)
     ListName = ListHead->ListName;
     ASSERT(ListHead != NULL);
     ASSERT(ListName <= FreePageList);
-    
+    ASSERT_LIST_INVARIANT(ListHead);
+
     /* Remove one count */
     ASSERT(ListHead->Total != 0);
     ListHead->Total--;
@@ -205,7 +226,7 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry)
     else
     {
         /* Set the list head's backlink instead */
-        ListHead->Blink = OldFlink;
+        ListHead->Blink = OldBlink;
     }
     
     /* Check if the back entry is the list head */
@@ -222,7 +243,8 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry)
     
     /* We are not on a list anymore */
     Entry->u1.Flink = Entry->u2.Blink = 0;
-    
+    ASSERT_LIST_INVARIANT(ListHead);
+
     /* FIXME: Deal with color list */
     
     /* See if we hit any thresholds */
@@ -272,6 +294,7 @@ MiRemovePageByColor(IN PFN_NUMBER PageIndex,
 
     /* Could be either on free or zero list */
     ListHead = MmPageLocationList[Pfn1->u3.e1.PageLocation];
+    ASSERT_LIST_INVARIANT(ListHead);
     ListName = ListHead->ListName;
     ASSERT(ListName <= FreePageList);
     
@@ -307,12 +330,14 @@ MiRemovePageByColor(IN PFN_NUMBER PageIndex,
     }
     
     /* We are not on a list anymore */
+       ASSERT_LIST_INVARIANT(ListHead);
     Pfn1->u1.Flink = Pfn1->u2.Blink = 0;
     
     /* Zero flags but restore color and cache */
     Pfn1->u3.e2.ShortFlags = 0;
     Pfn1->u3.e1.PageColor = OldColor;
     Pfn1->u3.e1.CacheAttribute = OldCache;
+
 #if 0 // When switching to ARM3
     /* Get the first page on the color list */
     ColorTable = &MmFreePagesByColor[ListName][Color];
@@ -379,12 +404,13 @@ MiRemoveAnyPage(IN ULONG Color)
         {
 #endif
             /* Check the free list */
+            ASSERT_LIST_INVARIANT(&MmFreePageListHead);
             PageIndex = MmFreePageListHead.Flink;
             Color = PageIndex & MmSecondaryColorMask;
             if (PageIndex == LIST_HEAD)
             {
                 /* Check the zero list */
-                ASSERT(MmFreePageListHead.Total == 0);
+                ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
                 PageIndex = MmZeroedPageListHead.Flink;
                 Color = PageIndex & MmSecondaryColorMask;
                 ASSERT(PageIndex != LIST_HEAD);
@@ -408,6 +434,8 @@ MiRemoveAnyPage(IN ULONG Color)
            (Pfn1->u3.e1.PageLocation == ZeroedPageList));
     ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
     ASSERT(Pfn1->u2.ShareCount == 0);
+    ASSERT_LIST_INVARIANT(&MmFreePageListHead);
+    ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
         
     /* Return the page */
     return PageIndex;
@@ -419,7 +447,9 @@ MiRemoveHeadList(IN PMMPFNLIST ListHead)
 {
     PFN_NUMBER Entry, Flink;
     PMMPFN Pfn1;
-    
+    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+    ASSERT_LIST_INVARIANT(ListHead);
+
     /* Get the entry that's currently first on the list */
     Entry = ListHead->Flink;
     Pfn1 = MiGetPfnEntry(Entry);
@@ -443,7 +473,8 @@ MiRemoveHeadList(IN PMMPFNLIST ListHead)
     /* We are not on a list anymore */
     Pfn1->u1.Flink = Pfn1->u2.Blink = 0;
     ListHead->Total--;
-    
+       ASSERT_LIST_INVARIANT(ListHead);
+
     /* Return the head element */
     return Pfn1;
 }
@@ -461,6 +492,7 @@ MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
     PMMCOLOR_TABLES ColorTable;
 #endif
     /* Make sure the page index is valid */
+    ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
     ASSERT((PageFrameIndex != 0) &&
            (PageFrameIndex <= MmHighestPhysicalPage) &&
            (PageFrameIndex >= MmLowestPhysicalPage));
@@ -477,6 +509,7 @@ MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
 
     /* Get the free page list and increment its count */
     ListHead = &MmFreePageListHead;
+    ASSERT_LIST_INVARIANT(ListHead);
     ListHead->Total++;
 
     /* Get the last page on the list */
@@ -494,7 +527,8 @@ MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
 
     /* Now make the list head point back to us (since we go at the end) */
     ListHead->Blink = PageFrameIndex;
-    
+    ASSERT_LIST_INVARIANT(ListHead);
+
     /* And initialize our own list pointers */
     Pfn1->u1.Flink = LIST_HEAD;
     Pfn1->u2.Blink = LastPage;
@@ -502,7 +536,7 @@ MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
     /* Set the list name and default priority */
     Pfn1->u3.e1.PageLocation = FreePageList;
     Pfn1->u4.Priority = 3;
-    
+
     /* Clear some status fields */
     Pfn1->u4.InPageError = 0;
     Pfn1->u4.AweAllocation = 0;
@@ -618,6 +652,48 @@ MiInitializePfn(IN PFN_NUMBER PageFrameIndex,
     Pfn1->u2.ShareCount++;
 }
 
+PFN_NUMBER
+NTAPI
+MiAllocatePfn(IN PMMPTE PointerPte,
+              IN ULONG Protection)
+{
+    KIRQL OldIrql;
+    PFN_NUMBER PageFrameIndex;
+    MMPTE TempPte;
+    
+    /* Make an empty software PTE */
+    MI_MAKE_SOFTWARE_PTE(&TempPte, MM_READWRITE);
+    
+    /* Lock the PFN database */
+    OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+    
+    /* Check if we're running low on pages */
+    if (MmAvailablePages < 128)
+    {
+        DPRINT1("Warning, running low on memory: %d pages left\n", MmAvailablePages);
+        //MiEnsureAvailablePageOrWait(NULL, OldIrql);
+    }
+    
+    /* Grab a page */
+    ASSERT_LIST_INVARIANT(&MmFreePageListHead);
+    ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
+    PageFrameIndex = MiRemoveAnyPage(0);
+
+    /* Write the software PTE */
+    ASSERT(PointerPte->u.Hard.Valid == 0);
+    *PointerPte = TempPte;
+    PointerPte->u.Soft.Protection |= Protection;
+    
+    /* Initialize its PFN entry */
+    MiInitializePfn(PageFrameIndex, PointerPte, TRUE);
+    
+    /* Release the PFN lock and return the page */
+    ASSERT_LIST_INVARIANT(&MmFreePageListHead);
+    ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);
+    KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+    return PageFrameIndex;
+}
+
 VOID
 NTAPI
 MiDecrementShareCount(IN PMMPFN Pfn1,
@@ -683,4 +759,41 @@ MiDecrementShareCount(IN PMMPFN Pfn1,
     }
 }
 
+VOID
+NTAPI
+MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex,
+                               IN PMMPTE PointerPte,
+                               IN PFN_NUMBER PteFrame)
+{
+    PMMPFN Pfn1;
+    
+    /* Setup the PTE */
+    Pfn1 = MiGetPfnEntry(PageFrameIndex);
+    Pfn1->PteAddress = PointerPte;
+    
+#if 0 // When using ARM3 PFN
+    /* Make this a software PTE */
+    MI_MAKE_SOFTWARE_PTE(&Pfn1->OriginalPte, MM_READWRITE);
+#endif
+    
+    /* Setup the page */
+    ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
+    Pfn1->u3.e2.ReferenceCount = 1;
+    Pfn1->u2.ShareCount = 1;
+    Pfn1->u3.e1.PageLocation = ActiveAndValid;
+    Pfn1->u3.e1.Modified = TRUE;
+    Pfn1->u4.InPageError = FALSE;
+    
+    /* Did we get a PFN for the page table */
+    if (PteFrame)
+    {
+        /* Store it */
+        Pfn1->u4.PteFrame = PteFrame;
+        
+        /* Increase its share count so we don't get rid of it */    
+        Pfn1 = MiGetPfnEntry(PageFrameIndex);
+        Pfn1->u2.ShareCount++;
+    }
+}
+
 /* EOF */