static CLIENT_ID PagerThreadId;
static KEVENT PagerThreadEvent;
static BOOLEAN PagerThreadShouldTerminate;
+static ULONG PagerThreadWorkCount;
/* FUNCTIONS *****************************************************************/
+BOOLEAN
+MiIsPagerThread(VOID)
+{
+ return(PsGetCurrentThreadId() == PagerThreadId.UniqueThread);
+}
+
+VOID
+MiStartPagerThread(VOID)
+{
+ ULONG WasWorking;
+
+ WasWorking = InterlockedIncrement(&PagerThreadWorkCount);
+ if (WasWorking == 1)
+ {
+ KeSetEvent(&PagerThreadEvent, IO_NO_INCREMENT, FALSE);
+ }
+}
+
+VOID
+MiStopPagerThread(VOID)
+{
+ (VOID)InterlockedDecrement(&PagerThreadWorkCount);
+}
+
static NTSTATUS STDCALL
MmPagerThreadMain(PVOID Ignored)
{
NTSTATUS Status;
-
+
for(;;)
{
- Status = KeWaitForSingleObject(&PagerThreadEvent,
- 0,
- KernelMode,
- FALSE,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DbgPrint("PagerThread: Wait failed\n");
- KeBugCheck(0);
- }
- if (PagerThreadShouldTerminate)
- {
- DbgPrint("PagerThread: Terminating\n");
- return(STATUS_SUCCESS);
- }
+ /* Wake for a low memory situation or a terminate request. */
+ Status = KeWaitForSingleObject(&PagerThreadEvent,
+ 0,
+ KernelMode,
+ FALSE,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint("PagerThread: Wait failed\n");
+ KEBUGCHECK(0);
+ }
+ if (PagerThreadShouldTerminate)
+ {
+ DbgPrint("PagerThread: Terminating\n");
+ return(STATUS_SUCCESS);
+ }
+ do
+ {
+ /* Try and make some memory available to the system. */
+ MmRebalanceMemoryConsumers();
+ } while(PagerThreadWorkCount > 0);
}
}
NTSTATUS Status;
PagerThreadShouldTerminate = FALSE;
+ PagerThreadWorkCount = 0;
KeInitializeEvent(&PagerThreadEvent,
SynchronizationEvent,
FALSE);
NULL,
NULL,
&PagerThreadId,
- MmPagerThreadMain,
+ (PKSTART_ROUTINE) MmPagerThreadMain,
NULL);
if (!NT_SUCCESS(Status))
{