[NTOS]: When expanding paged pool, use MiRemoveAnyPage, not MmAllocPage.
[reactos.git] / reactos / ntoskrnl / mm / ARM3 / pool.c
index bfb75df..c4a7374 100644 (file)
@@ -26,12 +26,104 @@ KGUARDED_MUTEX MmPagedPoolMutex;
 MM_PAGED_POOL_INFO MmPagedPoolInfo;
 SIZE_T MmAllocatedNonPagedPool;
 ULONG MmSpecialPoolTag;
+ULONG MmConsumedPoolPercentage;
+BOOLEAN MmProtectFreedNonPagedPool;
 
 /* PRIVATE FUNCTIONS **********************************************************/
 
 VOID
 NTAPI
-MiInitializeArmPool(VOID)
+MiInitializeNonPagedPoolThresholds(VOID)
+{
+    PFN_NUMBER Size = MmMaximumNonPagedPoolInPages;
+
+    /* Default low threshold of 8MB or one third of nonpaged pool */
+    MiLowNonPagedPoolThreshold = (8 * _1MB) >> PAGE_SHIFT;
+    MiLowNonPagedPoolThreshold = min(MiLowNonPagedPoolThreshold, Size / 3);
+
+    /* Default high threshold of 20MB or 50% */
+    MiHighNonPagedPoolThreshold = (20 * _1MB) >> PAGE_SHIFT;
+    MiHighNonPagedPoolThreshold = min(MiHighNonPagedPoolThreshold, Size / 2);
+    ASSERT(MiLowNonPagedPoolThreshold < MiHighNonPagedPoolThreshold);
+}
+
+VOID
+NTAPI
+MiInitializePoolEvents(VOID)
+{
+    KIRQL OldIrql;
+    PFN_NUMBER FreePoolInPages;
+
+    /* Lock paged pool */
+    KeAcquireGuardedMutex(&MmPagedPoolMutex);
+
+    /* Total size of the paged pool minus the allocated size, is free */
+    FreePoolInPages = MmSizeOfPagedPoolInPages - MmPagedPoolInfo.AllocatedPagedPool;
+
+    /* Check the initial state high state */
+    if (FreePoolInPages >= MiHighPagedPoolThreshold)
+    {
+        /* We have plenty of pool */
+        KeSetEvent(MiHighPagedPoolEvent, 0, FALSE);
+    }
+    else
+    {
+        /* We don't */
+        KeClearEvent(MiHighPagedPoolEvent);
+    }
+
+    /* Check the initial low state */
+    if (FreePoolInPages <= MiLowPagedPoolThreshold)
+    {
+        /* We're very low in free pool memory */
+        KeSetEvent(MiLowPagedPoolEvent, 0, FALSE);
+    }
+    else
+    {
+        /* We're not */
+        KeClearEvent(MiLowPagedPoolEvent);
+    }
+
+    /* Release the paged pool lock */
+    KeReleaseGuardedMutex(&MmPagedPoolMutex);
+
+    /* Now it's time for the nonpaged pool lock */
+    OldIrql = KeAcquireQueuedSpinLock(LockQueueMmNonPagedPoolLock);
+
+    /* Free pages are the maximum minus what's been allocated */
+    FreePoolInPages = MmMaximumNonPagedPoolInPages - MmAllocatedNonPagedPool;
+
+    /* Check if we have plenty */
+    if (FreePoolInPages >= MiHighNonPagedPoolThreshold)
+    {
+        /* We do, set the event */
+        KeSetEvent(MiHighNonPagedPoolEvent, 0, FALSE);
+    }
+    else
+    {
+        /* We don't, clear the event */
+        KeClearEvent(MiHighNonPagedPoolEvent);
+    }
+
+    /* Check if we have very little */
+    if (FreePoolInPages <= MiLowNonPagedPoolThreshold)
+    {
+        /* We do, set the event */
+        KeSetEvent(MiLowNonPagedPoolEvent, 0, FALSE);
+    }
+    else
+    {
+        /* We don't, clear it */
+        KeClearEvent(MiLowNonPagedPoolEvent);
+    }
+
+    /* We're done, release the nonpaged pool lock */
+    KeReleaseQueuedSpinLock(LockQueueMmNonPagedPoolLock, OldIrql);
+}
+
+VOID
+NTAPI
+MiInitializeNonPagedPool(VOID)
 {
     ULONG i;
     PFN_NUMBER PoolPages;
@@ -213,7 +305,7 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
             //
             // Get the template PTE we'll use to expand
             //
-            TempPte = HyperTemplatePte;
+            TempPte = ValidKernelPte;
             
             //
             // Get the first PTE in expansion space
@@ -233,21 +325,25 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
                 //
                 ASSERT(PointerPte->u.Hard.Valid == 0);
                 
-                //
-                // Request a paged pool page and write the PFN for it
-                //
-                PageFrameNumber = MmAllocPage(MC_PPOOL, 0);
+                /* Request a page */
+                PageFrameNumber = MiRemoveAnyPage(0);
                 TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
                 
                 //
                 // Save it into our double-buffered system page directory
                 //
+                /* This seems to be making the assumption that one PDE is one page long */
+                C_ASSERT(PAGE_SIZE == (PD_COUNT * (sizeof(MMPTE) * PDE_COUNT)));
                 MmSystemPagePtes[(ULONG_PTR)PointerPte & (PAGE_SIZE - 1) /
                                  sizeof(MMPTE)] = TempPte;
                             
-                //
-                // Write the actual PTE now
-                //
+                /* Initialize the PFN */
+                MiInitializePfnForOtherProcess(PageFrameNumber,
+                                               PointerPte,
+                                               MmSystemPageDirectory[(PointerPte - (PMMPTE)PDE_BASE) / PDE_COUNT]);
+                             
+                /* Write the actual PTE now */
+                ASSERT(TempPte.u.Hard.Valid == 1);
                 *PointerPte++ = TempPte;
                 
                 //
@@ -324,11 +420,9 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
         //
         KeFlushEntireTb(TRUE, TRUE);
         
-        //
-        // Setup a demand-zero writable PTE
-        //
-        TempPte.u.Long = 0;
-        MI_MAKE_WRITE_PAGE(&TempPte);
+        /* Setup a demand-zero writable PTE */
+        DPRINT1("Setting up demand zero\n");
+        MI_MAKE_SOFTWARE_PTE(&TempPte, MM_READWRITE);
         
         //
         // Find the first and last PTE, then loop them all
@@ -340,6 +434,7 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
             //
             // Write the demand zero PTE and keep going
             //
+            ASSERT(PointerPte->u.Hard.Valid == 0);
             *PointerPte++ = TempPte;
         } while (PointerPte < StartPte);
         
@@ -493,22 +588,21 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
     //
     // Loop the pages
     //
-    TempPte = HyperTemplatePte;
+    TempPte = ValidKernelPte;
     do
     {
-        //
-        // Allocate a page
-        //
-        PageFrameNumber = MmAllocPage(MC_NPPOOL, 0);
+        /* Allocate a page */
+        PageFrameNumber = MiRemoveAnyPage(0);
         
-        //
-        // Get the PFN entry for it
-        //
+        /* Get the PFN entry for it and fill it out */
         Pfn1 = MiGetPfnEntry(PageFrameNumber);
+        Pfn1->u3.e2.ReferenceCount = 1;
+        Pfn1->u2.ShareCount = 1;
+        Pfn1->PteAddress = PointerPte;
+        Pfn1->u3.e1.PageLocation = ActiveAndValid;
+        Pfn1->u4.VerifierAllocation = 0;
         
-        //
-        // Write the PTE for it
-        //
+        /* Write the PTE for it */
         TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
         ASSERT(PointerPte->u.Hard.Valid == 0);
         ASSERT(TempPte.u.Hard.Valid == 1);