[NTOS/MM]
authorJérôme Gardou <jerome.gardou@reactos.org>
Wed, 6 Aug 2014 21:53:57 +0000 (21:53 +0000)
committerJérôme Gardou <jerome.gardou@reactos.org>
Wed, 6 Aug 2014 21:53:57 +0000 (21:53 +0000)
 - Call the right delete routine for ARM3 section object
 - Properly free the pages of pagefile-backed segments when those are deleted
 - Put the right assert at the right place in MmUnlinkPageFromList
 - Remove DPRINT from previous commit which is interesting but noisy

svn path=/trunk/; revision=63822

reactos/ntoskrnl/mm/ARM3/miarm.h
reactos/ntoskrnl/mm/ARM3/pfnlist.c
reactos/ntoskrnl/mm/ARM3/section.c
reactos/ntoskrnl/mm/ARM3/virtual.c
reactos/ntoskrnl/mm/balance.c
reactos/ntoskrnl/mm/section.c

index 6e803ae..8a842e5 100644 (file)
@@ -2274,6 +2274,12 @@ MiLocateSubsection(
     IN ULONG_PTR Vpn
 );
 
+VOID
+NTAPI
+MiDeleteARM3Section(
+    PVOID ObjectBody
+);
+
 NTSTATUS
 NTAPI
 MiQueryMemorySectionName(
index 12b33ce..9c4d3f5 100644 (file)
@@ -338,10 +338,11 @@ MiUnlinkPageFromList(IN PMMPFN Pfn)
 
     /* We are not on a list anymore */
     Pfn->u1.Flink = Pfn->u2.Blink = 0;
-    ASSERT_LIST_INVARIANT(ListHead);
 
     /* Remove one entry from the list */
     ListHead->Total--;
+
+    ASSERT_LIST_INVARIANT(ListHead);
 }
 
 PFN_NUMBER
@@ -1234,6 +1235,9 @@ MiDecrementShareCount(IN PMMPFN Pfn1,
                      0);
     }
 
+    /* Page should at least have one reference */
+    ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
+
     /* Check if the share count is now 0 */
     ASSERT(Pfn1->u2.ShareCount < 0xF000000);
     if (!--Pfn1->u2.ShareCount)
@@ -1257,7 +1261,7 @@ MiDecrementShareCount(IN PMMPFN Pfn1,
             TempPte.u.Soft.Prototype = 0;
             TempPte.u.Soft.Protection = Pfn1->OriginalPte.u.Soft.Protection;
             MI_WRITE_INVALID_PTE(PointerPte, TempPte);
-            DPRINT("Marking PTE: %p as transition (%p - %lx)\n", PointerPte, Pfn1, MiGetPfnEntryIndex(Pfn1));
+            DPRINT1("Marking PTE: %p as transition (%p - %lx)\n", PointerPte, Pfn1, MiGetPfnEntryIndex(Pfn1));
         }
 
         /* Put the page in transition */
