Author: jgardou
Date: Mon Feb 20 20:51:18 2012
New Revision: 55763

URL: http://svn.reactos.org/svn/reactos?rev=55763&view=rev
Log:
[NTOSKRNL/MM]
  - Stop leaking references to PDEs.
Still one reference left to the TLB mapping at process deletion.

Modified:
    trunk/reactos/ntoskrnl/mm/anonmem.c
    trunk/reactos/ntoskrnl/mm/balance.c
    trunk/reactos/ntoskrnl/mm/i386/page.c
    trunk/reactos/ntoskrnl/mm/marea.c
    trunk/reactos/ntoskrnl/mm/section.c

Modified: trunk/reactos/ntoskrnl/mm/anonmem.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/anonmem.c?rev=55763&r1=55762&r2=55763&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/anonmem.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/anonmem.c [iso-8859-1] Mon Feb 20 20:51:18 2012
@@ -113,6 +113,12 @@
             MmCreatePageFileMapping(Process, Address, SwapEntry);
             MmSetSavedSwapEntryPage(Page, 0);
         }
+#if (_MI_PAGING_LEVELS == 2)
+        else if(Address < MmSystemRangeStart)
+        {
+            
AddressSpace->VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
+        }
+#endif
         MmUnlockAddressSpace(AddressSpace);
         MmReleasePageMemoryConsumer(MC_USER, Page);
         PageOp->Status = STATUS_SUCCESS;
@@ -191,6 +197,9 @@
     PMM_REGION Region;
     PMM_PAGEOP PageOp;
     PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
