192 lines
4.3 KiB
C
192 lines
4.3 KiB
C
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
zeropage.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the zero page thread for memory management.
|
|
|
|
Author:
|
|
|
|
Lou Perazzoli (loup) 6-Apr-1991
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "mi.h"
|
|
|
|
#define MM_ZERO_PAGE_OBJECT 0
|
|
#define PO_SYS_IDLE_OBJECT 1
|
|
#define NUMBER_WAIT_OBJECTS 2
|
|
|
|
|
|
VOID
|
|
MmZeroPageThread (
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implements the NT zeroing page thread. This thread runs
|
|
at priority zero and removes a page from the free list,
|
|
zeroes it, and places it on the zeroed page list.
|
|
|
|
Arguments:
|
|
|
|
StartContext - not used.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
Environment:
|
|
|
|
Kernel mode.
|
|
|
|
--*/
|
|
|
|
{
|
|
PVOID EndVa;
|
|
KIRQL OldIrql;
|
|
PFN_NUMBER PageFrame;
|
|
PMMPFN Pfn1;
|
|
PVOID StartVa;
|
|
PKTHREAD Thread;
|
|
PVOID ZeroBase;
|
|
PFN_NUMBER NewPage;
|
|
PVOID WaitObjects[NUMBER_WAIT_OBJECTS];
|
|
NTSTATUS Status;
|
|
|
|
|
|
// Before this becomes the zero page thread, free the kernel
|
|
// initialization code.
|
|
|
|
|
|
#if !defined(_IA64_)
|
|
MiFindInitializationCode (&StartVa, &EndVa);
|
|
if (StartVa != NULL) {
|
|
MiFreeInitializationCode (StartVa, EndVa);
|
|
}
|
|
#endif
|
|
|
|
|
|
// The following code sets the current thread's base priority to zero
|
|
// and then sets its current priority to zero. This ensures that the
|
|
// thread always runs at a priority of zero.
|
|
|
|
|
|
Thread = KeGetCurrentThread();
|
|
Thread->BasePriority = 0;
|
|
KeSetPriorityThread (Thread, 0);
|
|
|
|
|
|
// Initialize wait object array for multiple wait
|
|
|
|
|
|
WaitObjects[MM_ZERO_PAGE_OBJECT] = &MmZeroingPageEvent;
|
|
WaitObjects[PO_SYS_IDLE_OBJECT] = &PoSystemIdleTimer;
|
|
|
|
|
|
// Loop forever zeroing pages.
|
|
|
|
|
|
do {
|
|
|
|
|
|
// Wait until there are at least MmZeroPageMinimum pages
|
|
// on the free list.
|
|
|
|
|
|
Status = KeWaitForMultipleObjects (NUMBER_WAIT_OBJECTS,
|
|
WaitObjects,
|
|
WaitAny,
|
|
WrFreePage,
|
|
KernelMode,
|
|
FALSE,
|
|
(PLARGE_INTEGER) NULL,
|
|
(PKWAIT_BLOCK) NULL
|
|
);
|
|
|
|
if (Status == PO_SYS_IDLE_OBJECT) {
|
|
PoSystemIdleWorker (TRUE);
|
|
continue;
|
|
}
|
|
|
|
LOCK_PFN_WITH_TRY (OldIrql);
|
|
do {
|
|
if ((volatile)MmFreePageListHead.Total == 0) {
|
|
|
|
|
|
// No pages on the free list at this time, wait for
|
|
// some more.
|
|
|
|
|
|
MmZeroingPageThreadActive = FALSE;
|
|
UNLOCK_PFN (OldIrql);
|
|
break;
|
|
|
|
} else {
|
|
|
|
PageFrame = MmFreePageListHead.Flink;
|
|
Pfn1 = MI_PFN_ELEMENT(PageFrame);
|
|
|
|
ASSERT (PageFrame != MM_EMPTY_LIST);
|
|
Pfn1 = MI_PFN_ELEMENT(PageFrame);
|
|
|
|
NewPage = MiRemoveAnyPage (MI_GET_SECONDARY_COLOR (PageFrame, Pfn1));
|
|
if (NewPage != PageFrame) {
|
|
|
|
|
|
// Someone has removed a page from the colored lists chain
|
|
// without updating the freelist chain.
|
|
|
|
|
|
KeBugCheckEx (PFN_LIST_CORRUPT,
|
|
0x8F,
|
|
NewPage,
|
|
PageFrame,
|
|
0);
|
|
}
|
|
|
|
|
|
// Zero the page using the last color used to map the page.
|
|
|
|
|
|
#if defined(_AXP64_) || defined(_X86_) || defined(_IA64_)
|
|
|
|
ZeroBase = MiMapPageToZeroInHyperSpace (PageFrame);
|
|
UNLOCK_PFN (OldIrql);
|
|
|
|
#if defined(_X86_)
|
|
|
|
KeZeroPageFromIdleThread(ZeroBase);
|
|
|
|
#else //X86
|
|
|
|
RtlZeroMemory (ZeroBase, PAGE_SIZE);
|
|
|
|
#endif //X86
|
|
|
|
#else //AXP64||X86||IA64
|
|
|
|
ZeroBase = (PVOID)(Pfn1->u3.e1.PageColor << PAGE_SHIFT);
|
|
UNLOCK_PFN (OldIrql);
|
|
HalZeroPage(ZeroBase, ZeroBase, PageFrame);
|
|
|
|
#endif //AXP64||X86||IA64
|
|
|
|
LOCK_PFN_WITH_TRY (OldIrql);
|
|
MiInsertPageInList (MmPageLocationList[ZeroedPageList],
|
|
PageFrame);
|
|
}
|
|
} while(TRUE);
|
|
} while (TRUE);
|
|
}
|