Author: jgardou
Date: Tue Feb 21 00:32:24 2012
New Revision: 55770

URL: http://svn.reactos.org/svn/reactos?rev=55770&view=rev
Log:
[NTOSKRNL/MM]
 - finally, release user shared data at process address space cleanup.
 - release PDE pages that might not be freed at process end.
 - Let the caller handle PDE release when deleting a PTE
 - restore Richard's ASSERT : All user PDE pages are now freed!

Modified:
    trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c
    trunk/reactos/ntoskrnl/mm/ARM3/procsup.c
    trunk/reactos/ntoskrnl/mm/ARM3/virtual.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/ARM3/pfnlist.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c?rev=55770&r1=55769&r2=55770&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c [iso-8859-1] Tue Feb 21 00:32:24 
2012
@@ -931,8 +931,11 @@
         ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
         if (Pfn1->u3.e2.ReferenceCount == 1)
         {
-            /* In ReactOS, this path should always be hit with a deleted PFN */
-            ASSERT(MI_IS_PFN_DELETED(Pfn1) == TRUE);
+            if(Pfn1->u3.e1.PrototypePte == 0)
+            {
+                /* In ReactOS, this path should always be hit with a deleted 
PFN */
+                ASSERT(MI_IS_PFN_DELETED(Pfn1) == TRUE);
+            }
 
             /* Clear the last reference */
             Pfn1->u3.e2.ReferenceCount = 0;

Modified: trunk/reactos/ntoskrnl/mm/ARM3/procsup.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/procsup.c?rev=55770&r1=55769&r2=55770&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/procsup.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/procsup.c [iso-8859-1] Tue Feb 21 00:32:24 
2012
@@ -1349,6 +1349,8 @@
         /* Free the VAD memory */
         ExFreePool(Vad);
     }
+    /* Delete the shared user data section */
+    MiDeleteVirtualAddresses(USER_SHARED_DATA, USER_SHARED_DATA, NULL);
 
     /* Release the address space */
     MmUnlockAddressSpace(&Process->Vm);
@@ -1363,14 +1365,6 @@
     PFN_NUMBER PageFrameIndex;
 
     //ASSERT(Process->CommitCharge == 0);
-
-    /* Delete the shared user data section (Should be done in clean, not 
delete) */
-    ASSERT(MmHighestUserAddress > (PVOID)USER_SHARED_DATA);
-    KeAttachProcess(&Process->Pcb);
-    //DPRINT1("Killing shared user data page no longer works -- has someone 
changed ARM3 in a way to make this fail now?\n");
-    //MiDeleteVirtualAddresses(USER_SHARED_DATA, USER_SHARED_DATA, NULL);
-    //DPRINT1("Done\n");
-    KeDetachProcess();
     
     /* Acquire the PFN lock */
     OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
@@ -1407,11 +1401,8 @@
         MiDecrementShareCount(Pfn1, PageFrameIndex);
         MiDecrementShareCount(Pfn1, PageFrameIndex);
         
-        /* HACK: In Richard's original patch this ASSERT did work */
-        //DPRINT1("Ref count: %lx %lx\n", Pfn1->u3.e2.ReferenceCount, 
Pfn1->u2.ShareCount);
-        //ASSERT((Pfn1->u3.e2.ReferenceCount == 0) || 
(Pfn1->u3.e1.WriteInProgress));
-        if(!((Pfn1->u3.e2.ReferenceCount == 0) || 
(Pfn1->u3.e1.WriteInProgress)))
-            DPRINT1("Ref count: %lx %lx\n", Pfn1->u3.e2.ReferenceCount, 
Pfn1->u2.ShareCount);
+        /* Page table is now dead. Bye bye... */
+        ASSERT((Pfn1->u3.e2.ReferenceCount == 0) || 
(Pfn1->u3.e1.WriteInProgress));
     }
     else
     {

Modified: trunk/reactos/ntoskrnl/mm/ARM3/virtual.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/virtual.c?rev=55770&r1=55769&r2=55770&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/virtual.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/virtual.c [iso-8859-1] Tue Feb 21 00:32:24 
2012
@@ -258,9 +258,6 @@
 #if (_MI_PAGING_LEVELS == 2)
         }
 #endif
-        /* Drop the reference on the page table. */
-        MiDecrementShareCount(MiGetPfnEntry(PFN_FROM_PTE(PointerPde)), 
PFN_FROM_PTE(PointerPde));
-
         /* Drop the share count */
         MiDecrementShareCount(Pfn1, PageFrameIndex);
 

Modified: trunk/reactos/ntoskrnl/mm/balance.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/balance.c?rev=55770&r1=55769&r2=55770&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/balance.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/balance.c [iso-8859-1] Tue Feb 21 00:32:24 2012
@@ -250,6 +250,9 @@
     {
         /* Clean up the unused PDEs */
         ULONG_PTR Address;
+        PEPROCESS Process = PsGetCurrentProcess();
+
+        /* Acquire PFN lock */
         KIRQL OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
         PMMPDE pointerPde;
         for(Address = (ULONG_PTR)MI_LOWEST_VAD_ADDRESS;
@@ -260,10 +263,11 @@
             {
                 pointerPde = MiAddressToPde(Address);
                 if(pointerPde->u.Hard.Valid)
-                    MiDeletePte(pointerPde, MiPdeToPte(pointerPde), 
PsGetCurrentProcess(), NULL);
+                    MiDeletePte(pointerPde, MiPdeToPte(pointerPde), Process, 
NULL);
                 ASSERT(pointerPde->u.Hard.Valid == 0);
             }
         }
+        /* Release lock */
         KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
     }
 #endif

Modified: trunk/reactos/ntoskrnl/mm/i386/page.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/i386/page.c?rev=55770&r1=55769&r2=55770&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/i386/page.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/i386/page.c [iso-8859-1] Tue Feb 21 00:32:24 2012
@@ -248,6 +248,10 @@
             PMMPDE PdeBase;
             ULONG PdeOffset = MiGetPdeOffset(Address);
             
+            /* Nobody but page fault should ask for creating the PDE,
+             * Which imples that Process is the current one */
+            ASSERT(Create == FALSE);
+            
             PdeBase = 
MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase[0]));
             if (PdeBase == NULL)
             {
@@ -256,24 +260,8 @@
             PointerPde = PdeBase + PdeOffset;
             if (PointerPde->u.Hard.Valid == 0)
             {
-                /* Nobody but page fault should ask for creating the PDE,
-                 * Which imples that Process is the current one */
                 MmDeleteHyperspaceMapping(PdeBase);
-                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);
-                }
+                return NULL;
             }
             else
             {
@@ -717,9 +705,10 @@
         KeBugCheck(MEMORY_MANAGEMENT);
     }
 
-    Pt = MmGetPageTableForProcess(Process, Address, TRUE);
+    Pt = MmGetPageTableForProcess(Process, Address, FALSE);
     if (Pt == NULL)
     {
+        /* Nobody should page out an address that hasn't even been mapped */
         KeBugCheck(MEMORY_MANAGEMENT);
     }
     Pte = InterlockedExchangePte(Pt, SwapEntry << 1);

Modified: trunk/reactos/ntoskrnl/mm/marea.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/marea.c?rev=55770&r1=55769&r2=55770&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/marea.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/marea.c [iso-8859-1] Tue Feb 21 00:32:24 2012
@@ -1066,6 +1066,37 @@
             KeBugCheck(MEMORY_MANAGEMENT);
       }
    }
+   
+#if (_MI_PAGING_LEVELS == 2)
+    {
+        KIRQL OldIrql;
+        PMMPDE pointerPde;
+        /* Attach to Process */
+        KeAttachProcess(&Process->Pcb);
+        
+        /* Acquire PFN lock */
+        OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+        
+        for(Address = MI_LOWEST_VAD_ADDRESS;
+            Address < MM_HIGHEST_VAD_ADDRESS;
+            Address =(PVOID)((ULONG_PTR)Address + (PAGE_SIZE * PTE_COUNT)))
+        {
+            /* At this point all references should be dead */
+            
ASSERT(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] == 0);
+            pointerPde = MiAddressToPde(Address);
+            /* Unlike in ARM3, we don't necesarrily free the PDE page as soon 
as reference reaches 0,
+             * so we must clean up a bit when process closes */
+            if(pointerPde->u.Hard.Valid)
+                MiDeletePte(pointerPde, MiPdeToPte(pointerPde), Process, NULL);
+            ASSERT(pointerPde->u.Hard.Valid == 0);
+        }
+        /* Release lock */
+        KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+        
+        /* Detach */
+        KeDetachProcess();
+    }
+#endif
 
    MmUnlockAddressSpace(&Process->Vm);
 

Modified: trunk/reactos/ntoskrnl/mm/section.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/section.c?rev=55770&r1=55769&r2=55770&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] Tue Feb 21 00:32:24 2012
@@ -119,6 +119,7 @@
    ULONG Offset;
    BOOLEAN WasDirty;
    BOOLEAN Private;
+   PEPROCESS CallingProcess;
 }
 MM_SECTION_PAGEOUT_CONTEXT;
 
@@ -2052,10 +2053,11 @@
    }
 
 #if (_MI_PAGING_LEVELS == 2)
-    if(Address < MmSystemRangeStart)
+    /* If this is for the calling process, we take care of te reference in the 
main function */
+    if((Address < MmSystemRangeStart) && (Process != 
PageOutContext->CallingProcess))
     {
-        if(Process->VmDeleted) DPRINT1("deleted!!!");
         
Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
+        
ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]
 < PTE_COUNT);
     }
 #endif
 
@@ -2091,6 +2093,7 @@
     */
    Context.Segment = MemoryArea->Data.SectionData.Segment;
    Context.Section = MemoryArea->Data.SectionData.Section;
+   Context.CallingProcess = Process;
 
    Context.Offset = (ULONG)((ULONG_PTR)Address - 
(ULONG_PTR)MemoryArea->StartingAddress
                     + MemoryArea->Data.SectionData.ViewOffset);
@@ -2223,6 +2226,14 @@
       }
       if (!Context.WasDirty && SwapEntry != 0)
       {
+#if (_MI_PAGING_LEVELS == 2)
+        /* We keep the pagefile index global to the segment, not in the PTE */
+        if(Address < MmSystemRangeStart)
+        {
+            
Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
+            
ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]
 < PTE_COUNT);
+        }
+#endif
          MmSetSavedSwapEntryPage(Page, 0);
          MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, 
MAKE_SWAP_SSE(SwapEntry));
          MmReleasePageMemoryConsumer(MC_USER, Page);
@@ -2241,6 +2252,14 @@
       }
       if (!Context.WasDirty || SwapEntry != 0)
       {
+#if (_MI_PAGING_LEVELS == 2)
+        /* We keep the pagefile index global to the segment, not in the PTE */
+         if(Address < MmSystemRangeStart)
+         {
+            
Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
+            
ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]
 < PTE_COUNT);
+         }
+#endif
          MmSetSavedSwapEntryPage(Page, 0);
          if (SwapEntry != 0)
          {
@@ -2254,6 +2273,14 @@
    }
    else if (!Context.Private && DirectMapped)
    {
+#if (_MI_PAGING_LEVELS == 2)
+      /* Read only page, no need for a pagefile entry -> PDE-- */
+      if(Address < MmSystemRangeStart)
+      {
+         
Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
+         
ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]
 < PTE_COUNT);
+      }
+#endif
       if (SwapEntry != 0)
       {
          DPRINT1("Found a swapentry for a non private and direct mapped page 
(address %x)\n",
@@ -2282,6 +2309,14 @@
                  Address);
          KeBugCheck(MEMORY_MANAGEMENT);
       }
+#if (_MI_PAGING_LEVELS == 2)
+      /* Non dirty, non private, non direct-mapped -> PDE-- */
+      if(Address < MmSystemRangeStart)
+      {
+         
Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
+         
ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]
 < PTE_COUNT);
+      }
+#endif
       MmReleasePageMemoryConsumer(MC_USER, Page);
       PageOp->Status = STATUS_SUCCESS;
       MmspCompleteAndReleasePageOp(PageOp);
@@ -2291,13 +2326,6 @@
    {
       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);
@@ -2325,13 +2353,6 @@
          /*
           * 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,
@@ -2382,13 +2403,6 @@
        * 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)
       {
@@ -2440,13 +2454,6 @@
    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);
@@ -2458,6 +2465,14 @@
    }
    else
    {
+#if (_MI_PAGING_LEVELS == 2)
+      /* We keep the pagefile index global to the segment, not in the PTE */
+      if(Address < MmSystemRangeStart)
+      {
+         
Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--;
+         
ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]
 < PTE_COUNT);
+      }
+#endif
       Entry = MAKE_SWAP_SSE(SwapEntry);
       MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, Entry);
    }


Reply via email to