+#if (_MI_PAGING_LEVELS == 2)
+    BOOLEAN refPde = TRUE;
+#endif
 
     /*
     * There is a window between taking the page fault and locking the
@@ -326,7 +335,17 @@
             KeBugCheck(MEMORY_MANAGEMENT);
         }
         MmSetSavedSwapEntryPage(Page, SwapEntry);
-    }
+        
+#if (_MI_PAGING_LEVELS == 2)
+        /* PTE was already "created", no need to reference PDE */
+        refPde = FALSE;
+#endif
+    }
+#if (_MI_PAGING_LEVELS == 2)
+    /* Add an additional page table reference */
+    if(refPde) 
MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++;
+    ASSERT(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] <= 
PTE_COUNT);
+#endif
 
     /*
     * Set the page. If we fail because we are out of memory then
@@ -337,16 +356,6 @@
         Region->Protect,
         &Page,
         1);
-    while (Status == STATUS_NO_MEMORY)
-    {
-        MmUnlockAddressSpace(AddressSpace);
-        Status = MmCreateVirtualMapping(Process,
-            (PVOID)PAGE_ROUND_DOWN(Address),
-            Region->Protect,
-            &Page,
-            1);
-        MmLockAddressSpace(AddressSpace);
-    }
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("MmCreateVirtualMapping failed, not out of memory\n");
@@ -393,9 +402,9 @@
         for (i=0; i < PAGE_ROUND_UP(RegionSize)/PAGE_SIZE; i++)
         {
             PFN_NUMBER Page;
-
-            if (MmIsPageSwapEntry(Process,
-                        (char*)BaseAddress + (i * PAGE_SIZE)))
+            PVOID Address = (char*)BaseAddress + (i*PAGE_SIZE);
+
+            if (MmIsPageSwapEntry(Process, Address))
             {
                 SWAPENTRY SwapEntry;
 
@@ -403,11 +412,17 @@
                     (char*)BaseAddress + (i * PAGE_SIZE),
                     &SwapEntry);
                 MmFreeSwapPage(SwapEntry);
+#if (_MI_PAGING_LEVELS == 2)
+                if(Address < MmSystemRangeStart)
+                {
+                    
AddressSpace->VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
+                }
+#endif
             }
             else
             {
                 MmDeleteVirtualMapping(Process,
-                    (char*)BaseAddress + (i*PAGE_SIZE),
+                    Address,
                     FALSE, NULL, &Page);
                 if (Page != 0)
                 {
@@ -417,10 +432,16 @@
                     {
                         MmFreeSwapPage(SavedSwapEntry);
                         MmSetSavedSwapEntryPage(Page, 0);
-                    }
+                    }                            
                     MmDeleteRmap(Page, Process,
                         (char*)BaseAddress + (i * PAGE_SIZE));
                     MmReleasePageMemoryConsumer(MC_USER, Page);
+#if (_MI_PAGING_LEVELS == 2)
+                    if(Address < MmSystemRangeStart)
+                    {
+                        
AddressSpace->VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
+                    }
+#endif
                 }
             }
         }

Modified: trunk/reactos/ntoskrnl/mm/balance.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/balance.c?rev=55763&r1=55762&r2=55763&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/balance.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/balance.c [iso-8859-1] Mon Feb 20 20:51:18 2012
@@ -14,6 +14,8 @@
 #define NDEBUG
 #include <debug.h>
 
+#include "ARM3/miarm.h"
+
 #if defined (ALLOC_PRAGMA)
 #pragma alloc_text(INIT, MmInitializeBalancer)
 #pragma alloc_text(INIT, MmInitializeMemoryConsumer)
@@ -234,8 +236,38 @@
 
 VOID
 NTAPI
+MiDeletePte(IN PMMPTE PointerPte,
+            IN PVOID VirtualAddress,
+            IN PEPROCESS CurrentProcess,
+            IN PMMPTE PrototypePte);
+
+VOID
+NTAPI
 MmRebalanceMemoryConsumers(VOID)
 {
+#if (_MI_PAGING_LEVELS == 2)
+    if(!MiIsBalancerThread())
+    {
+        /* Clean up the unused PDEs */
+        ULONG_PTR Address;
+        KIRQL OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+        PMMPDE pointerPde;
+        for(Address = (ULONG_PTR)MI_LOWEST_VAD_ADDRESS;
+            Address < (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS;
+            Address += (PAGE_SIZE * PTE_COUNT))
+        {
+            if(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] 
== 0)
+            {
+                pointerPde = MiAddressToPde(Address);
+                if(pointerPde->u.Hard.Valid)
+                    MiDeletePte(pointerPde, MiPdeToPte(pointerPde), 
PsGetCurrentProcess(), NULL);
+                ASSERT(pointerPde->u.Hard.Valid == 0);
+            }
+        }
+        KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+    }
+#endif
+
     if (MiBalancerThreadHandle != NULL &&
         !MiIsBalancerThread())
     {

Modified: trunk/reactos/ntoskrnl/mm/i386/page.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/i386/page.c?rev=55763&r1=55762&r2=55763&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/i386/page.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/i386/page.c [iso-8859-1] Mon Feb 20 20:51:18 2012
@@ -258,9 +258,22 @@
             {
                 /* Nobody but page fault should ask for creating the PDE,
                  * Which imples that Process is the current one */
-                ASSERT(Create == FALSE);
                 MmDeleteHyperspaceMapping(PdeBase);
-                return NULL;
+                if(Create == FALSE)
+                    return NULL;
+                else
+                {
+                    KAPC_STATE ApcState;
+                    PULONG ret;
+                    /* Attach to process */
+                    KeStackAttachProcess(&Process->Pcb, &ApcState);
+                    
+                    /* Retry */
+                    ret = MmGetPageTableForProcess(Process, Address, TRUE);
+                    
+                    /* Get Back to original process */
+                    KeUnstackDetachProcess(&ApcState);
+                }
             }
             else
             {
@@ -293,6 +306,7 @@
     }
 
     /* This is for kernel land address */
+    ASSERT(Process == NULL);
     PointerPde = MiAddressToPde(Address);
     Pt = (PULONG)MiAddressToPte(Address);
     if (PointerPde->u.Hard.Valid == 0)

Modified: trunk/reactos/ntoskrnl/mm/marea.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/marea.c?rev=55763&r1=55762&r2=55763&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/marea.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/marea.c [iso-8859-1] Mon Feb 20 20:51:18 2012
@@ -44,6 +44,8 @@
 #include <ntoskrnl.h>
 #define NDEBUG
 #include <debug.h>
+
+#include "ARM3/miarm.h"
 
 MEMORY_AREA MiStaticMemoryAreas[MI_STATIC_MEMORY_AREAS];
 ULONG MiStaticMemoryAreaCount;
@@ -688,6 +690,12 @@
  *
  * @remarks Lock the address space before calling this function.
  */
+VOID
+NTAPI
+MiDeletePte(IN PMMPTE PointerPte,
+            IN PVOID VirtualAddress,
+            IN PEPROCESS CurrentProcess,
+            IN PMMPTE PrototypePte);
 
 NTSTATUS NTAPI
 MmFreeMemoryArea(
@@ -716,10 +724,10 @@
             Address < (ULONG_PTR)EndAddress;
             Address += PAGE_SIZE)
        {
-             BOOLEAN Dirty = FALSE;
-             SWAPENTRY SwapEntry = 0;
-             PFN_NUMBER Page = 0;
-
+            BOOLEAN Dirty = FALSE;
+            SWAPENTRY SwapEntry = 0;
+            PFN_NUMBER Page = 0;
+             
              if (MmIsPageSwapEntry(Process, (PVOID)Address))
              {
                 MmDeletePageFileMapping(Process, (PVOID)Address, &SwapEntry);
@@ -733,6 +741,25 @@
                 FreePage(FreePageContext, MemoryArea, (PVOID)Address,
                          Page, SwapEntry, (BOOLEAN)Dirty);
              }
+#if (_MI_PAGING_LEVELS == 2)
+            /* Remove page table reference */
+            if((SwapEntry || Page) && ((PVOID)Address < MmSystemRangeStart))
+            {
+                ASSERT(AddressSpace != MmGetKernelAddressSpace());
+                
MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
+                
ASSERT(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] < 
PTE_COUNT);
+                
if(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] == 0)
+                {
+                    /* No PTE relies on this PDE. Release it */
+                    KIRQL OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+                    PMMPDE PointerPde = MiAddressToPde(Address);
+                    ASSERT(PointerPde->u.Hard.Valid == 1);
+                    MiDeletePte(PointerPde, MiPdeToPte(PointerPde), Process, 
NULL);
+                    ASSERT(PointerPde->u.Hard.Valid == 0);
+                    KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+                }
+            }
+#endif
        }
 
        if (Process != NULL &&

Modified: trunk/reactos/ntoskrnl/mm/section.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/section.c?rev=55763&r1=55762&r2=55763&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] Mon Feb 20 20:51:18 2012
@@ -57,6 +57,8 @@
 #pragma alloc_text(INIT, MmInitSectionImplementation)
 #endif
 
+#include "ARM3/miarm.h"
+
 NTSTATUS
 NTAPI
 MiMapViewInSystemSpace(IN PVOID Section,
@@ -1448,6 +1450,15 @@
          Page = PFN_FROM_SSE(Entry);
 
          MmSharePageEntrySectionSegment(Segment, Offset);
+         
+ #if (_MI_PAGING_LEVELS == 2)
+        /* Reference Page Directory Entry */
+        if(Address < MmSystemRangeStart)
+        {
+            MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++;
+            
ASSERT(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] <= 
PTE_COUNT);
+        }
+#endif
 
          /* FIXME: Should we call MmCreateVirtualMappingUnsafe if
           * (Section->AllocationAttributes & SEC_PHYSICALMEMORY) is true?
@@ -1538,6 +1549,15 @@
       return(STATUS_SUCCESS);
    }
 
+#if (_MI_PAGING_LEVELS == 2)
+    /* Reference Page Directory Entry */
+    if(Address < MmSystemRangeStart)
+    {
+        MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++;
+        ASSERT(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] 
<= PTE_COUNT);
+    }
+#endif
+
    /*
     * Satisfying a page fault on a map of /Device/PhysicalMemory is easy
     */
@@ -1658,6 +1678,12 @@
          /*
           * Cleanup and release locks
           */
+#if (_MI_PAGING_LEVELS == 2)
+        if(Address < MmSystemRangeStart)
+        {
+            MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
+        }
+#endif
          MmLockAddressSpace(AddressSpace);
          PageOp->Status = Status;
          MmspCompleteAndReleasePageOp(PageOp);
@@ -1876,7 +1902,10 @@
       MmSetPageProtect(Process, Address, Region->Protect);
       return(STATUS_SUCCESS);
    }
-
+   
+   if(OldPage == 0)
+      DPRINT("OldPage == 0!\n");
+   
    /*
     * Get or create a pageop
     */
@@ -1986,7 +2015,7 @@
    MM_SECTION_PAGEOUT_CONTEXT* PageOutContext;
    BOOLEAN WasDirty;
    PFN_NUMBER Page;
-
+   
    PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context;
    if (Process)
    {
@@ -2021,6 +2050,14 @@
    {
       MmReleasePageMemoryConsumer(MC_USER, Page);
    }
+
+#if (_MI_PAGING_LEVELS == 2)
+    if(Address < MmSystemRangeStart)
+    {
+        if(Process->VmDeleted) DPRINT1("deleted!!!");
+        
Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
+    }
+#endif
 
    DPRINT("PhysicalAddress %x, Address %x\n", Page << PAGE_SHIFT, Address);
 }
@@ -2254,6 +2291,13 @@
    {
       MmSetSavedSwapEntryPage(Page, 0);
       MmLockAddressSpace(AddressSpace);
+ #if (_MI_PAGING_LEVELS == 2)
+      /* Page table was dereferenced while deleting the RMAP */
+      if(Address < MmSystemRangeStart)
+      {
+         
AddressSpace->VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++;
+      }
+#endif
       Status = MmCreatePageFileMapping(Process,
                                        Address,
                                        SwapEntry);
@@ -2281,6 +2325,13 @@
          /*
           * For private pages restore the old mappings.
           */
+ #if (_MI_PAGING_LEVELS == 2)
+        /* Page table was dereferenced while deleting the RMAP */
+        if(Address < MmSystemRangeStart)
+        {
+            
AddressSpace->VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++;
+        }
+#endif
          if (Context.Private)
          {
             Status = MmCreateVirtualMapping(Process,
@@ -2331,6 +2382,13 @@
        * As above: undo our actions.
        * FIXME: Also free the swap page.
        */
+#if (_MI_PAGING_LEVELS == 2)
+        /* Page table was dereferenced while deleting the RMAP */
+        if(Address < MmSystemRangeStart)
+        {
+            
AddressSpace->VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++;
+        }
+#endif
       MmLockAddressSpace(AddressSpace);
       if (Context.Private)
       {
@@ -2382,6 +2440,13 @@
    if (Context.Private)
    {
       MmLockAddressSpace(AddressSpace);
+ #if (_MI_PAGING_LEVELS == 2)
+      /* Page table was dereferenced while deleting the RMAP */
+      if(Address < MmSystemRangeStart)
+      {
+          
AddressSpace->VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++;
+      }
+#endif
       Status = MmCreatePageFileMapping(Process,
                                        Address,
                                        SwapEntry);


Reply via email to