From 9b201b7180aecdbd01af148dbfa7385df8f885ac Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Wed, 6 Aug 2014 21:53:57 +0000 Subject: [PATCH] [NTOS/MM] - 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 | 6 +++ reactos/ntoskrnl/mm/ARM3/pfnlist.c | 10 ++-- reactos/ntoskrnl/mm/ARM3/section.c | 79 +++++++++++++++++++++++++++++- reactos/ntoskrnl/mm/ARM3/virtual.c | 10 +++- reactos/ntoskrnl/mm/balance.c | 5 -- reactos/ntoskrnl/mm/section.c | 7 +++ 6 files changed, 105 insertions(+), 12 deletions(-) diff --git a/reactos/ntoskrnl/mm/ARM3/miarm.h b/reactos/ntoskrnl/mm/ARM3/miarm.h index 6e803aeb7d0..8a842e5ef08 100644 --- a/reactos/ntoskrnl/mm/ARM3/miarm.h +++ b/reactos/ntoskrnl/mm/ARM3/miarm.h @@ -2274,6 +2274,12 @@ MiLocateSubsection( IN ULONG_PTR Vpn ); +VOID +NTAPI +MiDeleteARM3Section( + PVOID ObjectBody +); + NTSTATUS NTAPI MiQueryMemorySectionName( diff --git a/reactos/ntoskrnl/mm/ARM3/pfnlist.c b/reactos/ntoskrnl/mm/ARM3/pfnlist.c index 12b33cec0e7..9c4d3f5bb17 100644 --- a/reactos/ntoskrnl/mm/ARM3/pfnlist.c +++ b/reactos/ntoskrnl/mm/ARM3/pfnlist.c @@ -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? */ diff --git a/reactos/ntoskrnl/mm/ARM3/section.c b/reactos/ntoskrnl/mm/ARM3/section.c index f8ae660db29..f3063d0c389 100644 --- a/reactos/ntoskrnl/mm/ARM3/section.c +++ b/reactos/ntoskrnl/mm/ARM3/section.c @@ -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 diff --git a/reactos/ntoskrnl/mm/ARM3/virtual.c b/reactos/ntoskrnl/mm/ARM3/virtual.c index 97d76011596..932e1d04ac2 100644 --- a/reactos/ntoskrnl/mm/ARM3/virtual.c +++ b/reactos/ntoskrnl/mm/ARM3/virtual.c @@ -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 */ diff --git a/reactos/ntoskrnl/mm/balance.c b/reactos/ntoskrnl/mm/balance.c index d06e0ee4434..3296b223ef1 100644 --- a/reactos/ntoskrnl/mm/balance.c +++ b/reactos/ntoskrnl/mm/balance.c @@ -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 { diff --git a/reactos/ntoskrnl/mm/section.c b/reactos/ntoskrnl/mm/section.c index e30cc2a0f86..7875c7a51cd 100644 --- a/reactos/ntoskrnl/mm/section.c +++ b/reactos/ntoskrnl/mm/section.c @@ -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) { -- 2.17.1