mirror of
https://github.com/reactos/reactos.git
synced 2025-08-02 06:55:44 +00:00
[NTOS]: Instead of having an LRU linked list of working set pages, we instead have a bitmap.
Advantage: Pages are only in a linked list when they are NOT active (free/zeroed, for now). This makes the LIST_ENTRY fields usable when a page is active, so we can store data in there. This will make it easier to sync our PFN format with Windows. Advantage: It's a lot faster to set/clear bits than to do list operations (both still O1 though). Scanning for the bit is a bit slower than parsing a list, on the other hand, so it's a toss. Disadvantage: We lose LRU, which in theory makes us cannibalize working sets randomly instead of by-usage. However, considering the speed of ReactOS paging, and the effects of canabalizing the WS in the first place, I doubt this is really a problem. The main point of this is advantage #1 -- making used pages not be on any lists. This will allow us to almost 100% sync the PFN layouts, which will lead to the eventual negation of any temporary disavantages. svn path=/trunk/; revision=45616
This commit is contained in:
parent
1337cbf945
commit
37aa114310
3 changed files with 55 additions and 48 deletions
|
@ -188,11 +188,6 @@ MmTrimUserMemory(ULONG Target, ULONG Priority, PULONG NrFreedPages)
|
||||||
Target--;
|
Target--;
|
||||||
(*NrFreedPages)++;
|
(*NrFreedPages)++;
|
||||||
}
|
}
|
||||||
else if (Status == STATUS_PAGEFILE_QUOTA)
|
|
||||||
{
|
|
||||||
MmRemoveLRUUserPage(CurrentPage);
|
|
||||||
MmInsertLRULastUserPage(CurrentPage);
|
|
||||||
}
|
|
||||||
|
|
||||||
CurrentPage = NextPage;
|
CurrentPage = NextPage;
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,71 +74,81 @@ static ULONG UnzeroedPageCount = 0;
|
||||||
|
|
||||||
/* FUNCTIONS *************************************************************/
|
/* FUNCTIONS *************************************************************/
|
||||||
|
|
||||||
|
static RTL_BITMAP MiUserPfnBitMap;
|
||||||
|
|
||||||
|
/* FUNCTIONS *************************************************************/
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
MiInitializeUserPfnBitmap(VOID)
|
||||||
|
{
|
||||||
|
PVOID Bitmap;
|
||||||
|
|
||||||
|
/* Allocate enough buffer for the PFN bitmap and align it on 32-bits */
|
||||||
|
Bitmap = ExAllocatePoolWithTag(NonPagedPool,
|
||||||
|
(((MmHighestPhysicalPage + 1) + 31) / 32) * 4,
|
||||||
|
' mM');
|
||||||
|
ASSERT(Bitmap);
|
||||||
|
|
||||||
|
/* Initialize it and clear all the bits to begin with */
|
||||||
|
RtlInitializeBitMap(&MiUserPfnBitMap,
|
||||||
|
Bitmap,
|
||||||
|
MmHighestPhysicalPage + 1);
|
||||||
|
RtlClearAllBits(&MiUserPfnBitMap);
|
||||||
|
}
|
||||||
|
|
||||||
PFN_TYPE
|
PFN_TYPE
|
||||||
NTAPI
|
NTAPI
|
||||||
MmGetLRUFirstUserPage(VOID)
|
MmGetLRUFirstUserPage(VOID)
|
||||||
{
|
{
|
||||||
PLIST_ENTRY NextListEntry;
|
ULONG Position;
|
||||||
PHYSICAL_PAGE* PageDescriptor;
|
KIRQL OldIrql;
|
||||||
KIRQL oldIrql;
|
|
||||||
|
|
||||||
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
/* Find the first user page */
|
||||||
NextListEntry = UserPageListHead.Flink;
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
if (NextListEntry == &UserPageListHead)
|
Position = RtlFindSetBits(&MiUserPfnBitMap, 1, 0);
|
||||||
{
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
|
if (Position == 0xFFFFFFFF) return 0;
|
||||||
return 0;
|
|
||||||
}
|
/* Return it */
|
||||||
PageDescriptor = CONTAINING_RECORD(NextListEntry, PHYSICAL_PAGE, ListEntry);
|
return Position;
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
|
|
||||||
return PageDescriptor - MmPfnDatabase[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MmInsertLRULastUserPage(PFN_TYPE Pfn)
|
MmInsertLRULastUserPage(PFN_TYPE Pfn)
|
||||||
{
|
{
|
||||||
KIRQL oldIrql;
|
KIRQL OldIrql;
|
||||||
PPHYSICAL_PAGE Page;
|
|
||||||
|
|
||||||
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
/* Set the page as a user page */
|
||||||
Page = MiGetPfnEntry(Pfn);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
// if (!Page->Consumer != MC_USER) DPRINT1("Page Consumer: %d\n", Page->Consumer);
|
RtlSetBit(&MiUserPfnBitMap, Pfn);
|
||||||
ASSERT(Page->Consumer == MC_USER);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
ASSERT(Page->u3.e1.PageLocation = ActiveAndValid);
|
|
||||||
InsertTailList(&UserPageListHead, &Page->ListEntry);
|
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PFN_TYPE
|
PFN_TYPE
|
||||||
NTAPI
|
NTAPI
|
||||||
MmGetLRUNextUserPage(PFN_TYPE PreviousPfn)
|
MmGetLRUNextUserPage(PFN_TYPE PreviousPfn)
|
||||||
{
|
{
|
||||||
PLIST_ENTRY NextListEntry;
|
ULONG Position;
|
||||||
PHYSICAL_PAGE* PageDescriptor;
|
KIRQL OldIrql;
|
||||||
KIRQL oldIrql;
|
|
||||||
PPHYSICAL_PAGE Page;
|
|
||||||
|
|
||||||
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
/* Find the next user page */
|
||||||
Page = MiGetPfnEntry(PreviousPfn);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
ASSERT(Page->Consumer == MC_USER);
|
Position = RtlFindSetBits(&MiUserPfnBitMap, 1, PreviousPfn + 1);
|
||||||
ASSERT(Page->u3.e1.PageLocation = ActiveAndValid);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
NextListEntry = (PLIST_ENTRY)Page->ListEntry.Flink;
|
if (Position == 0xFFFFFFFF) return 0;
|
||||||
if (NextListEntry == &UserPageListHead)
|
|
||||||
{
|
/* Return it */
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
|
return Position;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
PageDescriptor = CONTAINING_RECORD(NextListEntry, PHYSICAL_PAGE, ListEntry);
|
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
|
|
||||||
return PageDescriptor - MmPfnDatabase[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MmRemoveLRUUserPage(PFN_TYPE Page)
|
MmRemoveLRUUserPage(PFN_TYPE Page)
|
||||||
{
|
{
|
||||||
RemoveEntryList(&MiGetPfnEntry(Page)->ListEntry);
|
/* Unset the page as a user page */
|
||||||
|
RtlClearBit(&MiUserPfnBitMap, Page);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
|
@ -907,7 +917,6 @@ MmDereferencePage(PFN_TYPE Pfn)
|
||||||
if (Page->u3.e2.ReferenceCount == 0)
|
if (Page->u3.e2.ReferenceCount == 0)
|
||||||
{
|
{
|
||||||
MmAvailablePages++;
|
MmAvailablePages++;
|
||||||
if (Page->Consumer == MC_USER) RemoveEntryList(&Page->ListEntry);
|
|
||||||
Page->u3.e1.PageLocation = FreePageList;
|
Page->u3.e1.PageLocation = FreePageList;
|
||||||
InsertTailList(&FreeUnzeroedPageListHead,
|
InsertTailList(&FreeUnzeroedPageListHead,
|
||||||
&Page->ListEntry);
|
&Page->ListEntry);
|
||||||
|
|
|
@ -349,6 +349,8 @@ MiDbgDumpMemoryDescriptors(VOID)
|
||||||
DPRINT1("Total: %08lX (%d MB)\n", TotalPages, (TotalPages * PAGE_SIZE) / 1024 / 1024);
|
DPRINT1("Total: %08lX (%d MB)\n", TotalPages, (TotalPages * PAGE_SIZE) / 1024 / 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID NTAPI MiInitializeUserPfnBitmap(VOID);
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
NTAPI
|
NTAPI
|
||||||
MmInitSystem(IN ULONG Phase,
|
MmInitSystem(IN ULONG Phase,
|
||||||
|
@ -397,6 +399,7 @@ MmInitSystem(IN ULONG Phase,
|
||||||
MmInitializePagedPool();
|
MmInitializePagedPool();
|
||||||
|
|
||||||
/* Initialize working sets */
|
/* Initialize working sets */
|
||||||
|
MiInitializeUserPfnBitmap();
|
||||||
MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
|
MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
|
||||||
|
|
||||||
/* Initialize the user mode image list */
|
/* Initialize the user mode image list */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue