2008-03-09 14:11:42 +00:00
|
|
|
/*
|
2023-09-06 12:53:53 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
|
|
|
* PURPOSE: kernel memory management functions
|
|
|
|
* PROGRAMMERS: David Welch <welch@cwcom.net>
|
|
|
|
* Cameron Gutman <cameron.gutman@reactos.org>
|
2001-12-28 00:04:45 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
2004-08-15 16:39:12 +00:00
|
|
|
#include <ntoskrnl.h>
|
2001-12-28 00:04:45 +00:00
|
|
|
#define NDEBUG
|
2008-08-30 16:31:06 +00:00
|
|
|
#include <debug.h>
|
2001-12-28 00:04:45 +00:00
|
|
|
|
2012-02-20 20:51:18 +00:00
|
|
|
#include "ARM3/miarm.h"
|
|
|
|
|
2021-05-11 15:13:14 +00:00
|
|
|
|
2001-12-28 00:04:45 +00:00
|
|
|
/* TYPES ********************************************************************/
|
2001-12-31 01:53:46 +00:00
|
|
|
typedef struct _MM_ALLOCATION_REQUEST
|
|
|
|
{
|
2014-10-05 06:33:34 +00:00
|
|
|
PFN_NUMBER Page;
|
|
|
|
LIST_ENTRY ListEntry;
|
|
|
|
KEVENT Event;
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
MM_ALLOCATION_REQUEST, *PMM_ALLOCATION_REQUEST;
|
2001-12-28 00:04:45 +00:00
|
|
|
/* GLOBALS ******************************************************************/
|
|
|
|
|
2004-04-22 01:57:49 +00:00
|
|
|
MM_MEMORY_CONSUMER MiMemoryConsumers[MC_MAXIMUM];
|
2001-12-28 00:04:45 +00:00
|
|
|
static ULONG MiMinimumAvailablePages;
|
2011-11-29 23:59:25 +00:00
|
|
|
static ULONG MiMinimumPagesPerRun;
|
2003-11-16 15:20:39 +00:00
|
|
|
static CLIENT_ID MiBalancerThreadId;
|
|
|
|
static HANDLE MiBalancerThreadHandle = NULL;
|
|
|
|
static KEVENT MiBalancerEvent;
|
2023-04-06 05:42:32 +00:00
|
|
|
static KEVENT MiBalancerDoneEvent;
|
2003-11-16 15:20:39 +00:00
|
|
|
static KTIMER MiBalancerTimer;
|
|
|
|
|
2021-01-29 17:47:26 +00:00
|
|
|
static LONG PageOutThreadActive;
|
|
|
|
|
2001-12-28 00:04:45 +00:00
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2020-05-23 13:56:10 +00:00
|
|
|
VOID
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2003-10-23 20:28:08 +00:00
|
|
|
MmInitializeBalancer(ULONG NrAvailablePages, ULONG NrSystemPages)
|
2001-12-28 00:04:45 +00:00
|
|
|
{
|
2014-10-05 06:33:34 +00:00
|
|
|
memset(MiMemoryConsumers, 0, sizeof(MiMemoryConsumers));
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2014-10-05 06:33:34 +00:00
|
|
|
/* Set up targets. */
|
2016-10-18 20:19:00 +00:00
|
|
|
MiMinimumAvailablePages = 256;
|
2014-10-05 06:33:34 +00:00
|
|
|
MiMinimumPagesPerRun = 256;
|
2020-12-07 10:42:47 +00:00
|
|
|
MiMemoryConsumers[MC_USER].PagesTarget = NrAvailablePages / 2;
|
2001-12-28 00:04:45 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2020-05-23 13:56:10 +00:00
|
|
|
VOID
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2014-10-05 06:33:34 +00:00
|
|
|
MmInitializeMemoryConsumer(
|
|
|
|
ULONG Consumer,
|
|
|
|
NTSTATUS (*Trim)(ULONG Target, ULONG Priority, PULONG NrFreed))
|
2001-12-28 00:04:45 +00:00
|
|
|
{
|
2014-10-05 06:33:34 +00:00
|
|
|
MiMemoryConsumers[Consumer].Trim = Trim;
|
2001-12-28 00:04:45 +00:00
|
|
|
}
|
|
|
|
|
2010-09-27 21:58:54 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiZeroPhysicalPage(
|
|
|
|
IN PFN_NUMBER PageFrameIndex
|
|
|
|
);
|
|
|
|
|
2001-12-28 00:04:45 +00:00
|
|
|
NTSTATUS
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2010-07-15 22:50:12 +00:00
|
|
|
MmReleasePageMemoryConsumer(ULONG Consumer, PFN_NUMBER Page)
|
2001-12-28 00:04:45 +00:00
|
|
|
{
|
2021-06-07 08:40:20 +00:00
|
|
|
KIRQL OldIrql;
|
|
|
|
|
2014-10-05 06:33:34 +00:00
|
|
|
if (Page == 0)
|
|
|
|
{
|
|
|
|
DPRINT1("Tried to release page zero.\n");
|
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
|
|
|
}
|
|
|
|
|
2021-01-27 09:29:07 +00:00
|
|
|
(void)InterlockedDecrementUL(&MiMemoryConsumers[Consumer].PagesUsed);
|
2022-09-12 12:22:52 +00:00
|
|
|
UpdateTotalCommittedPages(-1);
|
2014-10-05 06:33:34 +00:00
|
|
|
|
2021-06-07 08:40:20 +00:00
|
|
|
OldIrql = MiAcquirePfnLock();
|
|
|
|
|
2016-10-18 20:19:00 +00:00
|
|
|
MmDereferencePage(Page);
|
|
|
|
|
2021-06-07 08:40:20 +00:00
|
|
|
MiReleasePfnLock(OldIrql);
|
|
|
|
|
2014-10-05 06:33:34 +00:00
|
|
|
return(STATUS_SUCCESS);
|
2001-12-28 00:04:45 +00:00
|
|
|
}
|
|
|
|
|
2011-12-28 01:18:35 +00:00
|
|
|
ULONG
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2011-12-28 01:18:35 +00:00
|
|
|
MiTrimMemoryConsumer(ULONG Consumer, ULONG InitialTarget)
|
2001-12-28 00:04:45 +00:00
|
|
|
{
|
2012-02-22 21:18:56 +00:00
|
|
|
ULONG Target = InitialTarget;
|
2011-11-29 23:59:25 +00:00
|
|
|
ULONG NrFreedPages = 0;
|
|
|
|
NTSTATUS Status;
|
2001-12-28 00:04:45 +00:00
|
|
|
|
2011-11-29 23:59:25 +00:00
|
|
|
/* Make sure we can trim this consumer */
|
|
|
|
if (!MiMemoryConsumers[Consumer].Trim)
|
2011-12-28 01:18:35 +00:00
|
|
|
{
|
|
|
|
/* Return the unmodified initial target */
|
|
|
|
return InitialTarget;
|
|
|
|
}
|
2001-12-28 00:04:45 +00:00
|
|
|
|
2011-11-29 23:59:25 +00:00
|
|
|
if (MmAvailablePages < MiMinimumAvailablePages)
|
|
|
|
{
|
|
|
|
/* Global page limit exceeded */
|
2012-03-28 19:41:40 +00:00
|
|
|
Target = (ULONG)max(Target, MiMinimumAvailablePages - MmAvailablePages);
|
2011-11-29 23:59:25 +00:00
|
|
|
}
|
2021-01-29 17:47:26 +00:00
|
|
|
else if (MiMemoryConsumers[Consumer].PagesUsed > MiMemoryConsumers[Consumer].PagesTarget)
|
|
|
|
{
|
|
|
|
/* Consumer page limit exceeded */
|
|
|
|
Target = max(Target, MiMemoryConsumers[Consumer].PagesUsed - MiMemoryConsumers[Consumer].PagesTarget);
|
|
|
|
}
|
2020-12-07 10:42:47 +00:00
|
|
|
|
2011-11-29 23:59:25 +00:00
|
|
|
if (Target)
|
|
|
|
{
|
|
|
|
/* Now swap the pages out */
|
2021-01-28 14:42:12 +00:00
|
|
|
Status = MiMemoryConsumers[Consumer].Trim(Target, MmAvailablePages < MiMinimumAvailablePages, &NrFreedPages);
|
2011-11-29 23:59:25 +00:00
|
|
|
|
2013-08-31 16:02:13 +00:00
|
|
|
DPRINT("Trimming consumer %lu: Freed %lu pages with a target of %lu pages\n", Consumer, NrFreedPages, Target);
|
2011-12-10 04:11:19 +00:00
|
|
|
|
2011-11-29 23:59:25 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
|
|
|
}
|
|
|
|
}
|
2020-12-07 10:42:47 +00:00
|
|
|
|
|
|
|
/* Return the page count needed to be freed to meet the initial target */
|
|
|
|
return (InitialTarget > NrFreedPages) ? (InitialTarget - NrFreedPages) : 0;
|
2001-12-28 00:04:45 +00:00
|
|
|
}
|
|
|
|
|
- Create mmsup.c in ReactOS memory manager directory. It hosts misc support functions:
- Copy kmap.c here, since it's the very definition of "misc support function"
- Copy some exported functions in mm.c which were listed as "misc functions"
- Warn that current implementation of MmIsNonPagedSystemAddressValid will kill kittens.
- Rename mm.c to mmfault.c, since other than the misc functions now in mmsup.c, it was all routines to handle page/access faults.
- Warn that MmIsAddressValid, as currently implemented, kills puppies.
- Move WriteWatch functions to virtual.c since they're part of the Virtual API system call set already hosted there.
- Move the global variables that people had been throwing in here to mminit.c, which is slightly more appropriate.
- Move wset.c's MmTrimUserMemory to balance.c, since that's where all other similar functions are located.
- Incidentally, kill wset.c, as this was the only function present.
- No functional changes, just refactoring and cleanup (other than warning the critter murder the two broken functions will achieve if called).
svn path=/trunk/; revision=41659
2009-06-28 07:52:30 +00:00
|
|
|
NTSTATUS
|
|
|
|
MmTrimUserMemory(ULONG Target, ULONG Priority, PULONG NrFreedPages)
|
|
|
|
{
|
2023-04-08 16:27:15 +00:00
|
|
|
PFN_NUMBER FirstPage, CurrentPage;
|
- Create mmsup.c in ReactOS memory manager directory. It hosts misc support functions:
- Copy kmap.c here, since it's the very definition of "misc support function"
- Copy some exported functions in mm.c which were listed as "misc functions"
- Warn that current implementation of MmIsNonPagedSystemAddressValid will kill kittens.
- Rename mm.c to mmfault.c, since other than the misc functions now in mmsup.c, it was all routines to handle page/access faults.
- Warn that MmIsAddressValid, as currently implemented, kills puppies.
- Move WriteWatch functions to virtual.c since they're part of the Virtual API system call set already hosted there.
- Move the global variables that people had been throwing in here to mminit.c, which is slightly more appropriate.
- Move wset.c's MmTrimUserMemory to balance.c, since that's where all other similar functions are located.
- Incidentally, kill wset.c, as this was the only function present.
- No functional changes, just refactoring and cleanup (other than warning the critter murder the two broken functions will achieve if called).
svn path=/trunk/; revision=41659
2009-06-28 07:52:30 +00:00
|
|
|
NTSTATUS Status;
|
2011-11-29 08:13:56 +00:00
|
|
|
|
- Create mmsup.c in ReactOS memory manager directory. It hosts misc support functions:
- Copy kmap.c here, since it's the very definition of "misc support function"
- Copy some exported functions in mm.c which were listed as "misc functions"
- Warn that current implementation of MmIsNonPagedSystemAddressValid will kill kittens.
- Rename mm.c to mmfault.c, since other than the misc functions now in mmsup.c, it was all routines to handle page/access faults.
- Warn that MmIsAddressValid, as currently implemented, kills puppies.
- Move WriteWatch functions to virtual.c since they're part of the Virtual API system call set already hosted there.
- Move the global variables that people had been throwing in here to mminit.c, which is slightly more appropriate.
- Move wset.c's MmTrimUserMemory to balance.c, since that's where all other similar functions are located.
- Incidentally, kill wset.c, as this was the only function present.
- No functional changes, just refactoring and cleanup (other than warning the critter murder the two broken functions will achieve if called).
svn path=/trunk/; revision=41659
2009-06-28 07:52:30 +00:00
|
|
|
(*NrFreedPages) = 0;
|
2011-11-29 08:13:56 +00:00
|
|
|
|
2023-09-06 12:53:53 +00:00
|
|
|
DPRINT("MM BALANCER: %s\n", Priority ? "Paging out!" : "Removing access bit!");
|
2021-01-28 14:42:12 +00:00
|
|
|
|
2023-04-08 16:27:15 +00:00
|
|
|
FirstPage = MmGetLRUFirstUserPage();
|
|
|
|
CurrentPage = FirstPage;
|
- Create mmsup.c in ReactOS memory manager directory. It hosts misc support functions:
- Copy kmap.c here, since it's the very definition of "misc support function"
- Copy some exported functions in mm.c which were listed as "misc functions"
- Warn that current implementation of MmIsNonPagedSystemAddressValid will kill kittens.
- Rename mm.c to mmfault.c, since other than the misc functions now in mmsup.c, it was all routines to handle page/access faults.
- Warn that MmIsAddressValid, as currently implemented, kills puppies.
- Move WriteWatch functions to virtual.c since they're part of the Virtual API system call set already hosted there.
- Move the global variables that people had been throwing in here to mminit.c, which is slightly more appropriate.
- Move wset.c's MmTrimUserMemory to balance.c, since that's where all other similar functions are located.
- Incidentally, kill wset.c, as this was the only function present.
- No functional changes, just refactoring and cleanup (other than warning the critter murder the two broken functions will achieve if called).
svn path=/trunk/; revision=41659
2009-06-28 07:52:30 +00:00
|
|
|
while (CurrentPage != 0 && Target > 0)
|
|
|
|
{
|
2021-01-28 14:42:12 +00:00
|
|
|
if (Priority)
|
|
|
|
{
|
|
|
|
Status = MmPageOutPhysicalAddress(CurrentPage);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT("Succeeded\n");
|
|
|
|
Target--;
|
|
|
|
(*NrFreedPages)++;
|
2023-04-08 16:27:15 +00:00
|
|
|
if (CurrentPage == FirstPage)
|
|
|
|
{
|
|
|
|
FirstPage = 0;
|
|
|
|
}
|
2021-01-28 14:42:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
- Create mmsup.c in ReactOS memory manager directory. It hosts misc support functions:
- Copy kmap.c here, since it's the very definition of "misc support function"
- Copy some exported functions in mm.c which were listed as "misc functions"
- Warn that current implementation of MmIsNonPagedSystemAddressValid will kill kittens.
- Rename mm.c to mmfault.c, since other than the misc functions now in mmsup.c, it was all routines to handle page/access faults.
- Warn that MmIsAddressValid, as currently implemented, kills puppies.
- Move WriteWatch functions to virtual.c since they're part of the Virtual API system call set already hosted there.
- Move the global variables that people had been throwing in here to mminit.c, which is slightly more appropriate.
- Move wset.c's MmTrimUserMemory to balance.c, since that's where all other similar functions are located.
- Incidentally, kill wset.c, as this was the only function present.
- No functional changes, just refactoring and cleanup (other than warning the critter murder the two broken functions will achieve if called).
svn path=/trunk/; revision=41659
2009-06-28 07:52:30 +00:00
|
|
|
{
|
2021-01-28 14:42:12 +00:00
|
|
|
/* When not paging-out agressively, just reset the accessed bit */
|
|
|
|
PEPROCESS Process = NULL;
|
|
|
|
PVOID Address = NULL;
|
|
|
|
BOOLEAN Accessed = FALSE;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We have a lock-ordering problem here. We cant lock the PFN DB before the Process address space.
|
|
|
|
* So we must use circonvoluted loops.
|
|
|
|
* Well...
|
|
|
|
*/
|
|
|
|
while (TRUE)
|
|
|
|
{
|
|
|
|
KAPC_STATE ApcState;
|
|
|
|
KIRQL OldIrql = MiAcquirePfnLock();
|
|
|
|
PMM_RMAP_ENTRY Entry = MmGetRmapListHeadPage(CurrentPage);
|
|
|
|
while (Entry)
|
|
|
|
{
|
|
|
|
if (RMAP_IS_SEGMENT(Entry->Address))
|
|
|
|
{
|
|
|
|
Entry = Entry->Next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check that we didn't treat this entry before */
|
|
|
|
if (Entry->Address < Address)
|
|
|
|
{
|
|
|
|
Entry = Entry->Next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((Entry->Address == Address) && (Entry->Process <= Process))
|
|
|
|
{
|
|
|
|
Entry = Entry->Next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Entry)
|
|
|
|
{
|
|
|
|
MiReleasePfnLock(OldIrql);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
Process = Entry->Process;
|
|
|
|
Address = Entry->Address;
|
|
|
|
|
2021-08-04 18:35:14 +00:00
|
|
|
ObReferenceObject(Process);
|
|
|
|
|
|
|
|
if (!ExAcquireRundownProtection(&Process->RundownProtect))
|
|
|
|
{
|
|
|
|
ObDereferenceObject(Process);
|
|
|
|
MiReleasePfnLock(OldIrql);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-01-28 14:42:12 +00:00
|
|
|
MiReleasePfnLock(OldIrql);
|
|
|
|
|
|
|
|
KeStackAttachProcess(&Process->Pcb, &ApcState);
|
2021-08-04 18:35:14 +00:00
|
|
|
MiLockProcessWorkingSet(Process, PsGetCurrentThread());
|
2021-01-28 14:42:12 +00:00
|
|
|
|
2021-08-04 21:57:39 +00:00
|
|
|
/* Be sure this is still valid. */
|
2021-08-04 18:35:14 +00:00
|
|
|
if (MmIsAddressValid(Address))
|
2021-01-28 14:42:12 +00:00
|
|
|
{
|
2021-08-04 18:35:14 +00:00
|
|
|
PMMPTE Pte = MiAddressToPte(Address);
|
2021-08-04 21:57:39 +00:00
|
|
|
Accessed = Accessed || Pte->u.Hard.Accessed;
|
|
|
|
Pte->u.Hard.Accessed = 0;
|
2021-01-28 14:42:12 +00:00
|
|
|
|
2021-08-04 21:57:39 +00:00
|
|
|
/* There is no need to invalidate, the balancer thread is never on a user process */
|
|
|
|
//KeInvalidateTlbEntry(Address);
|
2021-01-28 14:42:12 +00:00
|
|
|
}
|
|
|
|
|
2021-08-04 18:35:14 +00:00
|
|
|
MiUnlockProcessWorkingSet(Process, PsGetCurrentThread());
|
2021-01-28 14:42:12 +00:00
|
|
|
|
|
|
|
KeUnstackDetachProcess(&ApcState);
|
2021-08-04 18:35:14 +00:00
|
|
|
ExReleaseRundownProtection(&Process->RundownProtect);
|
|
|
|
ObDereferenceObject(Process);
|
2021-01-28 14:42:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!Accessed)
|
|
|
|
{
|
|
|
|
/* Nobody accessed this page since the last time we check. Time to clean up */
|
|
|
|
|
|
|
|
Status = MmPageOutPhysicalAddress(CurrentPage);
|
2023-04-08 16:27:15 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
if (CurrentPage == FirstPage)
|
|
|
|
{
|
|
|
|
FirstPage = 0;
|
|
|
|
}
|
|
|
|
}
|
2021-01-28 14:42:12 +00:00
|
|
|
// DPRINT1("Paged-out one page: %s\n", NT_SUCCESS(Status) ? "Yes" : "No");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Done for this page. */
|
- Create mmsup.c in ReactOS memory manager directory. It hosts misc support functions:
- Copy kmap.c here, since it's the very definition of "misc support function"
- Copy some exported functions in mm.c which were listed as "misc functions"
- Warn that current implementation of MmIsNonPagedSystemAddressValid will kill kittens.
- Rename mm.c to mmfault.c, since other than the misc functions now in mmsup.c, it was all routines to handle page/access faults.
- Warn that MmIsAddressValid, as currently implemented, kills puppies.
- Move WriteWatch functions to virtual.c since they're part of the Virtual API system call set already hosted there.
- Move the global variables that people had been throwing in here to mminit.c, which is slightly more appropriate.
- Move wset.c's MmTrimUserMemory to balance.c, since that's where all other similar functions are located.
- Incidentally, kill wset.c, as this was the only function present.
- No functional changes, just refactoring and cleanup (other than warning the critter murder the two broken functions will achieve if called).
svn path=/trunk/; revision=41659
2009-06-28 07:52:30 +00:00
|
|
|
Target--;
|
|
|
|
}
|
2011-11-29 08:13:56 +00:00
|
|
|
|
2021-01-27 09:29:07 +00:00
|
|
|
CurrentPage = MmGetLRUNextUserPage(CurrentPage, TRUE);
|
2023-04-08 16:27:15 +00:00
|
|
|
if (FirstPage == 0)
|
|
|
|
{
|
|
|
|
FirstPage = CurrentPage;
|
|
|
|
}
|
|
|
|
else if (CurrentPage == FirstPage)
|
|
|
|
{
|
|
|
|
DPRINT1("We are back at the start, abort!\n");
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
2021-01-27 09:29:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (CurrentPage)
|
|
|
|
{
|
|
|
|
KIRQL OldIrql = MiAcquirePfnLock();
|
|
|
|
MmDereferencePage(CurrentPage);
|
|
|
|
MiReleasePfnLock(OldIrql);
|
- Create mmsup.c in ReactOS memory manager directory. It hosts misc support functions:
- Copy kmap.c here, since it's the very definition of "misc support function"
- Copy some exported functions in mm.c which were listed as "misc functions"
- Warn that current implementation of MmIsNonPagedSystemAddressValid will kill kittens.
- Rename mm.c to mmfault.c, since other than the misc functions now in mmsup.c, it was all routines to handle page/access faults.
- Warn that MmIsAddressValid, as currently implemented, kills puppies.
- Move WriteWatch functions to virtual.c since they're part of the Virtual API system call set already hosted there.
- Move the global variables that people had been throwing in here to mminit.c, which is slightly more appropriate.
- Move wset.c's MmTrimUserMemory to balance.c, since that's where all other similar functions are located.
- Incidentally, kill wset.c, as this was the only function present.
- No functional changes, just refactoring and cleanup (other than warning the critter murder the two broken functions will achieve if called).
svn path=/trunk/; revision=41659
2009-06-28 07:52:30 +00:00
|
|
|
}
|
2011-11-29 08:13:56 +00:00
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
- Create mmsup.c in ReactOS memory manager directory. It hosts misc support functions:
- Copy kmap.c here, since it's the very definition of "misc support function"
- Copy some exported functions in mm.c which were listed as "misc functions"
- Warn that current implementation of MmIsNonPagedSystemAddressValid will kill kittens.
- Rename mm.c to mmfault.c, since other than the misc functions now in mmsup.c, it was all routines to handle page/access faults.
- Warn that MmIsAddressValid, as currently implemented, kills puppies.
- Move WriteWatch functions to virtual.c since they're part of the Virtual API system call set already hosted there.
- Move the global variables that people had been throwing in here to mminit.c, which is slightly more appropriate.
- Move wset.c's MmTrimUserMemory to balance.c, since that's where all other similar functions are located.
- Incidentally, kill wset.c, as this was the only function present.
- No functional changes, just refactoring and cleanup (other than warning the critter murder the two broken functions will achieve if called).
svn path=/trunk/; revision=41659
2009-06-28 07:52:30 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 23:59:25 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MmRebalanceMemoryConsumers(VOID)
|
|
|
|
{
|
2021-02-03 12:40:30 +00:00
|
|
|
// if (InterlockedCompareExchange(&PageOutThreadActive, 0, 1) == 0)
|
2011-11-29 23:59:25 +00:00
|
|
|
{
|
|
|
|
KeSetEvent(&MiBalancerEvent, IO_NO_INCREMENT, FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-06 05:42:32 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MmRebalanceMemoryConsumersAndWait(VOID)
|
|
|
|
{
|
|
|
|
ASSERT(PsGetCurrentProcess()->AddressCreationLock.Owner != KeGetCurrentThread());
|
|
|
|
ASSERT(!MM_ANY_WS_LOCK_HELD(PsGetCurrentThread()));
|
|
|
|
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
|
|
|
|
|
|
|
|
KeResetEvent(&MiBalancerDoneEvent);
|
|
|
|
MmRebalanceMemoryConsumers();
|
|
|
|
KeWaitForSingleObject(&MiBalancerDoneEvent, Executive, KernelMode, FALSE, NULL);
|
|
|
|
}
|
|
|
|
|
2001-12-28 00:04:45 +00:00
|
|
|
NTSTATUS
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2004-04-10 22:36:07 +00:00
|
|
|
MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
|
2010-07-15 22:50:12 +00:00
|
|
|
PPFN_NUMBER AllocatedPage)
|
2001-12-28 00:04:45 +00:00
|
|
|
{
|
2014-10-05 06:33:34 +00:00
|
|
|
PFN_NUMBER Page;
|
2023-09-06 11:34:25 +00:00
|
|
|
static INT i = 0;
|
|
|
|
static LARGE_INTEGER TinyTime = {{-1L, -1L}};
|
|
|
|
|
|
|
|
/* Delay some requests for the Memory Manager to recover pages */
|
|
|
|
if (i++ >= 100)
|
|
|
|
{
|
|
|
|
KeDelayExecutionThread(KernelMode, FALSE, &TinyTime);
|
|
|
|
i = 0;
|
|
|
|
}
|
2014-10-05 06:33:34 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Actually allocate the page.
|
|
|
|
*/
|
|
|
|
Page = MmAllocPage(Consumer);
|
|
|
|
if (Page == 0)
|
|
|
|
{
|
2023-04-02 15:35:30 +00:00
|
|
|
*AllocatedPage = 0;
|
|
|
|
return STATUS_NO_MEMORY;
|
2014-10-05 06:33:34 +00:00
|
|
|
}
|
|
|
|
*AllocatedPage = Page;
|
|
|
|
|
2023-04-02 15:35:30 +00:00
|
|
|
/* Update the target */
|
|
|
|
InterlockedIncrementUL(&MiMemoryConsumers[Consumer].PagesUsed);
|
|
|
|
UpdateTotalCommittedPages(1);
|
|
|
|
|
2014-10-05 06:33:34 +00:00
|
|
|
return(STATUS_SUCCESS);
|
2001-12-28 00:04:45 +00:00
|
|
|
}
|
2003-07-10 21:05:04 +00:00
|
|
|
|
2023-09-06 11:34:25 +00:00
|
|
|
VOID
|
|
|
|
CcRosTrimCache(
|
|
|
|
_In_ ULONG Target,
|
|
|
|
_Out_ PULONG NrFreed);
|
2014-08-06 21:53:09 +00:00
|
|
|
|
2008-11-29 20:47:48 +00:00
|
|
|
VOID NTAPI
|
2003-11-16 15:20:39 +00:00
|
|
|
MiBalancerThread(PVOID Unused)
|
|
|
|
{
|
2014-10-05 06:33:34 +00:00
|
|
|
PVOID WaitObjects[2];
|
|
|
|
NTSTATUS Status;
|
|
|
|
ULONG i;
|
2011-12-19 08:49:42 +00:00
|
|
|
|
2014-10-05 06:33:34 +00:00
|
|
|
WaitObjects[0] = &MiBalancerEvent;
|
|
|
|
WaitObjects[1] = &MiBalancerTimer;
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
2023-04-06 05:42:32 +00:00
|
|
|
KeSetEvent(&MiBalancerDoneEvent, IO_NO_INCREMENT, FALSE);
|
2014-10-05 06:33:34 +00:00
|
|
|
Status = KeWaitForMultipleObjects(2,
|
|
|
|
WaitObjects,
|
|
|
|
WaitAny,
|
|
|
|
Executive,
|
|
|
|
KernelMode,
|
|
|
|
FALSE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (Status == STATUS_WAIT_0 || Status == STATUS_WAIT_1)
|
2012-03-05 19:40:44 +00:00
|
|
|
{
|
2014-10-05 06:33:34 +00:00
|
|
|
ULONG InitialTarget = 0;
|
2023-09-06 11:34:25 +00:00
|
|
|
ULONG Target;
|
|
|
|
ULONG NrFreedPages;
|
2014-10-05 06:33:34 +00:00
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
ULONG OldTarget = InitialTarget;
|
|
|
|
|
|
|
|
/* Trim each consumer */
|
|
|
|
for (i = 0; i < MC_MAXIMUM; i++)
|
|
|
|
{
|
|
|
|
InitialTarget = MiTrimMemoryConsumer(i, InitialTarget);
|
|
|
|
}
|
|
|
|
|
2023-09-06 11:34:25 +00:00
|
|
|
/* Trim cache */
|
|
|
|
Target = max(InitialTarget, abs(MiMinimumAvailablePages - MmAvailablePages));
|
|
|
|
if (Target)
|
|
|
|
{
|
|
|
|
CcRosTrimCache(Target, &NrFreedPages);
|
|
|
|
InitialTarget -= min(NrFreedPages, InitialTarget);
|
|
|
|
}
|
|
|
|
|
2014-10-05 06:33:34 +00:00
|
|
|
/* No pages left to swap! */
|
|
|
|
if (InitialTarget != 0 &&
|
|
|
|
InitialTarget == OldTarget)
|
|
|
|
{
|
|
|
|
/* Game over */
|
|
|
|
KeBugCheck(NO_PAGES_AVAILABLE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (InitialTarget != 0);
|
2021-01-29 17:47:26 +00:00
|
|
|
|
|
|
|
if (Status == STATUS_WAIT_0)
|
|
|
|
InterlockedDecrement(&PageOutThreadActive);
|
2014-10-05 06:33:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT1("KeWaitForMultipleObjects failed, status = %x\n", Status);
|
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
|
|
|
}
|
|
|
|
}
|
2003-11-16 15:20:39 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2020-05-23 13:56:10 +00:00
|
|
|
VOID
|
2005-09-14 01:05:50 +00:00
|
|
|
NTAPI
|
2003-11-16 15:20:39 +00:00
|
|
|
MiInitBalancerThread(VOID)
|
|
|
|
{
|
2014-10-05 06:33:34 +00:00
|
|
|
KPRIORITY Priority;
|
|
|
|
NTSTATUS Status;
|
2021-01-28 14:42:12 +00:00
|
|
|
LARGE_INTEGER Timeout;
|
2003-11-16 15:20:39 +00:00
|
|
|
|
2014-10-05 06:33:34 +00:00
|
|
|
KeInitializeEvent(&MiBalancerEvent, SynchronizationEvent, FALSE);
|
2023-04-06 05:42:32 +00:00
|
|
|
KeInitializeEvent(&MiBalancerDoneEvent, SynchronizationEvent, FALSE);
|
2014-10-05 06:33:34 +00:00
|
|
|
KeInitializeTimerEx(&MiBalancerTimer, SynchronizationTimer);
|
2021-01-28 14:42:12 +00:00
|
|
|
|
|
|
|
Timeout.QuadPart = -20000000; /* 2 sec */
|
2014-10-05 06:33:34 +00:00
|
|
|
KeSetTimerEx(&MiBalancerTimer,
|
2021-01-28 14:42:12 +00:00
|
|
|
Timeout,
|
2014-10-05 06:33:34 +00:00
|
|
|
2000, /* 2 sec */
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
Status = PsCreateSystemThread(&MiBalancerThreadHandle,
|
|
|
|
THREAD_ALL_ACCESS,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
&MiBalancerThreadId,
|
|
|
|
MiBalancerThread,
|
|
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
KeBugCheck(MEMORY_MANAGEMENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
Priority = LOW_REALTIME_PRIORITY + 1;
|
|
|
|
NtSetInformationThread(MiBalancerThreadHandle,
|
|
|
|
ThreadPriority,
|
|
|
|
&Priority,
|
|
|
|
sizeof(Priority));
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2003-11-16 15:20:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 21:05:04 +00:00
|
|
|
/* EOF */
|