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?re... ============================================================================== --- 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.r... ============================================================================== --- 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>