[NTOS]: Implement MiDeleteSystemPageableVm.
authorSir Richard <sir_richard@svn.reactos.org>
Sat, 5 Jun 2010 04:16:46 +0000 (04:16 +0000)
committerSir Richard <sir_richard@svn.reactos.org>
Sat, 5 Jun 2010 04:16:46 +0000 (04:16 +0000)
[NTOS]: The paged pool free code was behaving incorrectly, assuming that paged pool was "locked down" and never paged out/reused (a valid NT operation mode), while the allocation code was assuming paged pool was a volatile, reusable, pageable resource (normal NT operation mode). The free code now assumes normal operation mode, and actually frees the freed paged pool pages, by using MiDeleteSystemPageableVm.
I have a feeling this will make ARM3 paged pool work.

svn path=/trunk/; revision=47582

reactos/ntoskrnl/mm/ARM3/miarm.h
reactos/ntoskrnl/mm/ARM3/pool.c
reactos/ntoskrnl/mm/ARM3/virtual.c

index efcc053..67eeb42 100644 (file)
@@ -733,6 +733,15 @@ MiInsertPageInFreeList(
     IN PFN_NUMBER PageFrameIndex
 );
 
+PFN_NUMBER
+NTAPI
+MiDeleteSystemPageableVm(
+    IN PMMPTE PointerPte,
+    IN PFN_NUMBER PageCount,
+    IN ULONG Flags,
+    OUT PPFN_NUMBER ValidPages
+);
+                         
 PLDR_DATA_TABLE_ENTRY
 NTAPI
 MiLookupDataTableEntry(
index c4a7374..e3af2a6 100644 (file)
@@ -264,6 +264,7 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
             // Get the page bit count
             //
             i = ((SizeInPages - 1) / 1024) + 1;
+            DPRINT1("Paged pool expansion: %d %x\n", i, SizeInPages);
             
             //
             // Check if there is enougn paged pool expansion space left
@@ -666,6 +667,11 @@ MiFreePoolPages(IN PVOID StartingVa)
         //
         NumberOfPages = End - i + 1;
         
+        /* Delete the actual pages */
+        PointerPte = MmPagedPoolInfo.FirstPteForPagedPool + i;
+        FreePages = MiDeleteSystemPageableVm(PointerPte, NumberOfPages, 0, NULL);
+        ASSERT(FreePages == NumberOfPages);
+        
         //
         // Acquire the paged pool lock
         //
index 88ff54f..a517cba 100644 (file)
@@ -29,6 +29,102 @@ MiProtectVirtualMemory(IN PEPROCESS Process,
 
 /* PRIVATE FUNCTIONS **********************************************************/
 
+PFN_NUMBER
+NTAPI
+MiDeleteSystemPageableVm(IN PMMPTE PointerPte,
+                         IN PFN_NUMBER PageCount,
+                         IN ULONG Flags,
+                         OUT PPFN_NUMBER ValidPages)
+{                     
+    PFN_NUMBER ActualPages = 0;
+    PETHREAD CurrentThread;
+    PMMPFN Pfn1, Pfn2;
+    PFN_NUMBER PageFrameIndex, PageTableIndex;
+    KIRQL OldIrql, LockIrql;
+    ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
+    
+    /*
+     * Now we must raise to APC_LEVEL and mark the thread as owner
+     * We don't actually implement a working set pushlock, so this is only
+     * for internal consistency (and blocking APCs)
+     */
+    KeRaiseIrql(APC_LEVEL, &LockIrql);
+    CurrentThread = PsGetCurrentThread();
+    KeEnterGuardedRegion();
+    ASSERT((CurrentThread->OwnsSystemWorkingSetExclusive == 0) &&
+           (CurrentThread->OwnsSystemWorkingSetShared == 0));
+    CurrentThread->OwnsSystemWorkingSetExclusive = 1;
+                
+    /* Loop all pages */
+    while (PageCount)
+    {
+        /* Make sure there's some data about the page */
+        if (PointerPte->u.Long)
+        {
+            /* As always, only handle current ARM3 scenarios */
+            ASSERT(PointerPte->u.Soft.Prototype == 0);
+            ASSERT(PointerPte->u.Soft.Transition == 0);
+            ASSERT(PointerPte->u.Hard.Valid == 1);
+            
+            /* Normally this is one possibility -- freeing a valid page */
+            if (PointerPte->u.Hard.Valid)
+            {
+                /* Get the page PFN */
+                PageFrameIndex = PFN_FROM_PTE(PointerPte);
+                Pfn1 = MiGetPfnEntry(PageFrameIndex);
+                
+                /* Should not have any working set data yet */
+                ASSERT(Pfn1->u1.WsIndex == 0);
+                
+                /* Actual valid, legitimate, pages */
+                if (ValidPages) *ValidPages++;
+                
+                /* Get the page table entry */
+                PageTableIndex = Pfn1->u4.PteFrame;
+                DPRINT1("Page table: %lx\n", PageTableIndex);
+                Pfn2 = MiGetPfnEntry(PageTableIndex);
+                
+                /* Lock the PFN database */
+                OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+                
+                /* Delete it the page */
+                MI_SET_PFN_DELETED(Pfn1);
+                MiDecrementShareCount(Pfn1, PageFrameIndex);
+                
+                /* Decrement the page table too */
+                #if 0 // ARM3: Dont't trust this yet
+                MiDecrementShareCount(Pfn2, PageTableIndex);
+                #endif
+                
+                /* Release the PFN database */
+                KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+                
+                /* Destroy the PTE */
+                PointerPte->u.Long = 0;
+            }
+    
+            /* Actual legitimate pages */
+            ActualPages++;
+        }
+        
+        /* Keep going */
+        PointerPte++;
+        PageCount--;
+    }
+    
+    /* Re-enable APCs */
+    ASSERT(KeAreAllApcsDisabled() == TRUE);
+    CurrentThread->OwnsSystemWorkingSetExclusive = 0;
+    KeLeaveGuardedRegion();
+    KeLowerIrql(LockIrql);
+    
+    /* Flush the entire TLB */
+    KeFlushEntireTb(TRUE, TRUE);
+    
+    /* Done */
+    return ActualPages;
+}
+
 LONG
 MiGetExceptionInfo(IN PEXCEPTION_POINTERS ExceptionInfo,
                    OUT PBOOLEAN HaveBadAddress,