[NTOS]: Manage the PFN lists using the correct Flink/Blink semantics of the MMPFN structure, instead of typecasting a LIST_ENTRY on top of Flink and PteAddress. This allows PteAddress to be used now, and minimizes the number of differences between MMPFN and the ReactOS PHYSICAL_PAGE.

[NTOS]: Zero pages starting at the head of the free list, insert them at the back.
[NTOS]: Add MiInsertPageInFreeList to build the colored lists (not yet used) in the ARM3 PFN database.
[NTOS]: Rename the ReactOS PFN lists for free/zero to their real names as used in Windows.

svn path=/trunk/; revision=45634
This commit is contained in:
Sir Richard
2010-02-20 14:40:21 +00:00
parent ad0ec3b76b
commit 6118ff6a3c
4 changed files with 298 additions and 75 deletions
+32
View File
@@ -59,6 +59,11 @@
#error Define these please!
#endif
//
// PFN List Sentinel
//
#define LIST_HEAD 0xFFFFFFFF
//
// FIXFIX: These should go in ex.h after the pool merge
//
@@ -211,6 +216,7 @@ extern ULONG MmSecondaryColorMask;
extern ULONG MmNumberOfSystemPtes;
extern ULONG MmMaximumNonPagedPoolPercent;
extern ULONG MmLargeStackSize;
extern PMMCOLOR_TABLES MmFreePagesByColor[FreePageList + 1];
#define MI_PFN_TO_PFNENTRY(x) (&MmPfnDatabase[1][x])
#define MI_PFNENTRY_TO_PFN(x) (x - MmPfnDatabase[1])
@@ -374,4 +380,30 @@ MiUnmapLockedPagesInUserSpace(
IN PMDL Mdl
);
VOID
NTAPI
MiInsertInListTail(
IN PMMPFNLIST ListHead,
IN PMMPFN Entry
);
VOID
NTAPI
MiRemoveFromList(
IN PMMPFN Entry
);
PMMPFN
NTAPI
MiRemoveHeadList(
IN PMMPFNLIST ListHead
);
VOID
NTAPI
MiInsertPageInFreeList(
IN PFN_NUMBER PageFrameIndex
);
/* EOF */
+240
View File
@@ -0,0 +1,240 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: ntoskrnl/mm/ARM3/pfnlist.c
* PURPOSE: ARM Memory Manager PFN List Manipulation
* PROGRAMMERS: ReactOS Portable Systems Group
*/
/* INCLUDES *******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
#line 15 "ARM³::PFNLIST"
#define MODULE_INVOLVED_IN_ARM3
#include "../ARM3/miarm.h"
/* GLOBALS ********************************************************************/
MMPFNLIST MmZeroedPageListHead;
MMPFNLIST MmFreePageListHead;
MMPFNLIST MmStandbyPageListHead;
MMPFNLIST MmModifiedPageListHead;
MMPFNLIST MmModifiedNoWritePageListHead;
/* FUNCTIONS ******************************************************************/
VOID
NTAPI
MiInsertInListTail(IN PMMPFNLIST ListHead,
IN PMMPFN Entry)
{
PFN_NUMBER OldBlink, EntryIndex = MiGetPfnEntryIndex(Entry);
/* Get the back link */
OldBlink = ListHead->Blink;
if (OldBlink != LIST_HEAD)
{
/* Set the back pointer to point to us now */
MiGetPfnEntry(OldBlink)->u1.Flink = EntryIndex;
}
else
{
/* Set the list to point to us */
ListHead->Flink = EntryIndex;
}
/* Set the entry to point to the list head forwards, and the old page backwards */
Entry->u1.Flink = LIST_HEAD;
Entry->u2.Blink = OldBlink;
/* And now the head points back to us, since we are last */
ListHead->Blink = EntryIndex;
ListHead->Total++;
}
VOID
NTAPI
MiRemoveFromList(IN PMMPFN Entry)
{
PFN_NUMBER OldFlink, OldBlink;
PMMPFNLIST ListHead;
/* Find the list for this */
if (Entry->u3.e1.PageLocation == ZeroedPageList)
{
ListHead = &MmZeroedPageListHead;
}
else if (Entry->u3.e1.PageLocation == FreePageList)
{
ListHead = &MmFreePageListHead;
}
else
{
ListHead = NULL;
ASSERT(ListHead != NULL);
}
/* Get the forward and back pointers */
OldFlink = Entry->u1.Flink;
OldBlink = Entry->u2.Blink;
/* Check if the next entry is the list head */
if (OldFlink != LIST_HEAD)
{
/* It is not, so set the backlink of the actual entry, to our backlink */
MiGetPfnEntry(OldFlink)->u2.Blink = OldBlink;
}
else
{
/* Set the list head's backlink instead */
ListHead->Blink = OldFlink;
}
/* Check if the back entry is the list head */
if (OldBlink != LIST_HEAD)
{
/* It is not, so set the backlink of the actual entry, to our backlink */
MiGetPfnEntry(OldBlink)->u1.Flink = OldFlink;
}
else
{
/* Set the list head's backlink instead */
ListHead->Flink = OldFlink;
}
/* We are not on a list anymore */
ListHead->Total--;
Entry->u1.Flink = Entry->u2.Blink = 0;
}
PMMPFN
NTAPI
MiRemoveHeadList(IN PMMPFNLIST ListHead)
{
PFN_NUMBER Entry, Flink;
PMMPFN Pfn1;
/* Get the entry that's currently first on the list */
Entry = ListHead->Flink;
Pfn1 = MiGetPfnEntry(Entry);
/* Make the list point to the entry following the first one */
Flink = Pfn1->u1.Flink;
ListHead->Flink = Flink;
/* Check if the next entry is actually the list head */
if (ListHead->Flink != LIST_HEAD)
{
/* It isn't, so therefore whoever is coming next points back to the head */
MiGetPfnEntry(Flink)->u2.Blink = LIST_HEAD;
}
else
{
/* Then the list is empty, so the backlink should point back to us */
ListHead->Blink = LIST_HEAD;
}
/* We are not on a list anymore */
Pfn1->u1.Flink = Pfn1->u2.Blink = 0;
ListHead->Total--;
/* Return the head element */
return Pfn1;
}
VOID
NTAPI
MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
{
MMLISTS ListName;
PMMPFNLIST ListHead;
PFN_NUMBER LastPage;
PMMPFN Pfn1, Blink;
ULONG Color;
PMMCOLOR_TABLES ColorHead;
/* Make sure the page index is valid */
ASSERT((PageFrameIndex != 0) &&
(PageFrameIndex <= MmHighestPhysicalPage) &&
(PageFrameIndex >= MmLowestPhysicalPage));
/* Get the PFN entry */
Pfn1 = MI_PFN_TO_PFNENTRY(PageFrameIndex);
/* Sanity checks that a right kind of page is being inserted here */
ASSERT(Pfn1->u4.MustBeCached == 0);
ASSERT(Pfn1->u3.e1.Rom != 1);
ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
ASSERT(Pfn1->u4.VerifierAllocation == 0);
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
/* Get the free page list and increment its count */
ListHead = &MmFreePageListHead;
ListName = FreePageList;
ListHead->Total++;
/* Get the last page on the list */
LastPage = ListHead->Blink;
if (LastPage != -1)
{
/* Link us with the previous page, so we're at the end now */
MI_PFN_TO_PFNENTRY(LastPage)->u1.Flink = PageFrameIndex;
}
else
{
/* The list is empty, so we are the first page */
ListHead->Flink = PageFrameIndex;
}
/* Now make the list head point back to us (since we go at the end) */
ListHead->Blink = PageFrameIndex;
/* And initialize our own list pointers */
Pfn1->u1.Flink = -1;
Pfn1->u2.Blink = LastPage;
/* Set the list name and default priority */
Pfn1->u3.e1.PageLocation = ListName;
Pfn1->u4.Priority = 3;
/* Clear some status fields */
Pfn1->u4.InPageError = 0;
Pfn1->u4.AweAllocation = 0;
/* FIXME: More work to be done regarding page accounting */
/* Get the page color */
Color = PageFrameIndex & MmSecondaryColorMask;
/* Get the first page on the color list */
ColorHead = &MmFreePagesByColor[ListName][Color];
if (ColorHead->Flink == -1)
{
/* The list is empty, so we are the first page */
Pfn1->u4.PteFrame = -1;
ColorHead->Flink = PageFrameIndex;
}
else
{
/* Get the previous page */
Blink = (PMMPFN)ColorHead->Blink;
/* Make it link to us */
Pfn1->u4.PteFrame = MI_PFNENTRY_TO_PFN(Blink);
Blink->OriginalPte.u.Long = PageFrameIndex;
}
/* Now initialize our own list pointers */
ColorHead->Blink = Pfn1;
Pfn1->OriginalPte.u.Long = -1;
/* And increase the count in the colored list */
ColorHead->Count++;
/* FIXME: Notify zero page thread if enough pages are on the free list now */
}
/* EOF */
+25 -75
View File
@@ -31,9 +31,6 @@
//
#define RmapListHead AweReferenceCount
#define SavedSwapEntry u4.EntireFrame
#define RemoveEntryList(x) RemoveEntryList((PLIST_ENTRY)x)
#define InsertTailList(x, y) InsertTailList(x, (PLIST_ENTRY)y)
#define ListEntry u1
#define PHYSICAL_PAGE MMPFN
#define PPHYSICAL_PAGE PMMPFN
@@ -52,25 +49,8 @@ SIZE_T MmPagedPoolCommit;
SIZE_T MmPeakCommitment;
SIZE_T MmtotalCommitLimitMaximum;
MMPFNLIST MmZeroedPageListHead;
MMPFNLIST MmFreePageListHead;
MMPFNLIST MmStandbyPageListHead;
MMPFNLIST MmModifiedPageListHead;
MMPFNLIST MmModifiedNoWritePageListHead;
/* List of pages zeroed by the ZPW (MmZeroPageThreadMain) */
static LIST_ENTRY FreeZeroedPageListHead;
/* List of free pages, filled by MmGetReferenceCountPage and
* and MmInitializePageList */
static LIST_ENTRY FreeUnzeroedPageListHead;
static KEVENT ZeroPageThreadEvent;
static BOOLEAN ZeroPageThreadShouldTerminate = FALSE;
static ULONG UnzeroedPageCount = 0;
/* FUNCTIONS *************************************************************/
static RTL_BITMAP MiUserPfnBitMap;
/* FUNCTIONS *************************************************************/
@@ -153,7 +133,7 @@ NTAPI
MiIsPfnInUse(IN PMMPFN Pfn1)
{
return ((Pfn1->u3.e1.PageLocation != FreePageList) &&
(Pfn1->u3.e1.PageLocation != ZeroedPageList));
(Pfn1->u3.e1.PageLocation != ZeroedPageList));
}
PFN_NUMBER
@@ -265,11 +245,6 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
EndPfn = Pfn1 - SizeInPages + 1;
do
{
//
// If this was an unzeroed page, there are now less
//
if (Pfn1->u3.e1.PageLocation == ZeroedPageList) UnzeroedPageCount--;
//
// One less free page
//
@@ -278,7 +253,7 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
//
// This PFN is now a used page, set it up
//
RemoveEntryList(&Pfn1->ListEntry);
MiRemoveFromList(Pfn1);
Pfn1->u3.e2.ReferenceCount = 1;
Pfn1->SavedSwapEntry = 0;
@@ -368,7 +343,6 @@ MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress,
PFN_NUMBER PageCount, LowPage, HighPage, SkipPages, PagesFound = 0, Page;
PPFN_NUMBER MdlPage, LastMdlPage;
KIRQL OldIrql;
PLIST_ENTRY ListEntry;
PPHYSICAL_PAGE Pfn1;
INT LookForZeroedPages;
ASSERT (KeGetCurrentIrql() <= APC_LEVEL);
@@ -439,20 +413,19 @@ MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress,
//
// Do we have zeroed pages?
//
if (!IsListEmpty(&FreeZeroedPageListHead))
if (MmZeroedPageListHead.Total)
{
//
// Grab a zero page
//
ListEntry = RemoveTailList(&FreeZeroedPageListHead);
Pfn1 = MiRemoveHeadList(&MmZeroedPageListHead);
}
else if (!IsListEmpty(&FreeUnzeroedPageListHead))
else if (MmFreePageListHead.Total)
{
//
// Nope, grab an unzeroed page
//
ListEntry = RemoveTailList(&FreeUnzeroedPageListHead);
UnzeroedPageCount--;
Pfn1 = MiRemoveHeadList(&MmFreePageListHead);
}
else
{
@@ -463,11 +436,6 @@ MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress,
break;
}
//
// Get the PFN entry for this page
//
Pfn1 = CONTAINING_RECORD(ListEntry, PHYSICAL_PAGE, ListEntry);
//
// Make sure it's really free
//
@@ -530,12 +498,7 @@ MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress,
Pfn1->u3.e1.StartOfAllocation = 1;
Pfn1->u3.e1.EndOfAllocation = 1;
Pfn1->SavedSwapEntry = 0;
//
// If this page was unzeroed, we've consumed such a page
//
if (Pfn1->u3.e1.PageLocation != ZeroedPageList) UnzeroedPageCount--;
//
// Decrease available pages
//
@@ -681,8 +644,10 @@ MmInitializePageList(VOID)
ULONG NrSystemPages = 0;
/* Initialize the page lists */
InitializeListHead(&FreeUnzeroedPageListHead);
InitializeListHead(&FreeZeroedPageListHead);
MmFreePageListHead.Flink = MmFreePageListHead.Blink = LIST_HEAD;
MmZeroedPageListHead.Flink = MmZeroedPageListHead.Blink = LIST_HEAD;
MmZeroedPageListHead.Total = 0;
MmFreePageListHead.Total = 0;
/* This is what a used page looks like */
RtlZeroMemory(&UsedPage, sizeof(UsedPage));
@@ -694,12 +659,10 @@ MmInitializePageList(VOID)
NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
NextEntry = NextEntry->Flink)
{
#undef ListEntry
/* Get the descriptor */
Md = CONTAINING_RECORD(NextEntry,
MEMORY_ALLOCATION_DESCRIPTOR,
ListEntry);
#define ListEntry u1
/* Skip bad memory */
if ((Md->MemoryType == LoaderFirmwarePermanent) ||
@@ -722,9 +685,8 @@ MmInitializePageList(VOID)
{
/* Mark it as a free page */
MmPfnDatabase[0][Md->BasePage + i].u3.e1.PageLocation = FreePageList;
InsertTailList(&FreeUnzeroedPageListHead,
&MmPfnDatabase[0][Md->BasePage + i].ListEntry);
UnzeroedPageCount++;
MiInsertInListTail(&MmFreePageListHead,
&MmPfnDatabase[0][Md->BasePage + i]);
MmAvailablePages++;
}
}
@@ -873,10 +835,8 @@ MmDereferencePage(PFN_TYPE Pfn)
{
MmAvailablePages++;
Page->u3.e1.PageLocation = FreePageList;
InsertTailList(&FreeUnzeroedPageListHead,
&Page->ListEntry);
UnzeroedPageCount++;
if (UnzeroedPageCount > 8 && 0 == KeReadStateEvent(&ZeroPageThreadEvent))
MiInsertInListTail(&MmFreePageListHead, Page);
if (MmFreePageListHead.Total > 8 && 0 == KeReadStateEvent(&ZeroPageThreadEvent))
{
KeSetEvent(&ZeroPageThreadEvent, IO_NO_INCREMENT, FALSE);
}
@@ -888,16 +848,15 @@ NTAPI
MmAllocPage(ULONG Type, SWAPENTRY SwapEntry)
{
PFN_TYPE PfnOffset;
PLIST_ENTRY ListEntry;
PPHYSICAL_PAGE PageDescriptor;
BOOLEAN NeedClear = FALSE;
DPRINT("MmAllocPage()\n");
if (IsListEmpty(&FreeZeroedPageListHead))
if (MmZeroedPageListHead.Total == 0)
{
if (IsListEmpty(&FreeUnzeroedPageListHead))
{
if (MmFreePageListHead.Total == 0)
{
/* Check if this allocation is for the PFN DB itself */
if (MmNumberOfPhysicalPages == 0)
{
@@ -907,18 +866,13 @@ MmAllocPage(ULONG Type, SWAPENTRY SwapEntry)
DPRINT1("MmAllocPage(): Out of memory\n");
return 0;
}
ListEntry = RemoveTailList(&FreeUnzeroedPageListHead);
UnzeroedPageCount--;
PageDescriptor = CONTAINING_RECORD(ListEntry, PHYSICAL_PAGE, ListEntry);
PageDescriptor = MiRemoveHeadList(&MmFreePageListHead);
NeedClear = TRUE;
}
else
{
ListEntry = RemoveTailList(&FreeZeroedPageListHead);
PageDescriptor = CONTAINING_RECORD(ListEntry, PHYSICAL_PAGE, ListEntry);
PageDescriptor = MiRemoveHeadList(&MmZeroedPageListHead);
}
PageDescriptor->u3.e2.ReferenceCount = 1;
@@ -931,7 +885,7 @@ MmAllocPage(ULONG Type, SWAPENTRY SwapEntry)
{
MiZeroPage(PfnOffset);
}
PageDescriptor->u3.e1.PageLocation = ActiveAndValid;
return PfnOffset;
}
@@ -961,7 +915,6 @@ MmZeroPageThreadMain(PVOID Ignored)
{
NTSTATUS Status;
KIRQL oldIrql;
PLIST_ENTRY ListEntry;
PPHYSICAL_PAGE PageDescriptor;
PFN_TYPE Pfn;
ULONG Count;
@@ -988,11 +941,9 @@ MmZeroPageThreadMain(PVOID Ignored)
}
Count = 0;
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
while (!IsListEmpty(&FreeUnzeroedPageListHead))
while (MmFreePageListHead.Total)
{
ListEntry = RemoveTailList(&FreeUnzeroedPageListHead);
UnzeroedPageCount--;
PageDescriptor = CONTAINING_RECORD(ListEntry, PHYSICAL_PAGE, ListEntry);
PageDescriptor = MiRemoveHeadList(&MmFreePageListHead);
/* We set the page to used, because MmCreateVirtualMapping failed with unused pages */
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
Pfn = PageDescriptor - MmPfnDatabase[0];
@@ -1001,15 +952,14 @@ MmZeroPageThreadMain(PVOID Ignored)
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
if (NT_SUCCESS(Status))
{
InsertHeadList(&FreeZeroedPageListHead, ListEntry);
MiInsertInListTail(&MmZeroedPageListHead, PageDescriptor);
PageDescriptor->u3.e1.PageLocation = ZeroedPageList;
Count++;
}
else
{
InsertHeadList(&FreeUnzeroedPageListHead, ListEntry);
MiInsertInListTail(&MmFreePageListHead, PageDescriptor);
PageDescriptor->u3.e1.PageLocation = FreePageList;
UnzeroedPageCount++;
}
}
+1
View File
@@ -394,6 +394,7 @@
<file>mmsup.c</file>
<file>ncache.c</file>
<file>pagfault.c</file>
<file>pfnlist.c</file>
<file>pool.c</file>
<file>procsup.c</file>
<file>syspte.c</file>