https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6a5fd8f48795ab1819484b433194ee9357eb8bf1

commit 6a5fd8f48795ab1819484b433194ee9357eb8bf1
Author:     Jérôme Gardou <[email protected]>
AuthorDate: Tue May 11 12:03:52 2021 +0200
Commit:     Jérôme Gardou <[email protected]>
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)

Reply via email to