Author: sir_richard
Date: Thu Jul 22 18:26:04 2010
New Revision: 48187
URL:
http://svn.reactos.org/svn/reactos?rev=48187&view=rev
Log:
[NTOS]: Fix a very stupid bug which made any machine with less than 52GB of RAM appear as
a "Small memory machine" (instead of 13MB).
[NTOS]: Initialize MmTotalCommitLimit, MmTotalCommitLimitMaximum for consistency.
[NTOS]: Initialize and honor MmAllocationFragment value from registry, or from defaults.
[NTOS]: Initialize the system cache working set pushlock.
[NTOS]: Implement Mi(Un)Lock(Process)WorkingSet inlines to handle the various scenarios.
Replace broken/hacky code that was in the system loader, fault handler, and VM deletion
paths with the correct macros. No locking is done yet as ReactOS' MAREA implementation
overloads the Vm field in EPROCESS, but the correct APC blockings and state transitions
are done.
[NTOS]: Add another helper from symbols, MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS, and use it
instead of the math-by-hand.
[NTOS]: Add MM_IS_ANY_LOCK_HELD and MI_WS_OWNER to help out the new working let locking
inlines (names taken from symbols).
[NTOS]: Add _1GB helper for large-memory checks. Also define _1KB as "1024u".
The "u" makes GCC not complain when sizes reach >= 2GB, because GCC will
interpret the integer literals as "signed", even if the final calculated value
is in an unsigned variable.
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
trunk/reactos/ntoskrnl/mm/ARM3/mminit.c
trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
trunk/reactos/ntoskrnl/mm/ARM3/sysldr.c
trunk/reactos/ntoskrnl/mm/ARM3/virtual.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/miarm.h?r…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] Thu Jul 22 18:26:04 2010
@@ -8,35 +8,39 @@
#ifndef _M_AMD64
-#define MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING ((255*1024*1024) >> PAGE_SHIFT)
-#define MI_MIN_PAGES_FOR_SYSPTE_TUNING ((19*1024*1024) >> PAGE_SHIFT)
-#define MI_MIN_PAGES_FOR_SYSPTE_BOOST ((32*1024*1024) >> PAGE_SHIFT)
-#define MI_MAX_INIT_NONPAGED_POOL_SIZE (128 * 1024 * 1024)
-#define MI_MAX_NONPAGED_POOL_SIZE (128 * 1024 * 1024)
-#define MI_MAX_FREE_PAGE_LISTS 4
-
-#define MI_MIN_INIT_PAGED_POOLSIZE (32 * 1024 * 1024)
-
-#define MI_SESSION_VIEW_SIZE (20 * 1024 * 1024)
-#define MI_SESSION_POOL_SIZE (16 * 1024 * 1024)
-#define MI_SESSION_IMAGE_SIZE (8 * 1024 * 1024)
-#define MI_SESSION_WORKING_SET_SIZE (4 * 1024 * 1024)
-#define MI_SESSION_SIZE (MI_SESSION_VIEW_SIZE + \
- MI_SESSION_POOL_SIZE + \
- MI_SESSION_IMAGE_SIZE + \
- MI_SESSION_WORKING_SET_SIZE)
-
-#define MI_SYSTEM_VIEW_SIZE (16 * 1024 * 1024)
-
-#define MI_SYSTEM_CACHE_WS_START (PVOID)0xC0C00000
-#define MI_PAGED_POOL_START (PVOID)0xE1000000
-#define MI_NONPAGED_POOL_END (PVOID)0xFFBE0000
-#define MI_DEBUG_MAPPING (PVOID)0xFFBFF000
+#define MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING ((255 * _1MB) >> PAGE_SHIFT)
+#define MI_MIN_PAGES_FOR_SYSPTE_TUNING ((19 * _1MB) >> PAGE_SHIFT)
+#define MI_MIN_PAGES_FOR_SYSPTE_BOOST ((32 * _1MB) >> PAGE_SHIFT)
+#define MI_MAX_INIT_NONPAGED_POOL_SIZE (128 * _1MB)
+#define MI_MAX_NONPAGED_POOL_SIZE (128 * _1MB)
+#define MI_MAX_FREE_PAGE_LISTS 4
+
+#define MI_MIN_INIT_PAGED_POOLSIZE (32 * _1MB)
+
+#define MI_SESSION_VIEW_SIZE (20 * _1MB)
+#define MI_SESSION_POOL_SIZE (16 * _1MB)
+#define MI_SESSION_IMAGE_SIZE (8 * _1MB)
+#define MI_SESSION_WORKING_SET_SIZE (4 * _1MB)
+#define MI_SESSION_SIZE (MI_SESSION_VIEW_SIZE + \
+ MI_SESSION_POOL_SIZE + \
+ MI_SESSION_IMAGE_SIZE + \
+ MI_SESSION_WORKING_SET_SIZE)
+
+#define MI_SYSTEM_VIEW_SIZE (16 * _1MB)
+
+#define MI_SYSTEM_CACHE_WS_START (PVOID)0xC0C00000
+#define MI_PAGED_POOL_START (PVOID)0xE1000000
+#define MI_NONPAGED_POOL_END (PVOID)0xFFBE0000
+#define MI_DEBUG_MAPPING (PVOID)0xFFBFF000
#define MI_MIN_SECONDARY_COLORS 8
#define MI_SECONDARY_COLORS 64
#define MI_MAX_SECONDARY_COLORS 1024
+#define MI_MIN_ALLOCATION_FRAGMENT (4 * _1KB)
+#define MI_ALLOCATION_FRAGMENT (64 * _1KB)
+#define MI_MAX_ALLOCATION_FRAGMENT (2 * _1MB)
+
#define MM_HIGHEST_VAD_ADDRESS \
(PVOID)((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (16 * PAGE_SIZE))
@@ -46,8 +50,9 @@
#endif /* !_M_AMD64 */
/* Make the code cleaner with some definitions for size multiples */
-#define _1KB (1024)
+#define _1KB (1024u)
#define _1MB (1024 * _1KB)
+#define _1GB (1024 * _1MB)
/* Area mapped by a PDE */
#define PDE_MAPPED_VA (PTE_COUNT * PAGE_SIZE)
@@ -199,6 +204,9 @@
#define MI_IS_SYSTEM_PAGE_TABLE_ADDRESS(Address) \
(((Address) >= (PVOID)MiAddressToPte(MmSystemRangeStart)) && ((Address)
<= (PVOID)PTE_TOP))
+#define MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address) \
+ (((PVOID)(Address) >= (PVOID)PTE_BASE) && ((PVOID)(Address) <=
(PVOID)MmHyperSpaceEnd))
+
//
// Corresponds to MMPTE_SOFTWARE.Protection
//
@@ -608,6 +616,165 @@
*PointerPte = InvalidPte;
}
+//
+// Checks if the thread already owns a working set
+//
+FORCEINLINE
+BOOLEAN
+MM_ANY_WS_LOCK_HELD(IN PETHREAD Thread)
+{
+ /* If any of these are held, return TRUE */
+ return ((Thread->OwnsProcessWorkingSetExclusive) ||
+ (Thread->OwnsProcessWorkingSetShared) ||
+ (Thread->OwnsSystemWorkingSetExclusive) ||
+ (Thread->OwnsSystemWorkingSetShared) ||
+ (Thread->OwnsSessionWorkingSetExclusive) ||
+ (Thread->OwnsSessionWorkingSetShared));
+}
+
+//
+// Checks if the process owns the working set lock
+//
+FORCEINLINE
+BOOLEAN
+MI_WS_OWNER(IN PEPROCESS Process)
+{
+ /* Check if this process is the owner, and that the thread owns the WS */
+ return ((KeGetCurrentThread()->ApcState.Process == &Process->Pcb)
&&
+ ((PsGetCurrentThread()->OwnsProcessWorkingSetExclusive) ||
+ (PsGetCurrentThread()->OwnsProcessWorkingSetShared)));
+}
+
+//
+// Locks the working set for the given process
+//
+FORCEINLINE
+VOID
+MiLockProcessWorkingSet(IN PEPROCESS Process,
+ IN PETHREAD Thread)
+{
+ /* Shouldn't already be owning the process working set */
+ ASSERT(Thread->OwnsProcessWorkingSetShared == FALSE);
+ ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
+
+ /* Block APCs, make sure that still nothing is already held */
+ KeEnterGuardedRegion();
+ ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
+
+ /* FIXME: Actually lock it (we can't because Vm is used by MAREAs) */
+
+ /* FIXME: This also can't be checked because Vm is used by MAREAs) */
+ //ASSERT(Process->Vm.Flags.AcquiredUnsafe == 0);
+
+ /* Okay, now we can own it exclusively */
+ ASSERT(Thread->OwnsProcessWorkingSetExclusive == FALSE);
+ Thread->OwnsProcessWorkingSetExclusive = TRUE;
+}
+
+//
+// Unlocks the working set for the given process
+//
+FORCEINLINE
+VOID
+MiUnlockProcessWorkingSet(IN PEPROCESS Process,
+ IN PETHREAD Thread)
+{
+ /* Make sure this process really is owner, and it was a safe acquisition */
+ ASSERT(MI_WS_OWNER(Process));
+ /* This can't be checked because Vm is used by MAREAs) */
+ //ASSERT(Process->Vm.Flags.AcquiredUnsafe == 0);
+
+ /* The thread doesn't own it anymore */
+ ASSERT(Thread->OwnsProcessWorkingSetExclusive == TRUE);
+ Thread->OwnsProcessWorkingSetExclusive = FALSE;
+
+ /* FIXME: Actually release it (we can't because Vm is used by MAREAs) */
+
+ /* Unblock APCs */
+ KeLeaveGuardedRegion();
+}
+
+//
+// Locks the working set
+//
+FORCEINLINE
+VOID
+MiLockWorkingSet(IN PETHREAD Thread,
+ IN PMMSUPPORT WorkingSet)
+{
+ /* Block APCs */
+ KeEnterGuardedRegion();
+
+ /* Working set should be in global memory */
+ ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
+
+ /* Thread shouldn't already be owning something */
+ ASSERT(!MM_ANY_WS_LOCK_HELD(Thread));
+
+ /* FIXME: Actually lock it (we can't because Vm is used by MAREAs) */
+
+ /* Which working set is this? */
+ if (WorkingSet == &MmSystemCacheWs)
+ {
+ /* Own the system working set */
+ ASSERT((Thread->OwnsSystemWorkingSetExclusive == FALSE) &&
+ (Thread->OwnsSystemWorkingSetShared == FALSE));
+ Thread->OwnsSystemWorkingSetExclusive = TRUE;
+ }
+ else if (WorkingSet->Flags.SessionSpace)
+ {
+ /* We don't implement this yet */
+ UNIMPLEMENTED;
+ while (TRUE);
+ }
+ else
+ {
+ /* Own the process working set */
+ ASSERT((Thread->OwnsProcessWorkingSetExclusive == FALSE) &&
+ (Thread->OwnsProcessWorkingSetShared == FALSE));
+ Thread->OwnsProcessWorkingSetExclusive = TRUE;
+ }
+}
+
+//
+// Unlocks the working set
+//
+FORCEINLINE
+VOID
+MiUnlockWorkingSet(IN PETHREAD Thread,
+ IN PMMSUPPORT WorkingSet)
+{
+ /* Working set should be in global memory */
+ ASSERT(MI_IS_SESSION_ADDRESS((PVOID)WorkingSet) == FALSE);
+
+ /* Which working set is this? */
+ if (WorkingSet == &MmSystemCacheWs)
+ {
+ /* Release the system working set */
+ ASSERT((Thread->OwnsSystemWorkingSetExclusive == TRUE) ||
+ (Thread->OwnsSystemWorkingSetShared == TRUE));
+ Thread->OwnsSystemWorkingSetExclusive = FALSE;
+ }
+ else if (WorkingSet->Flags.SessionSpace)
+ {
+ /* We don't implement this yet */
+ UNIMPLEMENTED;
+ while (TRUE);
+ }
+ else
+ {
+ /* Release the process working set */
+ ASSERT((Thread->OwnsProcessWorkingSetExclusive) ||
+ (Thread->OwnsProcessWorkingSetShared));
+ Thread->OwnsProcessWorkingSetExclusive = FALSE;
+ }
+
+ /* FIXME: Actually release it (we can't because Vm is used by MAREAs) */
+
+ /* Unblock APCs */
+ KeLeaveGuardedRegion();
+}
+
NTSTATUS
NTAPI
MmArmInitSystem(
Modified: trunk/reactos/ntoskrnl/mm/ARM3/mminit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/mminit.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/mminit.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/mminit.c [iso-8859-1] Thu Jul 22 18:26:04 2010
@@ -327,6 +327,26 @@
/* FIXME: Move to cache/working set code later */
BOOLEAN MmLargeSystemCache;
+
+/*
+ * This value determines in how many fragments/chunks the subsection prototype
+ * PTEs should be allocated when mapping a section object. It is configurable in
+ * the registry through the MapAllocationFragment parameter.
+ *
+ * The default is 64KB on systems with more than 1GB of RAM, 32KB on systems with
+ * more than 256MB of RAM, and 16KB on systems with less than 256MB of RAM.
+ *
+ * The maximum it can be set to is 2MB, and the minimum is 4KB.
+ */
+SIZE_T MmAllocationFragment;
+
+/*
+ * These two values track how much virtual memory can be committed, and when
+ * expansion should happen.
+ */
+ // FIXME: They should be moved elsewhere since it's not an "init"
setting?
+SIZE_T MmTotalCommitLimit;
+SIZE_T MmTotalCommitLimitMaximum;
/* PRIVATE FUNCTIONS **********************************************************/
@@ -1799,6 +1819,44 @@
DPRINT("System PTE count has been tuned to %d (%d bytes)\n",
MmNumberOfSystemPtes, MmNumberOfSystemPtes * PAGE_SIZE);
+
+ /* Initialize the working set lock */
+ ExInitializePushLock((PULONG_PTR)&MmSystemCacheWs.WorkingSetMutex);
+
+ /* Set commit limit */
+ MmTotalCommitLimit = 2 * _1GB;
+ MmTotalCommitLimitMaximum = MmTotalCommitLimit;
+
+ /* Has the allocation fragment been setup? */
+ if (!MmAllocationFragment)
+ {
+ /* Use the default value */
+ MmAllocationFragment = MI_ALLOCATION_FRAGMENT;
+ if (PageCount < ((256 * _1MB) / PAGE_SIZE))
+ {
+ /* On memory systems with less than 256MB, divide by 4 */
+ MmAllocationFragment = MI_ALLOCATION_FRAGMENT / 4;
+ }
+ else if (PageCount < (_1GB / PAGE_SIZE))
+ {
+ /* On systems with less than 1GB, divide by 2 */
+ MmAllocationFragment = MI_ALLOCATION_FRAGMENT / 2;
+ }
+ }
+ else
+ {
+ /* Convert from 1KB fragments to pages */
+ MmAllocationFragment *= _1KB;
+ MmAllocationFragment = ROUND_TO_PAGES(MmAllocationFragment);
+
+ /* Don't let it past the maximum */
+ MmAllocationFragment = min(MmAllocationFragment,
+ MI_MAX_ALLOCATION_FRAGMENT);
+
+ /* Don't let it too small either */
+ MmAllocationFragment = max(MmAllocationFragment,
+ MI_MIN_ALLOCATION_FRAGMENT);
+ }
/* Initialize the platform-specific parts */
MiInitMachineDependent(LoaderBlock);
@@ -1889,12 +1947,12 @@
/* FIXME: Call out into Driver Verifier for initialization */
/* Check how many pages the system has */
- if (MmNumberOfPhysicalPages <= (13 * _1MB))
+ if (MmNumberOfPhysicalPages <= ((13 * _1MB) / PAGE_SIZE))
{
/* Set small system */
MmSystemSize = MmSmallSystem;
}
- else if (MmNumberOfPhysicalPages <= (19 * _1MB))
+ else if (MmNumberOfPhysicalPages <= ((19 * _1MB) / PAGE_SIZE))
{
/* Set small system and add 100 pages for the cache */
MmSystemSize = MmSmallSystem;
@@ -1986,6 +2044,14 @@
return FALSE;
}
+ /* Initialize the system cache */
+ //MiInitializeSystemCache(MmSystemCacheWsMinimum, MmAvailablePages);
+
+ /* Update the commit limit */
+ MmTotalCommitLimit = MmAvailablePages;
+ if (MmTotalCommitLimit > 1024) MmTotalCommitLimit -= 1024;
+ MmTotalCommitLimitMaximum = MmTotalCommitLimit;
+
/* Size up paged pool and build the shadow system page directory */
MiBuildPagedPool();
Modified: trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/pagfault.…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] Thu Jul 22 18:26:04 2010
@@ -297,7 +297,9 @@
PMMPDE PointerPde;
MMPTE TempPte;
PETHREAD CurrentThread;
+ PEPROCESS CurrentProcess;
NTSTATUS Status;
+ PMMSUPPORT WorkingSet;
DPRINT("ARM3 FAULT AT: %p\n", Address);
//
@@ -392,7 +394,7 @@
//
// Check for a fault on the page table or hyperspace itself
//
- if ((Address >= (PVOID)PTE_BASE) && (Address <= MmHyperSpaceEnd))
+ if (MI_IS_PAGE_TABLE_OR_HYPER_ADDRESS(Address))
{
//
// This might happen...not sure yet
@@ -415,17 +417,13 @@
return STATUS_ACCESS_VIOLATION;
}
- //
- // Now we must raise to APC_LEVEL and mark the thread as owner
- // We don't actually implement a working set pushlock, so this is only
- // for internal consistency (and blocking APCs)
- //
+ /* In this path, we are using the system working set */
+ CurrentThread = PsGetCurrentThread();
+ WorkingSet = &MmSystemCacheWs;
+
+ /* Acquire it */
KeRaiseIrql(APC_LEVEL, &LockIrql);
- CurrentThread = PsGetCurrentThread();
- KeEnterGuardedRegion();
- ASSERT((CurrentThread->OwnsSystemWorkingSetExclusive == 0) &&
- (CurrentThread->OwnsSystemWorkingSetShared == 0));
- CurrentThread->OwnsSystemWorkingSetExclusive = 1;
+ MiLockWorkingSet(CurrentThread, WorkingSet);
//
// Re-read PTE now that the IRQL has been raised
@@ -444,6 +442,10 @@
DPRINT1("Should NEVER happen on ARM3!!!\n");
return STATUS_ACCESS_VIOLATION;
}
+
+ /* Release the working set */
+ MiUnlockWorkingSet(CurrentThread, WorkingSet);
+ KeLowerIrql(LockIrql);
//
// Otherwise, the PDE was probably invalid, and all is good now
@@ -472,13 +474,10 @@
NULL,
TrapInformation,
NULL);
-
- //
- // Re-enable APCs
- //
+
+ /* Release the working set */
ASSERT(KeAreAllApcsDisabled() == TRUE);
- CurrentThread->OwnsSystemWorkingSetExclusive = 0;
- KeLeaveGuardedRegion();
+ MiUnlockWorkingSet(CurrentThread, WorkingSet);
KeLowerIrql(LockIrql);
//
@@ -488,9 +487,17 @@
return Status;
}
- //
- // DIE DIE DIE
- //
+ /* This is a user fault */
+ CurrentThread = PsGetCurrentThread();
+ CurrentProcess = PsGetCurrentProcess();
+
+ /* Lock the working set */
+ MiLockProcessWorkingSet(CurrentProcess, CurrentThread);
+
+ /* Do something */
+
+ /* Release the working set */
+ MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
DPRINT1("WARNING: USER MODE FAULT IN ARM3???\n");
return STATUS_ACCESS_VIOLATION;
}
Modified: trunk/reactos/ntoskrnl/mm/ARM3/sysldr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/sysldr.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/sysldr.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/sysldr.c [iso-8859-1] Thu Jul 22 18:26:04 2010
@@ -2230,7 +2230,7 @@
IN PMMPTE LastPte)
{
PVOID ImageBase;
- PETHREAD CurrentThread;
+ PETHREAD CurrentThread = PsGetCurrentThread();
PFN_NUMBER PageCount = 0, PageFrameIndex;
PMMPFN Pfn1;
PAGED_CODE();
@@ -2242,12 +2242,8 @@
/* If this is a large page, it's stuck in physical memory */
if (MI_IS_PHYSICAL_ADDRESS(ImageBase)) return;
- /* We should lock the system working set -- we don't have one yet, so just be
consistent */
- CurrentThread = PsGetCurrentThread();
- KeEnterGuardedRegion();
- ASSERT((CurrentThread->OwnsSystemWorkingSetExclusive == 0) &&
- (CurrentThread->OwnsSystemWorkingSetShared == 0));
- CurrentThread->OwnsSystemWorkingSetExclusive = 1;
+ /* Lock the working set */
+ MiLockWorkingSet(CurrentThread, &MmSystemCacheWs);
/* Loop the PTEs */
while (PointerPte <= LastPte)
@@ -2267,10 +2263,8 @@
PointerPte++;
}
- /* Release the working set "lock" */
- ASSERT(KeAreAllApcsDisabled() == TRUE);
- CurrentThread->OwnsSystemWorkingSetExclusive = 0;
- KeLeaveGuardedRegion();
+ /* Release the working set */
+ MiUnlockWorkingSet(CurrentThread, &MmSystemCacheWs);
/* Do we have any driver pages? */
if (PageCount)
Modified: trunk/reactos/ntoskrnl/mm/ARM3/virtual.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/virtual.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/virtual.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/virtual.c [iso-8859-1] Thu Jul 22 18:26:04 2010
@@ -37,23 +37,14 @@
OUT PPFN_NUMBER ValidPages)
{
PFN_NUMBER ActualPages = 0;
- PETHREAD CurrentThread;
+ PETHREAD CurrentThread = PsGetCurrentThread();
PMMPFN Pfn1, Pfn2;
PFN_NUMBER PageFrameIndex, PageTableIndex;
- KIRQL OldIrql, LockIrql;
+ KIRQL OldIrql;
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
- /*
- * Now we must raise to APC_LEVEL and mark the thread as owner
- * We don't actually implement a working set pushlock, so this is only
- * for internal consistency (and blocking APCs)
- */
- KeRaiseIrql(APC_LEVEL, &LockIrql);
- CurrentThread = PsGetCurrentThread();
- KeEnterGuardedRegion();
- ASSERT((CurrentThread->OwnsSystemWorkingSetExclusive == 0) &&
- (CurrentThread->OwnsSystemWorkingSetShared == 0));
- CurrentThread->OwnsSystemWorkingSetExclusive = 1;
+ /* Lock the system working set */
+ MiLockWorkingSet(CurrentThread, &MmSystemCacheWs);
/* Loop all pages */
while (PageCount)
@@ -124,11 +115,8 @@
PageCount--;
}
- /* Re-enable APCs */
- ASSERT(KeAreAllApcsDisabled() == TRUE);
- CurrentThread->OwnsSystemWorkingSetExclusive = 0;
- KeLeaveGuardedRegion();
- KeLowerIrql(LockIrql);
+ /* Release the working set */
+ MiUnlockWorkingSet(CurrentThread, &MmSystemCacheWs);
/* Flush the entire TLB */
KeFlushEntireTb(TRUE, TRUE);