@@ -1266,8 +1270,6 @@ MiDecrementShareCount(IN PMMPFN Pfn1,
         /* PFN lock must be held */
         ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
 
-        /* Page should at least have one reference */
-        ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
         if (Pfn1->u3.e2.ReferenceCount == 1)
         {
             /* Is there still a PFN for this page? */
index f8ae660..f3063d0 100644 (file)
@@ -608,6 +608,8 @@ MiSegmentDelete(IN PSEGMENT Segment)
     SEGMENT_FLAGS SegmentFlags;
     PSUBSECTION Subsection;
     PMMPTE PointerPte, LastPte, PteForProto;
+    PMMPFN Pfn1;
+    PFN_NUMBER PageFrameIndex;
     MMPTE TempPte;
     KIRQL OldIrql;
 
@@ -621,7 +623,7 @@ MiSegmentDelete(IN PSEGMENT Segment)
 
     /* These things are not supported yet */
     ASSERT(ControlArea->DereferenceList.Flink == NULL);
-    ASSERT(!(ControlArea->u.Flags.Image) & !(ControlArea->u.Flags.File));
+    ASSERT(!(ControlArea->u.Flags.Image) && !(ControlArea->u.Flags.File));
     ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
     ASSERT(ControlArea->u.Flags.Rom == 0);
 
@@ -661,7 +663,52 @@ MiSegmentDelete(IN PSEGMENT Segment)
         TempPte = *PointerPte;
         ASSERT(SegmentFlags.LargePages == 0);
         ASSERT(TempPte.u.Hard.Valid == 0);
-        ASSERT(TempPte.u.Soft.Prototype == 1);
+
+        /* See if we should clean things up */
+        if (!(ControlArea->u.Flags.Image) && !(ControlArea->u.Flags.File))
+        {
+            /*
+             * This is a section backed by the pagefile. Now that it doesn't exist anymore,
+             * we can give everything back to the system.
+             */
+            ASSERT(TempPte.u.Soft.Prototype == 0);
+
+            if (TempPte.u.Soft.Transition == 1)
+            {
+                /* We can give the page back for other use */
+                DPRINT1("Releasing page for transition PTE %p\n", PointerPte);
+                PageFrameIndex = PFN_FROM_PTE(&TempPte);
+                Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
+
+                /* As this is a paged-backed section, nobody should reference it anymore (no cache or whatever) */
+                ASSERT(Pfn1->u3.ReferenceCount == 0);
+
+                /* And it should be in standby or modified list */
+                ASSERT((Pfn1->u3.e1.PageLocation == ModifiedPageList) || (Pfn1->u3.e1.PageLocation == StandbyPageList));
+
+                /* Unlink it and put it back in free list */
+                MiUnlinkPageFromList(Pfn1);
+
+                /* Temporarily mark this as active and make it free again */
+                Pfn1->u3.e1.PageLocation = ActiveAndValid;
+                MI_SET_PFN_DELETED(Pfn1);
+
+                MiInsertPageInFreeList(PageFrameIndex);
+            }
+            else if (TempPte.u.Soft.PageFileHigh != 0)
+            {
+                /* Should not happen for now */
+                ASSERT(FALSE);
+            }
+        }
+        else
+        {
+            /* unsupported for now */
+            ASSERT(FALSE);
+
+            /* File-backed section must have prototype PTEs */
+            ASSERT(TempPte.u.Soft.Prototype == 1);
+        }
 
         /* Zero the PTE and keep going */
         PointerPte->u.Long = 0;
@@ -3050,6 +3097,34 @@ MmCommitSessionMappedView(IN PVOID MappedBase,
     return STATUS_SUCCESS;
 }
 
+VOID
+NTAPI
+MiDeleteARM3Section(PVOID ObjectBody)
+{
+    PSECTION SectionObject;
+    PCONTROL_AREA ControlArea;
+    KIRQL OldIrql;
+
+    SectionObject = (PSECTION)ObjectBody;
+
+    /* Lock the PFN database */
+    OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+    ASSERT(SectionObject->Segment);
+    ASSERT(SectionObject->Segment->ControlArea);
+
+    ControlArea = SectionObject->Segment->ControlArea;
+
+    /* Dereference */
+    ControlArea->NumberOfSectionReferences--;
+    ControlArea->NumberOfUserReferences--;
+
+    ASSERT(ControlArea->u.Flags.BeingDeleted == 0);
+
+    /* Check it. It will delete it if there is no more reference to it */
+    MiCheckControlArea(ControlArea, OldIrql);
+}
+
 /* SYSTEM CALLS ***************************************************************/
 
 NTSTATUS
index 97d7601..932e1d0 100644 (file)
@@ -423,10 +423,18 @@ MiDeletePte(IN PMMPTE PointerPte,
             /* Drop the reference on the page table. */
             MiDecrementShareCount(MiGetPfnEntry(Pfn1->u4.PteFrame), Pfn1->u4.PteFrame);
 
+            ASSERT(Pfn1->u3.e1.PrototypePte == 0);
+
+            /* Make the page free. For prototypes, it will be made free when deleting the section object */
             if (Pfn1->u2.ShareCount == 0)
             {
                 NT_ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
-                /* Mark the page temporarily as valid, we're going to make it free soon */
+
+                /* And it should be in standby or modified list */
+                ASSERT((Pfn1->u3.e1.PageLocation == ModifiedPageList) || (Pfn1->u3.e1.PageLocation == StandbyPageList));
+
+                /* Unlink it and put it back in free list */
+                MiUnlinkPageFromList(Pfn1);
                 Pfn1->u3.e1.PageLocation = ActiveAndValid;
 
                 /* Bring it back into the free list */
index d06e0ee..3296b22 100644 (file)
@@ -356,8 +356,6 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
 }
 
 
-extern MMPFNLIST MmModifiedPageListByColor[];
-
 VOID NTAPI
 MiBalancerThread(PVOID Unused)
 {
@@ -427,9 +425,6 @@ MiBalancerThread(PVOID Unused)
                   KeBugCheck(NO_PAGES_AVAILABLE);
               }
           } while (InitialTarget != 0);
-
-          if (MmModifiedPageListByColor[0].Total != 0)
-              DPRINT1("There are %u pages ready to be paged out in the modified list.\n", MmModifiedPageListByColor[0].Total);
       }
       else
       {
index e30cc2a..7875c7a 100644 (file)
@@ -2624,6 +2624,13 @@ MmpDeleteSection(PVOID ObjectBody)
 {
    PROS_SECTION_OBJECT Section = (PROS_SECTION_OBJECT)ObjectBody;
 
+    /* Check if it's an ARM3, or ReactOS section */
+    if (!MiIsRosSectionObject(Section))
+    {
+        MiDeleteARM3Section(ObjectBody);
+        return;
+    }
+
    DPRINT("MmpDeleteSection(ObjectBody %p)\n", ObjectBody);
    if (Section->AllocationAttributes & SEC_IMAGE)
    {