Author: sir_richard
Date: Sat Feb 20 15:40:21 2010
New Revision: 45634
URL:
http://svn.reactos.org/svn/reactos?rev=45634&view=rev
Log:
[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.
Added:
trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c (with props)
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
trunk/reactos/ntoskrnl/mm/freelist.c
trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild
Modified: trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/miarm.h?r…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] Sat Feb 20 15:40:21 2010
@@ -58,6 +58,11 @@
#else
#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 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 @@
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 */
Added: trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c (added)
+++ trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c [iso-8859-1] Sat Feb 20 15:40:21 2010
@@ -1,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 */
Propchange: trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/reactos/ntoskrnl/mm/freelist.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/freelist.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/freelist.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/freelist.c [iso-8859-1] Sat Feb 20 15:40:21 2010
@@ -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 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 @@
MiIsPfnInUse(IN PMMPFN Pfn1)
{
return ((Pfn1->u3.e1.PageLocation != FreePageList) &&
- (Pfn1->u3.e1.PageLocation != ZeroedPageList));
+ (Pfn1->u3.e1.PageLocation != ZeroedPageList));
}
PFN_NUMBER
@@ -266,11 +246,6 @@
do
{
//
- // If this was an unzeroed page, there are now less
- //
- if (Pfn1->u3.e1.PageLocation == ZeroedPageList)
UnzeroedPageCount--;
-
- //
// One less free page
//
MmAvailablePages--;
@@ -278,7 +253,7 @@
//
// 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 @@
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 @@
//
// 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
{
@@ -462,11 +435,6 @@
ASSERT(PagesFound);
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 @@
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 @@
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 @@
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 @@
{
/* 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 @@
{
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 @@
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 @@
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 @@
{
MiZeroPage(PfnOffset);
}
-
+
PageDescriptor->u3.e1.PageLocation = ActiveAndValid;
return PfnOffset;
}
@@ -961,7 +915,6 @@
{
NTSTATUS Status;
KIRQL oldIrql;
- PLIST_ENTRY ListEntry;
PPHYSICAL_PAGE PageDescriptor;
PFN_TYPE Pfn;
ULONG Count;
@@ -988,11 +941,9 @@
}
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 @@
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++;
}
}
Modified: trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl-generic.…
==============================================================================
--- trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] Sat Feb 20 15:40:21 2010
@@ -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>