* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: balance.c,v 1.13 2002/09/08 10:23:32 chorns Exp $
+/* $Id: balance.c,v 1.22 2003/10/23 20:28:08 hbirr Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/balance.c
static ULONG MiNrTotalPages;
static LIST_ENTRY AllocationListHead;
static KSPIN_LOCK AllocationListLock;
-static ULONG NrWorkingThreads = 0;
-static HANDLE WorkerThreadId;
static ULONG MiPagesRequired = 0;
-static ULONG MiMinimumPagesPerRun = 1;
+static ULONG MiMinimumPagesPerRun = 10;
/* FUNCTIONS ****************************************************************/
VOID MmPrintMemoryStatistic(VOID)
{
- DbgPrint("MC_CACHE %d, MC_USER %d, MC_PPOOL %d, MC_NPPOOL %d\n",
- MiMemoryConsumers[MC_CACHE].PagesUsed,
- MiMemoryConsumers[MC_USER].PagesUsed,
- MiMemoryConsumers[MC_PPOOL].PagesUsed,
- MiMemoryConsumers[MC_NPPOOL].PagesUsed);
+ DbgPrint("MC_CACHE %d, MC_USER %d, MC_PPOOL %d, MC_NPPOOL %d, MiNrAvailablePages %d\n",
+ MiMemoryConsumers[MC_CACHE].PagesUsed, MiMemoryConsumers[MC_USER].PagesUsed,
+ MiMemoryConsumers[MC_PPOOL].PagesUsed, MiMemoryConsumers[MC_NPPOOL].PagesUsed,
+ MiNrAvailablePages);
}
-VOID
-MmInitializeBalancer(ULONG NrAvailablePages)
+VOID INIT_FUNCTION
+MmInitializeBalancer(ULONG NrAvailablePages, ULONG NrSystemPages)
{
memset(MiMemoryConsumers, 0, sizeof(MiMemoryConsumers));
InitializeListHead(&AllocationListHead);
NrAvailablePages - MiMinimumAvailablePages;
MiMemoryConsumers[MC_PPOOL].PagesTarget = NrAvailablePages / 2;
MiMemoryConsumers[MC_NPPOOL].PagesTarget = 0xFFFFFFFF;
+ MiMemoryConsumers[MC_NPPOOL].PagesUsed = NrSystemPages;
}
-VOID
+VOID INIT_FUNCTION
MmInitializeMemoryConsumer(ULONG Consumer,
NTSTATUS (*Trim)(ULONG Target, ULONG Priority,
PULONG NrFreed))
if (Page.QuadPart == 0LL)
{
DPRINT1("Tried to release page zero.\n");
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
KeAcquireSpinLock(&AllocationListLock, &oldIrql);
if (MmGetReferenceCountPage(Page) == 1)
{
- InterlockedDecrement(&MiMemoryConsumers[Consumer].PagesUsed);
- InterlockedIncrement(&MiNrAvailablePages);
- InterlockedDecrement(&MiPagesRequired);
+ InterlockedDecrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
+ InterlockedIncrement((LONG *)&MiNrAvailablePages);
if (IsListEmpty(&AllocationListHead))
{
KeReleaseSpinLock(&AllocationListLock, oldIrql);
Target = MiMemoryConsumers[Consumer].PagesUsed -
MiMemoryConsumers[Consumer].PagesTarget;
- if (Target < 0)
+ if (Target < 1)
{
Target = 1;
}
}
VOID
-MiRebalanceMemoryConsumers(VOID)
+MmRebalanceMemoryConsumers(VOID)
{
LONG Target;
ULONG i;
NTSTATUS Status;
Target = (MiMinimumAvailablePages - MiNrAvailablePages) + MiPagesRequired;
- Target = min(Target, MiMinimumPagesPerRun);
+ Target = max(Target, (LONG) MiMinimumPagesPerRun);
for (i = 0; i < MC_MAXIMUM && Target > 0; i++)
{
Status = MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages);
if (!NT_SUCCESS(Status))
{
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
Target = Target - NrFreedPages;
}
}
- if (Target > 0)
- {
- KeBugCheck(0);
- }
}
NTSTATUS
/*
* Make sure we don't exceed our individual target.
*/
- OldUsed = InterlockedIncrement(&MiMemoryConsumers[Consumer].PagesUsed);
+ OldUsed = InterlockedIncrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
if (OldUsed >= (MiMemoryConsumers[Consumer].PagesTarget - 1) &&
- WorkerThreadId != PsGetCurrentThreadId())
+ !MiIsPagerThread())
{
if (!CanWait)
{
- InterlockedDecrement(&MiMemoryConsumers[Consumer].PagesUsed);
+ InterlockedDecrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
return(STATUS_NO_MEMORY);
}
MiTrimMemoryConsumer(Consumer);
/*
* Make sure we don't exceed global targets.
*/
- OldAvailable = InterlockedDecrement(&MiNrAvailablePages);
+ OldAvailable = InterlockedDecrement((LONG *)&MiNrAvailablePages);
if (OldAvailable < MiMinimumAvailablePages)
{
MM_ALLOCATION_REQUEST Request;
if (!CanWait)
{
- InterlockedIncrement(&MiNrAvailablePages);
- InterlockedDecrement(&MiMemoryConsumers[Consumer].PagesUsed);
+ InterlockedIncrement((LONG *)&MiNrAvailablePages);
+ InterlockedDecrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
return(STATUS_NO_MEMORY);
}
/* Insert an allocation request. */
Request.Page.QuadPart = 0LL;
KeInitializeEvent(&Request.Event, NotificationEvent, FALSE);
- InterlockedIncrement(&MiPagesRequired);
+ InterlockedIncrement((LONG *)&MiPagesRequired);
KeAcquireSpinLock(&AllocationListLock, &oldIrql);
- if (NrWorkingThreads == 0)
+ /* Always let the pager thread itself allocate memory. */
+ if (MiIsPagerThread())
{
- InsertTailList(&AllocationListHead, &Request.ListEntry);
- NrWorkingThreads++;
+ Page = MmAllocPage(Consumer, 0);
KeReleaseSpinLock(&AllocationListLock, oldIrql);
- WorkerThreadId = PsGetCurrentThreadId();
- MiRebalanceMemoryConsumers();
- KeAcquireSpinLock(&AllocationListLock, &oldIrql);
- NrWorkingThreads--;
- WorkerThreadId = 0;
- KeReleaseSpinLock(&AllocationListLock, oldIrql);
- }
- else
- {
- if (WorkerThreadId == PsGetCurrentThreadId())
+ if (Page.QuadPart == 0LL)
{
- Page = MmAllocPage(Consumer, 0);
- KeReleaseSpinLock(&AllocationListLock, oldIrql);
- if (Page.QuadPart == 0LL)
- {
- KeBugCheck(0);
- }
- *AllocatedPage = Page;
- return(STATUS_SUCCESS);
+ KEBUGCHECK(0);
}
- InsertTailList(&AllocationListHead, &Request.ListEntry);
- KeReleaseSpinLock(&AllocationListLock, oldIrql);
+ *AllocatedPage = Page;
+ 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,
0,
KernelMode,
FALSE,
NULL);
-
+
Page = Request.Page;
if (Page.QuadPart == 0LL)
{
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
MmTransferOwnershipPage(Page, Consumer);
*AllocatedPage = Page;
+ InterlockedDecrement((LONG *)&MiPagesRequired);
+ MiStopPagerThread();
return(STATUS_SUCCESS);
}
-
+
/*
* Actually allocate the page.
*/
Page = MmAllocPage(Consumer, 0);
if (Page.QuadPart == 0LL)
{
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
*AllocatedPage = Page;
return(STATUS_SUCCESS);
}
+
+/* EOF */