Windows2000/private/ntos/mm/zeropage.c
2020-09-30 17:12:32 +02:00

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);
}