mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
- Implemented Harmutt Birr's suggestion of a seperate thread
to do balancing. - Move pages that can't be paged out because the pagefile is full to the end of the LRU list so we don't waste time checking them again. svn path=/trunk/; revision=5092
This commit is contained in:
parent
e41f7f3329
commit
4ae404aaa8
6 changed files with 97 additions and 51 deletions
|
@ -632,5 +632,13 @@ BOOLEAN
|
||||||
MmIsAvailableSwapPage(VOID);
|
MmIsAvailableSwapPage(VOID);
|
||||||
VOID
|
VOID
|
||||||
MmShowOutOfSpaceMessagePagingFile(VOID);
|
MmShowOutOfSpaceMessagePagingFile(VOID);
|
||||||
|
VOID
|
||||||
|
MmRebalanceMemoryConsumers(VOID);
|
||||||
|
BOOLEAN
|
||||||
|
MiIsPagerThread(VOID);
|
||||||
|
VOID
|
||||||
|
MiStartPagerThread(VOID);
|
||||||
|
VOID
|
||||||
|
MmSetLRULastPage(PHYSICAL_ADDRESS PhysicalAddress);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: anonmem.c,v 1.17 2003/07/11 01:23:15 royce Exp $
|
/* $Id: anonmem.c,v 1.18 2003/07/12 01:52:10 dwelch Exp $
|
||||||
*
|
*
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/mm/anonmem.c
|
* FILE: ntoskrnl/mm/anonmem.c
|
||||||
|
@ -193,7 +193,7 @@ MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,
|
||||||
PageOp->Status = STATUS_UNSUCCESSFUL;
|
PageOp->Status = STATUS_UNSUCCESSFUL;
|
||||||
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
||||||
MmReleasePageOp(PageOp);
|
MmReleasePageOp(PageOp);
|
||||||
return(STATUS_UNSUCCESSFUL);
|
return(STATUS_PAGEFILE_QUOTA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: balance.c,v 1.17 2003/07/10 21:05:03 royce Exp $
|
/* $Id: balance.c,v 1.18 2003/07/12 01:52:10 dwelch Exp $
|
||||||
*
|
*
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/mm/balance.c
|
* FILE: ntoskrnl/mm/balance.c
|
||||||
|
@ -59,8 +59,6 @@ static ULONG MiNrAvailablePages;
|
||||||
static ULONG MiNrTotalPages;
|
static ULONG MiNrTotalPages;
|
||||||
static LIST_ENTRY AllocationListHead;
|
static LIST_ENTRY AllocationListHead;
|
||||||
static KSPIN_LOCK AllocationListLock;
|
static KSPIN_LOCK AllocationListLock;
|
||||||
static ULONG NrWorkingThreads = 0;
|
|
||||||
static HANDLE WorkerThreadId;
|
|
||||||
static ULONG MiPagesRequired = 0;
|
static ULONG MiPagesRequired = 0;
|
||||||
static ULONG MiMinimumPagesPerRun = 10;
|
static ULONG MiMinimumPagesPerRun = 10;
|
||||||
|
|
||||||
|
@ -161,7 +159,7 @@ MiTrimMemoryConsumer(ULONG Consumer)
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
MiRebalanceMemoryConsumers(VOID)
|
MmRebalanceMemoryConsumers(VOID)
|
||||||
{
|
{
|
||||||
LONG Target;
|
LONG Target;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
|
@ -203,7 +201,7 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
|
||||||
*/
|
*/
|
||||||
OldUsed = InterlockedIncrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
|
OldUsed = InterlockedIncrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
|
||||||
if (OldUsed >= (MiMemoryConsumers[Consumer].PagesTarget - 1) &&
|
if (OldUsed >= (MiMemoryConsumers[Consumer].PagesTarget - 1) &&
|
||||||
WorkerThreadId != PsGetCurrentThreadId())
|
!MiIsPagerThread())
|
||||||
{
|
{
|
||||||
if (!CanWait)
|
if (!CanWait)
|
||||||
{
|
{
|
||||||
|
@ -234,41 +232,30 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
|
||||||
InterlockedIncrement((LONG *)&MiPagesRequired);
|
InterlockedIncrement((LONG *)&MiPagesRequired);
|
||||||
|
|
||||||
KeAcquireSpinLock(&AllocationListLock, &oldIrql);
|
KeAcquireSpinLock(&AllocationListLock, &oldIrql);
|
||||||
if (NrWorkingThreads == 0)
|
/* Always let the pager thread itself allocate memory. */
|
||||||
|
if (MiIsPagerThread())
|
||||||
{
|
{
|
||||||
InsertTailList(&AllocationListHead, &Request.ListEntry);
|
Page = MmAllocPage(Consumer, 0);
|
||||||
NrWorkingThreads++;
|
|
||||||
KeReleaseSpinLock(&AllocationListLock, oldIrql);
|
KeReleaseSpinLock(&AllocationListLock, oldIrql);
|
||||||
WorkerThreadId = PsGetCurrentThreadId();
|
if (Page.QuadPart == 0LL)
|
||||||
MiRebalanceMemoryConsumers();
|
|
||||||
KeAcquireSpinLock(&AllocationListLock, &oldIrql);
|
|
||||||
NrWorkingThreads--;
|
|
||||||
WorkerThreadId = 0;
|
|
||||||
KeReleaseSpinLock(&AllocationListLock, oldIrql);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (WorkerThreadId == PsGetCurrentThreadId())
|
|
||||||
{
|
{
|
||||||
Page = MmAllocPage(Consumer, 0);
|
KeBugCheck(0);
|
||||||
KeReleaseSpinLock(&AllocationListLock, oldIrql);
|
|
||||||
if (Page.QuadPart == 0LL)
|
|
||||||
{
|
|
||||||
KeBugCheck(0);
|
|
||||||
}
|
|
||||||
*AllocatedPage = Page;
|
|
||||||
InterlockedDecrement((LONG *)&MiPagesRequired);
|
|
||||||
return(STATUS_SUCCESS);
|
|
||||||
}
|
}
|
||||||
InsertTailList(&AllocationListHead, &Request.ListEntry);
|
*AllocatedPage = Page;
|
||||||
KeReleaseSpinLock(&AllocationListLock, oldIrql);
|
InterlockedDecrement((LONG *)&MiPagesRequired);
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
/* Otherwise start the pager thread if it isn't already working. */
|
||||||
|
MiStartPagerThread();
|
||||||
|
InsertTailList(&AllocationListHead, &Request.ListEntry);
|
||||||
|
KeReleaseSpinLock(&AllocationListLock, oldIrql);
|
||||||
|
|
||||||
KeWaitForSingleObject(&Request.Event,
|
KeWaitForSingleObject(&Request.Event,
|
||||||
0,
|
0,
|
||||||
KernelMode,
|
KernelMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
Page = Request.Page;
|
Page = Request.Page;
|
||||||
if (Page.QuadPart == 0LL)
|
if (Page.QuadPart == 0LL)
|
||||||
{
|
{
|
||||||
|
@ -279,7 +266,7 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
|
||||||
InterlockedDecrement((LONG *)&MiPagesRequired);
|
InterlockedDecrement((LONG *)&MiPagesRequired);
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Actually allocate the page.
|
* Actually allocate the page.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -70,6 +70,11 @@ MmTransferOwnershipPage(PHYSICAL_ADDRESS PhysicalAddress, ULONG NewConsumer)
|
||||||
KIRQL oldIrql;
|
KIRQL oldIrql;
|
||||||
|
|
||||||
KeAcquireSpinLock(&PageListLock, &oldIrql);
|
KeAcquireSpinLock(&PageListLock, &oldIrql);
|
||||||
|
if (MmPageArray[Start].MapCount != 0)
|
||||||
|
{
|
||||||
|
DbgPrint("Transfering mapped page.\n");
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
RemoveEntryList(&MmPageArray[Start].ListEntry);
|
RemoveEntryList(&MmPageArray[Start].ListEntry);
|
||||||
InsertTailList(&UsedPageListHeads[NewConsumer],
|
InsertTailList(&UsedPageListHeads[NewConsumer],
|
||||||
&MmPageArray[Start].ListEntry);
|
&MmPageArray[Start].ListEntry);
|
||||||
|
@ -100,6 +105,23 @@ MmGetLRUFirstUserPage(VOID)
|
||||||
return(Next);
|
return(Next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MmSetLRULastPage(PHYSICAL_ADDRESS PhysicalAddress)
|
||||||
|
{
|
||||||
|
ULONG Start = PhysicalAddress.u.LowPart / PAGE_SIZE;
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&PageListLock, &oldIrql);
|
||||||
|
if (MmPageArray[Start].Flags.Type == MM_PHYSICAL_PAGE_USED &&
|
||||||
|
MmPageArray[Start].Flags.Consumer == MC_USER)
|
||||||
|
{
|
||||||
|
RemoveEntryList(&MmPageArray[Start].ListEntry);
|
||||||
|
InsertTailList(&UsedPageListHeads[MC_USER],
|
||||||
|
&MmPageArray[Start].ListEntry);
|
||||||
|
}
|
||||||
|
KeReleaseSpinLock(&PageListLock, oldIrql);
|
||||||
|
}
|
||||||
|
|
||||||
PHYSICAL_ADDRESS
|
PHYSICAL_ADDRESS
|
||||||
MmGetLRUNextUserPage(PHYSICAL_ADDRESS PreviousPhysicalAddress)
|
MmGetLRUNextUserPage(PHYSICAL_ADDRESS PreviousPhysicalAddress)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: pager.c,v 1.11 2002/09/08 10:23:36 chorns Exp $
|
/* $Id: pager.c,v 1.12 2003/07/12 01:52:10 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -25,31 +25,55 @@ static HANDLE PagerThreadHandle;
|
||||||
static CLIENT_ID PagerThreadId;
|
static CLIENT_ID PagerThreadId;
|
||||||
static KEVENT PagerThreadEvent;
|
static KEVENT PagerThreadEvent;
|
||||||
static BOOLEAN PagerThreadShouldTerminate;
|
static BOOLEAN PagerThreadShouldTerminate;
|
||||||
|
static ULONG PagerThreadWorking;
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
MiIsPagerThread(VOID)
|
||||||
|
{
|
||||||
|
return(PsGetCurrentThreadId() == PagerThreadId.UniqueThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MiStartPagerThread(VOID)
|
||||||
|
{
|
||||||
|
ULONG WasWorking;
|
||||||
|
|
||||||
|
WasWorking = InterlockedExchange(&PagerThreadWorking, 1);
|
||||||
|
if (WasWorking == 0)
|
||||||
|
{
|
||||||
|
KeSetEvent(&PagerThreadEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS STDCALL
|
static NTSTATUS STDCALL
|
||||||
MmPagerThreadMain(PVOID Ignored)
|
MmPagerThreadMain(PVOID Ignored)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
Status = KeWaitForSingleObject(&PagerThreadEvent,
|
/* Wake for a low memory situation or a terminate request. */
|
||||||
0,
|
Status = KeWaitForSingleObject(&PagerThreadEvent,
|
||||||
KernelMode,
|
0,
|
||||||
FALSE,
|
KernelMode,
|
||||||
NULL);
|
FALSE,
|
||||||
if (!NT_SUCCESS(Status))
|
NULL);
|
||||||
{
|
if (!NT_SUCCESS(Status))
|
||||||
DbgPrint("PagerThread: Wait failed\n");
|
{
|
||||||
KeBugCheck(0);
|
DbgPrint("PagerThread: Wait failed\n");
|
||||||
}
|
KeBugCheck(0);
|
||||||
if (PagerThreadShouldTerminate)
|
}
|
||||||
{
|
if (PagerThreadShouldTerminate)
|
||||||
DbgPrint("PagerThread: Terminating\n");
|
{
|
||||||
return(STATUS_SUCCESS);
|
DbgPrint("PagerThread: Terminating\n");
|
||||||
}
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
/* Try and make some memory available to the system. */
|
||||||
|
MmRebalanceMemoryConsumers();
|
||||||
|
/* Let the rest of the system know we finished this run. */
|
||||||
|
(VOID)InterlockedExchange(&PagerThreadWorking, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +82,7 @@ NTSTATUS MmInitPagerThread(VOID)
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
PagerThreadShouldTerminate = FALSE;
|
PagerThreadShouldTerminate = FALSE;
|
||||||
|
PagerThreadWorking = 0;
|
||||||
KeInitializeEvent(&PagerThreadEvent,
|
KeInitializeEvent(&PagerThreadEvent,
|
||||||
SynchronizationEvent,
|
SynchronizationEvent,
|
||||||
FALSE);
|
FALSE);
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: wset.c,v 1.16 2002/09/08 10:23:37 chorns Exp $
|
/* $Id: wset.c,v 1.17 2003/07/12 01:52:10 dwelch Exp $
|
||||||
*
|
*
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/mm/wset.c
|
* FILE: ntoskrnl/mm/wset.c
|
||||||
|
@ -59,6 +59,10 @@ MmTrimUserMemory(ULONG Target, ULONG Priority, PULONG NrFreedPages)
|
||||||
Target--;
|
Target--;
|
||||||
(*NrFreedPages)++;
|
(*NrFreedPages)++;
|
||||||
}
|
}
|
||||||
|
else if (Status == STATUS_PAGEFILE_QUOTA)
|
||||||
|
{
|
||||||
|
MmSetLRULastPage(CurrentPhysicalAddress);
|
||||||
|
}
|
||||||
|
|
||||||
CurrentPhysicalAddress = NextPhysicalAddress;
|
CurrentPhysicalAddress = NextPhysicalAddress;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue