[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
This commit is contained in:
Jérôme Gardou 2014-08-06 21:53:57 +00:00
parent 9aec0d47eb
commit 9b201b7180
6 changed files with 105 additions and 12 deletions

View file

@ -2274,6 +2274,12 @@ MiLocateSubsection(
IN ULONG_PTR Vpn
);
VOID
NTAPI
MiDeleteARM3Section(
PVOID ObjectBody
);
NTSTATUS
NTAPI
MiQueryMemorySectionName(

View 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? */

View 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

View 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 */

View 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
{

View 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)
{