https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6a5fd8f48795ab1819484…
commit 6a5fd8f48795ab1819484b433194ee9357eb8bf1
Author: Jérôme Gardou <jerome.gardou(a)reactos.org>
AuthorDate: Tue May 11 12:03:52 2021 +0200
Commit: Jérôme Gardou <zefklop(a)users.noreply.github.com>
CommitDate: Tue May 18 23:42:19 2021 +0200
[NTOS:MM] Relax requirements with regards to PFN lock when adding & removing
entries in Working Sets
Once a page is used, holding the WS lock is enough until you want to free it.
---
ntoskrnl/mm/ARM3/miarm.h | 9 ++++++
ntoskrnl/mm/ARM3/procsup.c | 6 ++--
ntoskrnl/mm/ARM3/wslist.cpp | 79 +++++++++++++++++++++++++--------------------
3 files changed, 56 insertions(+), 38 deletions(-)
diff --git a/ntoskrnl/mm/ARM3/miarm.h b/ntoskrnl/mm/ARM3/miarm.h
index adb6af3fd91..730acdd8bf1 100644
--- a/ntoskrnl/mm/ARM3/miarm.h
+++ b/ntoskrnl/mm/ARM3/miarm.h
@@ -1052,6 +1052,15 @@ MM_ANY_WS_LOCK_HELD(IN PETHREAD Thread)
(Thread->OwnsSessionWorkingSetShared));
}
+FORCEINLINE
+BOOLEAN
+MM_ANY_WS_LOCK_HELD_EXCLUSIVE(_In_ PETHREAD Thread)
+{
+ return ((Thread->OwnsProcessWorkingSetExclusive) ||
+ (Thread->OwnsSystemWorkingSetExclusive) ||
+ (Thread->OwnsSessionWorkingSetExclusive));
+}
+
//
// Checks if the process owns the working set lock
//
diff --git a/ntoskrnl/mm/ARM3/procsup.c b/ntoskrnl/mm/ARM3/procsup.c
index aa9133b1929..5f24a8a0b95 100644
--- a/ntoskrnl/mm/ARM3/procsup.c
+++ b/ntoskrnl/mm/ARM3/procsup.c
@@ -993,6 +993,9 @@ MmInitializeProcessAddressSpace(IN PEPROCESS Process,
PageFrameNumber = PFN_FROM_PTE(PointerPte);
MiInitializePfn(PageFrameNumber, PointerPte, TRUE);
+ /* All our pages are now active & valid. Release the lock. */
+ MiReleasePfnLock(OldIrql);
+
/* This should be in hyper space, but not in the mapping range */
Process->Vm.VmWorkingSetList = MmWorkingSetList;
ASSERT(((ULONG_PTR)MmWorkingSetList >= MI_MAPPING_RANGE_END) &&
((ULONG_PTR)MmWorkingSetList <= HYPER_SPACE_END));
@@ -1016,9 +1019,6 @@ MmInitializeProcessAddressSpace(IN PEPROCESS Process,
/* Sanity check */
ASSERT(Process->PhysicalVadRoot == NULL);
- /* Release PFN lock */
- MiReleasePfnLock(OldIrql);
-
/* Release the process working set */
MiUnlockProcessWorkingSet(Process, PsGetCurrentThread());
#ifdef _M_AMD64
diff --git a/ntoskrnl/mm/ARM3/wslist.cpp b/ntoskrnl/mm/ARM3/wslist.cpp
index 430e2c1a564..91cd87b354f 100644
--- a/ntoskrnl/mm/ARM3/wslist.cpp
+++ b/ntoskrnl/mm/ARM3/wslist.cpp
@@ -84,11 +84,15 @@ static void FreeWsleIndex(PMMWSL WsList, ULONG Index)
ASSERT(MiPteToAddress(PointerPte) != WsList);
PFN_NUMBER Page = PFN_FROM_PTE(PointerPte);
- PMMPFN Pfn = MiGetPfnEntry(Page);
- MI_SET_PFN_DELETED(Pfn);
- MiDecrementShareCount(MiGetPfnEntry(Pfn->u4.PteFrame),
Pfn->u4.PteFrame);
- MiDecrementShareCount(Pfn, Page);
+ {
+ MiPfnLockGuard PfnLock;
+
+ PMMPFN Pfn = MiGetPfnEntry(Page);
+ MI_SET_PFN_DELETED(Pfn);
+ MiDecrementShareCount(MiGetPfnEntry(Pfn->u4.PteFrame),
Pfn->u4.PteFrame);
+ MiDecrementShareCount(Pfn, Page);
+ }
PointerPte->u.Long = 0;
@@ -172,8 +176,13 @@ static ULONG GetFreeWsleIndex(PMMWSL WsList)
PMMPTE PointerPte =
MiAddressToPte(&WsList->Wsle[WsList->LastInitializedWsle]);
ASSERT(PointerPte->u.Hard.Valid == 0);
MMPTE TempPte = GetPteTemplateForWsList(WsList);
- TempPte.u.Hard.PageFrameNumber =
MiRemoveAnyPage(GetNextPageColorForWsList(WsList));
- MiInitializePfnAndMakePteValid(TempPte.u.Hard.PageFrameNumber, PointerPte,
TempPte);
+ {
+ MiPfnLockGuard PfnLock;
+
+ TempPte.u.Hard.PageFrameNumber =
MiRemoveAnyPage(GetNextPageColorForWsList(WsList));
+ MiInitializePfnAndMakePteValid(TempPte.u.Hard.PageFrameNumber,
PointerPte, TempPte);
+ }
+
WsList->LastInitializedWsle += PAGE_SIZE / sizeof(MMWSLE);
}
}
@@ -187,8 +196,7 @@ VOID
RemoveFromWsList(PMMWSL WsList, PVOID Address)
{
/* Make sure that we are holding the right locks. */
- ASSERT(MM_ANY_WS_LOCK_HELD(PsGetCurrentThread()));
- MI_ASSERT_PFN_LOCK_HELD();
+ ASSERT(MM_ANY_WS_LOCK_HELD_EXCLUSIVE(PsGetCurrentThread()));
PMMPTE PointerPte = MiAddressToPte(Address);
@@ -262,37 +270,37 @@ TrimWsList(PMMWSL WsList)
/* Please put yourself aside and make place for the younger ones */
PFN_NUMBER Page = PFN_FROM_PTE(PointerPte);
- KIRQL OldIrql = MiAcquirePfnLock();
+ {
+ MiPfnLockGuard PfnLock;
- PMMPFN Pfn = MiGetPfnEntry(Page);
+ PMMPFN Pfn = MiGetPfnEntry(Page);
- /* Not supported yet */
- ASSERT(Pfn->u3.e1.PrototypePte == 0);
- ASSERT(!MI_IS_ROS_PFN(Pfn));
+ /* Not supported yet */
+ ASSERT(Pfn->u3.e1.PrototypePte == 0);
+ ASSERT(!MI_IS_ROS_PFN(Pfn));
- /* FIXME: Remove this hack when possible */
- if (Pfn->Wsle.u1.e1.LockedInMemory || (Pfn->Wsle.u1.e1.LockedInWs))
- {
- MiReleasePfnLock(OldIrql);
- continue;
- }
+ /* FIXME: Remove this hack when possible */
+ if (Pfn->Wsle.u1.e1.LockedInMemory || (Pfn->Wsle.u1.e1.LockedInWs))
+ {
+ continue;
+ }
- /* We can remove it from the list. Save Protection first */
- ULONG Protection = Entry.u1.e1.Protection;
- RemoveFromWsList(WsList, Entry.u1.VirtualAddress);
+ /* We can remove it from the list. Save Protection first */
+ ULONG Protection = Entry.u1.e1.Protection;
+ RemoveFromWsList(WsList, Entry.u1.VirtualAddress);
- /* Dirtify the page, if needed */
- if (PointerPte->u.Hard.Dirty)
- Pfn->u3.e1.Modified = 1;
+ /* Dirtify the page, if needed */
+ if (PointerPte->u.Hard.Dirty)
+ Pfn->u3.e1.Modified = 1;
- /* Make this a transition PTE */
- MI_MAKE_TRANSITION_PTE(PointerPte, Page, Protection);
- KeInvalidateTlbEntry(MiAddressToPte(PointerPte));
+ /* Make this a transition PTE */
+ MI_MAKE_TRANSITION_PTE(PointerPte, Page, Protection);
+ KeInvalidateTlbEntry(MiAddressToPte(PointerPte));
- /* Drop the share count. This will take care of putting it in the standby or
modified list. */
- MiDecrementShareCount(Pfn, Page);
+ /* Drop the share count. This will take care of putting it in the standby or
modified list. */
+ MiDecrementShareCount(Pfn, Page);
+ }
- MiReleasePfnLock(OldIrql);
Ret++;
}
return Ret;
@@ -302,6 +310,7 @@ TrimWsList(PMMWSL WsList)
extern "C"
{
+_Use_decl_annotations_
VOID
NTAPI
MiInsertInWorkingSetList(
@@ -311,9 +320,8 @@ MiInsertInWorkingSetList(
{
PMMWSL WsList = Vm->VmWorkingSetList;
- /* Make sure that we are holding the right locks. */
- ASSERT(MM_ANY_WS_LOCK_HELD(PsGetCurrentThread()));
- MI_ASSERT_PFN_LOCK_HELD();
+ /* Make sure that we are holding the WS lock. */
+ ASSERT(MM_ANY_WS_LOCK_HELD_EXCLUSIVE(PsGetCurrentThread()));
PMMPTE PointerPte = MiAddressToPte(Address);
@@ -345,6 +353,7 @@ MiInsertInWorkingSetList(
Vm->PeakWorkingSetSize = Vm->WorkingSetSize;
}
+_Use_decl_annotations_
VOID
NTAPI
MiRemoveFromWorkingSetList(
@@ -356,7 +365,7 @@ MiRemoveFromWorkingSetList(
Vm->WorkingSetSize -= PAGE_SIZE;
}
-_Requires_exclusive_lock_held_(WorkingSet->WorkingSetMutex)
+_Use_decl_annotations_
VOID
NTAPI
MiInitializeWorkingSetList(_Inout_ PMMSUPPORT WorkingSet)