mirror of
https://github.com/reactos/reactos.git
synced 2025-06-01 07:28:19 +00:00

Hopefully fixed vfat fsd reported by Philip Susi FAT lookups go through cache svn path=/trunk/; revision=1499
134 lines
3.1 KiB
C
134 lines
3.1 KiB
C
/* $Id: pager.c,v 1.6 2001/01/08 02:14:06 dwelch Exp $
|
|
*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS kernel
|
|
* FILE: ntoskrnl/mm/pager.c
|
|
* PURPOSE: Moves infrequently used data out of memory
|
|
* PROGRAMMER: David Welch (welch@cwcom.net)
|
|
* UPDATE HISTORY:
|
|
* 27/05/98: Created
|
|
*/
|
|
|
|
/* INCLUDES ****************************************************************/
|
|
|
|
#include <ddk/ntddk.h>
|
|
#include <internal/ps.h>
|
|
#include <internal/ke.h>
|
|
#include <internal/mm.h>
|
|
#include <internal/mmhal.h>
|
|
|
|
#define NDEBUG
|
|
#include <internal/debug.h>
|
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
static HANDLE PagerThreadHandle;
|
|
static CLIENT_ID PagerThreadId;
|
|
static KEVENT PagerThreadEvent;
|
|
static PEPROCESS LastProcess;
|
|
static volatile BOOLEAN PagerThreadShouldTerminate;
|
|
static volatile ULONG PageCount;
|
|
static volatile ULONG WaiterCount;
|
|
static KEVENT FreedMemEvent;
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
VOID MmWaitForFreePages(VOID)
|
|
{
|
|
InterlockedIncrement((PULONG)&PageCount);
|
|
KeClearEvent(&FreedMemEvent);
|
|
KeSetEvent(&PagerThreadEvent,
|
|
IO_NO_INCREMENT,
|
|
FALSE);
|
|
InterlockedIncrement((PULONG)&WaiterCount);
|
|
KeWaitForSingleObject(&FreedMemEvent,
|
|
0,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL);
|
|
InterlockedDecrement((PULONG)&WaiterCount);
|
|
}
|
|
|
|
static VOID MmTryPageOutFromProcess(PEPROCESS Process)
|
|
{
|
|
ULONG P;
|
|
|
|
MmLockAddressSpace(&Process->AddressSpace);
|
|
P = MmTrimWorkingSet(Process, PageCount);
|
|
if (P > 0)
|
|
{
|
|
InterlockedExchangeAdd((PULONG)&PageCount, -P);
|
|
KeSetEvent(&FreedMemEvent, IO_NO_INCREMENT, FALSE);
|
|
}
|
|
MmUnlockAddressSpace(&Process->AddressSpace);
|
|
}
|
|
|
|
static NTSTATUS 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);
|
|
}
|
|
|
|
while (WaiterCount > 0)
|
|
{
|
|
while (PageCount > 0)
|
|
{
|
|
KeAttachProcess(LastProcess);
|
|
MmTryPageOutFromProcess(LastProcess);
|
|
KeDetachProcess();
|
|
if (PageCount != 0)
|
|
{
|
|
LastProcess = PsGetNextProcess(LastProcess);
|
|
}
|
|
}
|
|
DbgPrint("Out of memory\n");
|
|
KeSetEvent(&FreedMemEvent, IO_NO_INCREMENT, FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
NTSTATUS MmInitPagerThread(VOID)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
PageCount = 0;
|
|
WaiterCount = 0;
|
|
LastProcess = PsInitialSystemProcess;
|
|
PagerThreadShouldTerminate = FALSE;
|
|
KeInitializeEvent(&PagerThreadEvent,
|
|
SynchronizationEvent,
|
|
FALSE);
|
|
KeInitializeEvent(&FreedMemEvent,
|
|
NotificationEvent,
|
|
FALSE);
|
|
|
|
Status = PsCreateSystemThread(&PagerThreadHandle,
|
|
THREAD_ALL_ACCESS,
|
|
NULL,
|
|
NULL,
|
|
&PagerThreadId,
|
|
MmPagerThreadMain,
|
|
NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return(Status);
|
|
}
|
|
|
|
return(STATUS_SUCCESS);
|
|
}
|