X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=ntoskrnl%2Fmm%2FARM3%2Fpfnlist.c;h=9c2f5bdbe18c5a246462b16de9800a80adf72a6a;hp=fb24d9fdbffddaada4f978b93ccd464fadc5698c;hb=406dfdbc870f3a6874c0959a87428c94f7526d3b;hpb=251d21958c0cf60b190bfac974ae8db66309abb8 diff --git a/ntoskrnl/mm/ARM3/pfnlist.c b/ntoskrnl/mm/ARM3/pfnlist.c index fb24d9fdbff..9c2f5bdbe18 100644 --- a/ntoskrnl/mm/ARM3/pfnlist.c +++ b/ntoskrnl/mm/ARM3/pfnlist.c @@ -34,6 +34,7 @@ do { \ BOOLEAN MmDynamicPfn; BOOLEAN MmMirroring; +ULONG MmSystemPageColor; MMPFNLIST MmZeroedPageListHead = {0, ZeroedPageList, LIST_HEAD, LIST_HEAD}; MMPFNLIST MmFreePageListHead = {0, FreePageList, LIST_HEAD, LIST_HEAD}; @@ -54,6 +55,10 @@ PMMPFNLIST MmPageLocationList[] = NULL, NULL }; + +ULONG MI_PFN_CURRENT_USAGE; +CHAR MI_PFN_CURRENT_PROCESS_NAME[16] = "None yet"; + /* FUNCTIONS ******************************************************************/ VOID @@ -66,141 +71,11 @@ MiZeroPhysicalPage(IN PFN_NUMBER PageFrameIndex) /* Map in hyperspace, then wipe it using XMMI or MEMSET */ VirtualAddress = MiMapPageInHyperSpace(Process, PageFrameIndex, &OldIrql); + ASSERT(VirtualAddress); KeZeroPages(VirtualAddress, PAGE_SIZE); MiUnmapPageInHyperSpace(Process, VirtualAddress, OldIrql); } -VOID -NTAPI -MiInsertInListTail(IN PMMPFNLIST ListHead, - IN PMMPFN Entry) -{ - PFN_NUMBER OldBlink, EntryIndex = MiGetPfnEntryIndex(Entry); - ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); - ASSERT_LIST_INVARIANT(ListHead); - - /* 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++; - ASSERT_LIST_INVARIANT(ListHead); -} - -VOID -NTAPI -MiInsertZeroListAtBack(IN PFN_NUMBER EntryIndex) -{ - PFN_NUMBER OldBlink; - PMMPFNLIST ListHead; - PMMPFN Pfn1; -#if 0 - PMMPFN Blink; - ULONG Color; - PMMCOLOR_TABLES ColorHead; -#endif - - /* Make sure the PFN lock is held */ - ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); - - /* Get the descriptor */ - Pfn1 = MiGetPfnEntry(EntryIndex); - ASSERT(Pfn1->u3.e2.ReferenceCount == 0); - ASSERT(Pfn1->u4.MustBeCached == 0); - ASSERT(Pfn1->u3.e1.Rom == 0); - ASSERT(Pfn1->u3.e1.RemovalRequested == 0); - ASSERT(Pfn1->u4.InPageError == 0); - - /* Use the zero list */ - ListHead = &MmZeroedPageListHead; - ASSERT_LIST_INVARIANT(ListHead); - ListHead->Total++; - - /* 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 */ - Pfn1->u1.Flink = LIST_HEAD; - Pfn1->u2.Blink = OldBlink; - - /* And now the head points back to us, since we are last */ - ListHead->Blink = EntryIndex; - ASSERT_LIST_INVARIANT(ListHead); - - /* Update the page location */ - Pfn1->u3.e1.PageLocation = ZeroedPageList; - - /* FIXME: NOT YET Due to caller semantics: Update the available page count */ - //MmAvailablePages++; - - /* Check if we've reached the configured low memory threshold */ - if (MmAvailablePages == MmLowMemoryThreshold) - { - /* Clear the event, because now we're ABOVE the threshold */ - KeClearEvent(MiLowMemoryEvent); - } - else if (MmAvailablePages == MmHighMemoryThreshold) - { - /* Otherwise check if we reached the high threshold and signal the event */ - KeSetEvent(MiHighMemoryEvent, 0, FALSE); - } - -#if 0 - /* Get the page color */ - Color = EntryIndex & MmSecondaryColorMask; - - /* Get the first page on the color list */ - ColorHead = &MmFreePagesByColor[ZeroedPageList][Color]; - if (ColorHead->Flink == LIST_HEAD) - { - /* The list is empty, so we are the first page */ - Pfn1->u4.PteFrame = -1; - ColorHead->Flink = EntryIndex; - } - else - { - /* Get the previous page */ - Blink = (PMMPFN)ColorHead->Blink; - - /* Make it link to us */ - Pfn1->u4.PteFrame = MiGetPfnEntryIndex(Blink); - Blink->OriginalPte.u.Long = EntryIndex; - } - - /* Now initialize our own list pointers */ - ColorHead->Blink = Pfn1; - Pfn1->OriginalPte.u.Long = LIST_HEAD; - - /* And increase the count in the colored list */ - ColorHead->Count++; -#endif -} - VOID NTAPI MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry) @@ -208,6 +83,9 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry) PFN_NUMBER OldFlink, OldBlink; PMMPFNLIST ListHead; MMLISTS ListName; + ULONG Color; + PMMCOLOR_TABLES ColorTable; + PMMPFN Pfn1; /* Make sure the PFN lock is held */ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); @@ -235,7 +113,7 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry) if (OldFlink != LIST_HEAD) { /* It is not, so set the backlink of the actual entry, to our backlink */ - MiGetPfnEntry(OldFlink)->u2.Blink = OldBlink; + MI_PFN_ELEMENT(OldFlink)->u2.Blink = OldBlink; } else { @@ -247,20 +125,72 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry) if (OldBlink != LIST_HEAD) { /* It is not, so set the backlink of the actual entry, to our backlink */ - MiGetPfnEntry(OldBlink)->u1.Flink = OldFlink; + MI_PFN_ELEMENT(OldBlink)->u1.Flink = OldFlink; } else { /* Set the list head's backlink instead */ ListHead->Flink = OldFlink; } + + /* Get the page color */ + OldBlink = MiGetPfnEntryIndex(Entry); + Color = OldBlink & MmSecondaryColorMask; + + /* Get the first page on the color list */ + ColorTable = &MmFreePagesByColor[ListName][Color]; + + /* Check if this was was actually the head */ + OldFlink = ColorTable->Flink; + if (OldFlink == OldBlink) + { + /* Make the table point to the next page this page was linking to */ + ColorTable->Flink = Entry->OriginalPte.u.Long; + if (ColorTable->Flink != LIST_HEAD) + { + /* And make the previous link point to the head now */ + MI_PFN_ELEMENT(ColorTable->Flink)->u4.PteFrame = COLORED_LIST_HEAD; + } + else + { + /* And if that page was the head, loop the list back around */ + ColorTable->Blink = (PVOID)LIST_HEAD; + } + } + else + { + /* This page shouldn't be pointing back to the head */ + ASSERT(Entry->u4.PteFrame != COLORED_LIST_HEAD); + + /* Make the back link point to whoever the next page is */ + Pfn1 = MI_PFN_ELEMENT(Entry->u4.PteFrame); + Pfn1->OriginalPte.u.Long = Entry->OriginalPte.u.Long; + + /* Check if this page was pointing to the head */ + if (Entry->OriginalPte.u.Long != LIST_HEAD) + { + /* Make the back link point to the head */ + Pfn1 = MI_PFN_ELEMENT(Entry->OriginalPte.u.Long); + Pfn1->u4.PteFrame = Entry->u4.PteFrame; + } + else + { + /* Then the table is directly back pointing to this page now */ + ColorTable->Blink = Pfn1; + } + } + + /* One less colored page */ + ASSERT(ColorTable->Count >= 1); + ColorTable->Count--; + /* ReactOS Hack */ + Entry->OriginalPte.u.Long = 0; + /* We are not on a list anymore */ Entry->u1.Flink = Entry->u2.Blink = 0; ASSERT_LIST_INVARIANT(ListHead); - /* FIXME: Deal with color list */ - /* See if we hit any thresholds */ if (MmAvailablePages == MmHighMemoryThreshold) { @@ -278,6 +208,14 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry) { /* FIXME: Should wake up the MPW and working set manager, if we had one */ } + +#if MI_TRACE_PFNS + ASSERT(MI_PFN_CURRENT_USAGE != MI_USAGE_NOT_SET); + Entry->PfnUsage = MI_PFN_CURRENT_USAGE; + memcpy(Entry->ProcessName, MI_PFN_CURRENT_PROCESS_NAME, 16); +// MI_PFN_CURRENT_USAGE = MI_USAGE_NOT_SET; +// memcpy(MI_PFN_CURRENT_PROCESS_NAME, "Not Set", 16); +#endif } PFN_NUMBER @@ -290,15 +228,14 @@ MiRemovePageByColor(IN PFN_NUMBER PageIndex, MMLISTS ListName; PFN_NUMBER OldFlink, OldBlink; ULONG OldColor, OldCache; -#if 0 PMMCOLOR_TABLES ColorTable; -#endif + /* Make sure PFN lock is held */ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); ASSERT(Color < MmSecondaryColors); /* Get the PFN entry */ - Pfn1 = MiGetPfnEntry(PageIndex); + Pfn1 = MI_PFN_ELEMENT(PageIndex); ASSERT(Pfn1->u3.e1.RemovalRequested == 0); ASSERT(Pfn1->u3.e1.Rom == 0); @@ -323,19 +260,19 @@ MiRemovePageByColor(IN PFN_NUMBER PageIndex, if (OldFlink != LIST_HEAD) { /* It is not, so set the backlink of the actual entry, to our backlink */ - MiGetPfnEntry(OldFlink)->u2.Blink = OldBlink; + MI_PFN_ELEMENT(OldFlink)->u2.Blink = OldBlink; } else { /* Set the list head's backlink instead */ - ListHead->Blink = OldFlink; + ListHead->Blink = OldBlink; } /* 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; + MI_PFN_ELEMENT(OldBlink)->u1.Flink = OldFlink; } else { @@ -352,27 +289,32 @@ MiRemovePageByColor(IN PFN_NUMBER PageIndex, Pfn1->u3.e1.PageColor = OldColor; Pfn1->u3.e1.CacheAttribute = OldCache; -#if 0 // When switching to ARM3 /* Get the first page on the color list */ + ASSERT(Color < MmSecondaryColors); ColorTable = &MmFreePagesByColor[ListName][Color]; ASSERT(ColorTable->Count >= 1); /* Set the forward link to whoever we were pointing to */ ColorTable->Flink = Pfn1->OriginalPte.u.Long; + + /* Get the first page on the color list */ if (ColorTable->Flink == LIST_HEAD) { /* This is the beginning of the list, so set the sentinel value */ - ColorTable->Blink = LIST_HEAD; + ColorTable->Blink = (PVOID)LIST_HEAD; } else { /* The list is empty, so we are the first page */ - MiGetPfnEntry(ColorTable->Flink)->u4.PteFrame = -1; + MI_PFN_ELEMENT(ColorTable->Flink)->u4.PteFrame = COLORED_LIST_HEAD; } - /* One more page */ - ColorTable->Total++; -#endif + /* One less page */ + ColorTable->Count--; + + /* ReactOS Hack */ + Pfn1->OriginalPte.u.Long = 0; + /* See if we hit any thresholds */ if (MmAvailablePages == MmHighMemoryThreshold) { @@ -391,6 +333,14 @@ MiRemovePageByColor(IN PFN_NUMBER PageIndex, /* FIXME: Should wake up the MPW and working set manager, if we had one */ } +#if MI_TRACE_PFNS + //ASSERT(MI_PFN_CURRENT_USAGE != MI_USAGE_NOT_SET); + Pfn1->PfnUsage = MI_PFN_CURRENT_USAGE; + memcpy(Pfn1->ProcessName, MI_PFN_CURRENT_PROCESS_NAME, 16); + //MI_PFN_CURRENT_USAGE = MI_USAGE_NOT_SET; + //memcpy(MI_PFN_CURRENT_PROCESS_NAME, "Not Set", 16); +#endif + /* Return the page */ return PageIndex; } @@ -406,9 +356,8 @@ MiRemoveAnyPage(IN ULONG Color) ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); ASSERT(MmAvailablePages != 0); ASSERT(Color < MmSecondaryColors); - + /* Check the colored free list */ -#if 0 // Enable when using ARM3 database */ PageIndex = MmFreePagesByColor[FreePageList][Color].Flink; if (PageIndex == LIST_HEAD) { @@ -416,7 +365,6 @@ MiRemoveAnyPage(IN ULONG Color) PageIndex = MmFreePagesByColor[ZeroedPageList][Color].Flink; if (PageIndex == LIST_HEAD) { -#endif /* Check the free list */ ASSERT_LIST_INVARIANT(&MmFreePageListHead); PageIndex = MmFreePageListHead.Flink; @@ -434,16 +382,14 @@ MiRemoveAnyPage(IN ULONG Color) ASSERT(MmZeroedPageListHead.Total == 0); } } -#if 0 // Enable when using ARM3 database */ } } -#endif /* Remove the page from its list */ PageIndex = MiRemovePageByColor(PageIndex, Color); /* Sanity checks */ - Pfn1 = MiGetPfnEntry(PageIndex); + Pfn1 = MI_PFN_ELEMENT(PageIndex); ASSERT((Pfn1->u3.e1.PageLocation == FreePageList) || (Pfn1->u3.e1.PageLocation == ZeroedPageList)); ASSERT(Pfn1->u3.e2.ReferenceCount == 0); @@ -469,25 +415,23 @@ MiRemoveZeroPage(IN ULONG Color) ASSERT(Color < MmSecondaryColors); /* Check the colored zero list */ -#if 0 // Enable when using ARM3 database */ PageIndex = MmFreePagesByColor[ZeroedPageList][Color].Flink; if (PageIndex == LIST_HEAD) { -#endif /* Check the zero list */ ASSERT_LIST_INVARIANT(&MmZeroedPageListHead); PageIndex = MmZeroedPageListHead.Flink; Color = PageIndex & MmSecondaryColorMask; if (PageIndex == LIST_HEAD) { + /* This means there's no zero pages, we have to look for free ones */ ASSERT(MmZeroedPageListHead.Total == 0); Zero = TRUE; -#if 0 // Enable when using ARM3 database */ + /* Check the colored free list */ - PageIndex = MmFreePagesByColor[ZeroedPageList][Color].Flink; + PageIndex = MmFreePagesByColor[FreePageList][Color].Flink; if (PageIndex == LIST_HEAD) { -#endif /* Check the free list */ ASSERT_LIST_INVARIANT(&MmFreePageListHead); PageIndex = MmFreePageListHead.Flink; @@ -498,21 +442,18 @@ MiRemoveZeroPage(IN ULONG Color) /* FIXME: Should check the standby list */ ASSERT(MmZeroedPageListHead.Total == 0); } -#if 0 // Enable when using ARM3 database */ } -#endif } -#if 0 // Enable when using ARM3 database */ } -#endif + /* Sanity checks */ - Pfn1 = MiGetPfnEntry(PageIndex); + Pfn1 = MI_PFN_ELEMENT(PageIndex); ASSERT((Pfn1->u3.e1.PageLocation == FreePageList) || (Pfn1->u3.e1.PageLocation == ZeroedPageList)); /* Remove the page from its list */ PageIndex = MiRemovePageByColor(PageIndex, Color); - ASSERT(Pfn1 == MiGetPfnEntry(PageIndex)); + ASSERT(Pfn1 == MI_PFN_ELEMENT(PageIndex)); /* Zero it, if needed */ if (Zero) MiZeroPhysicalPage(PageIndex); @@ -526,45 +467,6 @@ MiRemoveZeroPage(IN ULONG Color) /* Return the page */ return PageIndex; } - - -PMMPFN -NTAPI -MiRemoveHeadList(IN PMMPFNLIST ListHead) -{ - PFN_NUMBER Entry, Flink; - PMMPFN Pfn1; - ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); - ASSERT_LIST_INVARIANT(ListHead); - - /* 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--; - ASSERT_LIST_INVARIANT(ListHead); - - /* Return the head element */ - return Pfn1; -} VOID NTAPI @@ -573,11 +475,10 @@ MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex) PMMPFNLIST ListHead; PFN_NUMBER LastPage; PMMPFN Pfn1; -#if 0 ULONG Color; PMMPFN Blink; PMMCOLOR_TABLES ColorTable; -#endif + /* Make sure the page index is valid */ ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL); ASSERT((PageFrameIndex != 0) && @@ -585,7 +486,7 @@ MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex) (PageFrameIndex >= MmLowestPhysicalPage)); /* Get the PFN entry */ - Pfn1 = MiGetPfnEntry(PageFrameIndex); + Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); /* Sanity checks that a right kind of page is being inserted here */ ASSERT(Pfn1->u4.MustBeCached == 0); @@ -604,7 +505,7 @@ MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex) if (LastPage != LIST_HEAD) { /* Link us with the previous page, so we're at the end now */ - MiGetPfnEntry(LastPage)->u1.Flink = PageFrameIndex; + MI_PFN_ELEMENT(LastPage)->u1.Flink = PageFrameIndex; } else { @@ -643,7 +544,6 @@ MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex) KeSetEvent(MiHighMemoryEvent, 0, FALSE); } -#if 0 // When using ARM3 PFN /* Get the page color */ Color = PageFrameIndex & MmSecondaryColorMask; @@ -652,7 +552,7 @@ MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex) if (ColorTable->Flink == LIST_HEAD) { /* The list is empty, so we are the first page */ - Pfn1->u4.PteFrame = -1; + Pfn1->u4.PteFrame = COLORED_LIST_HEAD; ColorTable->Flink = PageFrameIndex; } else @@ -660,26 +560,151 @@ MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex) /* Get the previous page */ Blink = (PMMPFN)ColorTable->Blink; - /* Make it link to us */ - Pfn1->u4.PteFrame = MI_PFNENTRY_TO_PFN(Blink); + /* Make it link to us, and link back to it */ Blink->OriginalPte.u.Long = PageFrameIndex; + Pfn1->u4.PteFrame = MiGetPfnEntryIndex(Blink); } /* Now initialize our own list pointers */ ColorTable->Blink = Pfn1; + + /* This page is now the last */ Pfn1->OriginalPte.u.Long = LIST_HEAD; /* And increase the count in the colored list */ ColorTable->Count++; + + /* Notify zero page thread if enough pages are on the free list now */ + if ((ListHead->Total >= 8) && !(MmZeroingPageThreadActive)) + { + /* Set the event */ + MmZeroingPageThreadActive = TRUE; + KeSetEvent(&MmZeroingPageEvent, IO_NO_INCREMENT, FALSE); + } + +#if MI_TRACE_PFNS + Pfn1->PfnUsage = MI_USAGE_FREE_PAGE; + RtlZeroMemory(Pfn1->ProcessName, 16); #endif +} + +/* Note: This function is hardcoded only for the zeroed page list, for now */ +VOID +NTAPI +MiInsertPageInList(IN PMMPFNLIST ListHead, + IN PFN_NUMBER PageFrameIndex) +{ + PFN_NUMBER Flink; + PMMPFN Pfn1, Pfn2; + MMLISTS ListName; + PMMCOLOR_TABLES ColorHead; + ULONG Color; + + /* For free pages, use MiInsertPageInFreeList */ + ASSERT(ListHead != &MmFreePageListHead); + + /* Make sure the lock is held */ + ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); - /* Notify zero page thread if enough pages are on the free list now */ - extern KEVENT ZeroPageThreadEvent; - if ((MmFreePageListHead.Total > 8) && !(KeReadStateEvent(&ZeroPageThreadEvent))) + /* Make sure the PFN is valid */ + ASSERT((PageFrameIndex) && + (PageFrameIndex <= MmHighestPhysicalPage) && + (PageFrameIndex >= MmLowestPhysicalPage)); + + /* Page should be unused */ + Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); + ASSERT(Pfn1->u3.e2.ReferenceCount == 0); + ASSERT(Pfn1->u3.e1.Rom != 1); + + /* Only used for zero pages in ReactOS */ + ListName = ListHead->ListName; + ASSERT(ListName == ZeroedPageList); + ListHead->Total++; + + /* Don't handle bad pages yet yet */ + ASSERT(Pfn1->u3.e1.RemovalRequested == 0); + + /* Make the head of the list point to this page now */ + Flink = ListHead->Flink; + ListHead->Flink = PageFrameIndex; + + /* Make the page point to the previous head, and back to the list */ + Pfn1->u1.Flink = Flink; + Pfn1->u2.Blink = LIST_HEAD; + + /* Was the list empty? */ + if (Flink != LIST_HEAD) { - /* This is ReactOS-specific */ - KeSetEvent(&ZeroPageThreadEvent, IO_NO_INCREMENT, FALSE); + /* It wasn't, so update the backlink of the previous head page */ + Pfn2 = MI_PFN_ELEMENT(Flink); + Pfn2->u2.Blink = PageFrameIndex; } + else + { + /* It was empty, so have it loop back around to this new page */ + ListHead->Blink = PageFrameIndex; + } + + /* Move the page onto its new location */ + Pfn1->u3.e1.PageLocation = ListName; + + /* One more page on the system */ + MmAvailablePages++; + + /* Check if we've reached the configured low memory threshold */ + if (MmAvailablePages == MmLowMemoryThreshold) + { + /* Clear the event, because now we're ABOVE the threshold */ + KeClearEvent(MiLowMemoryEvent); + } + else if (MmAvailablePages == MmHighMemoryThreshold) + { + /* Otherwise check if we reached the high threshold and signal the event */ + KeSetEvent(MiHighMemoryEvent, 0, FALSE); + } + + /* Sanity checks */ + ASSERT(ListName == ZeroedPageList); + ASSERT(Pfn1->u4.InPageError == 0); + + /* Get the page color */ + Color = PageFrameIndex & MmSecondaryColorMask; + + /* Get the list for this color */ + ColorHead = &MmFreePagesByColor[ZeroedPageList][Color]; + + /* Get the old head */ + Flink = ColorHead->Flink; + + /* Make this page point back to the list, and point forwards to the old head */ + Pfn1->OriginalPte.u.Long = Flink; + Pfn1->u4.PteFrame = COLORED_LIST_HEAD; + + /* Set the new head */ + ColorHead->Flink = PageFrameIndex; + + /* Was the head empty? */ + if (Flink != LIST_HEAD) + { + /* No, so make the old head point to this page */ + Pfn2 = MI_PFN_ELEMENT(Flink); + Pfn2->u4.PteFrame = PageFrameIndex; + } + else + { + /* Yes, make it loop back to this page */ + ColorHead->Blink = (PVOID)Pfn1; + } + + /* One more paged on the colored list */ + ColorHead->Count++; + +#if MI_TRACE_PFNS + //ASSERT(MI_PFN_CURRENT_USAGE == MI_USAGE_NOT_SET); + Pfn1->PfnUsage = MI_USAGE_FREE_PAGE; + MI_PFN_CURRENT_USAGE = MI_USAGE_NOT_SET; + RtlZeroMemory(Pfn1->ProcessName, 16); +#endif } VOID @@ -694,14 +719,24 @@ MiInitializePfn(IN PFN_NUMBER PageFrameIndex, ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); /* Setup the PTE */ - Pfn1 = MiGetPfnEntry(PageFrameIndex); + Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); Pfn1->PteAddress = PointerPte; /* Check if this PFN is part of a valid address space */ if (PointerPte->u.Hard.Valid == 1) { - /* FIXME: TODO */ - ASSERT(FALSE); + /* Only valid from MmCreateProcessAddressSpace path */ + ASSERT(PsGetCurrentProcess()->Vm.WorkingSetSize == 0); + + /* Make this a demand zero PTE */ + MI_MAKE_SOFTWARE_PTE(&Pfn1->OriginalPte, MM_READWRITE); + } + else + { + /* Copy the PTE data */ + Pfn1->OriginalPte = *PointerPte; + ASSERT(!((Pfn1->OriginalPte.u.Soft.Prototype == 0) && + (Pfn1->OriginalPte.u.Soft.Transition == 1))); } /* Otherwise this is a fresh page -- set it up */ @@ -735,7 +770,7 @@ MiInitializePfn(IN PFN_NUMBER PageFrameIndex, Pfn1->u4.PteFrame = PageFrameIndex; /* Increase its share count so we don't get rid of it */ - Pfn1 = MiGetPfnEntry(PageFrameIndex); + Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); Pfn1->u2.ShareCount++; } @@ -767,7 +802,7 @@ MiAllocatePfn(IN PMMPTE PointerPte, /* Grab a page */ ASSERT_LIST_INVARIANT(&MmFreePageListHead); ASSERT_LIST_INVARIANT(&MmZeroedPageListHead); - PageFrameIndex = MiRemoveAnyPage(0); + PageFrameIndex = MiRemoveAnyPage(MI_GET_NEXT_COLOR()); /* Write the software PTE */ MI_WRITE_INVALID_PTE(PointerPte, TempPte); @@ -789,8 +824,9 @@ MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex) { ASSERT(PageFrameIndex > 0); - ASSERT(MiGetPfnEntry(PageFrameIndex) != NULL); - ASSERT(Pfn1 == MiGetPfnEntry(PageFrameIndex)); + ASSERT(MI_PFN_ELEMENT(PageFrameIndex) != NULL); + ASSERT(Pfn1 == MI_PFN_ELEMENT(PageFrameIndex)); + ASSERT(MI_IS_ROS_PFN(Pfn1) == FALSE); /* Page must be in-use */ if ((Pfn1->u3.e1.PageLocation != ActiveAndValid) && @@ -826,13 +862,7 @@ MiDecrementShareCount(IN PMMPFN Pfn1, /* Clear the last reference */ Pfn1->u3.e2.ReferenceCount = 0; - - /* - * OriginalPte is used by AweReferenceCount in ReactOS, but either - * ways we shouldn't be seeing RMAP entries at this point - */ ASSERT(Pfn1->OriginalPte.u.Soft.Prototype == 0); - ASSERT(Pfn1->OriginalPte.u.Long == 0); /* Mark the page temporarily as valid, we're going to make it free soon */ Pfn1->u3.e1.PageLocation = ActiveAndValid; @@ -848,6 +878,49 @@ MiDecrementShareCount(IN PMMPFN Pfn1, } } +VOID +NTAPI +MiDecrementReferenceCount(IN PMMPFN Pfn1, + IN PFN_NUMBER PageFrameIndex) +{ + /* PFN lock must be held */ + ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); + + /* Sanity checks on the page */ + ASSERT(PageFrameIndex < MmHighestPhysicalPage); + ASSERT(Pfn1 == MI_PFN_ELEMENT(PageFrameIndex)); + ASSERT(Pfn1->u3.e2.ReferenceCount != 0); + + /* Dereference the page, bail out if it's still alive */ + InterlockedDecrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount); + if (Pfn1->u3.e2.ReferenceCount) return; + + /* Nobody should still have reference to this page */ + if (Pfn1->u2.ShareCount != 0) + { + /* Otherwise something's really wrong */ + KeBugCheckEx(PFN_LIST_CORRUPT, 7, PageFrameIndex, Pfn1->u2.ShareCount, 0); + } + + /* And it should be lying on some page list */ + ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid); + + /* Did someone set the delete flag? */ + if (MI_IS_PFN_DELETED(Pfn1)) + { + /* Insert it into the free list, there's nothing left to do */ + MiInsertPageInFreeList(PageFrameIndex); + return; + } + + /* We don't have a modified list yet */ + ASSERT(Pfn1->u3.e1.Modified == 0); + ASSERT(Pfn1->u3.e1.RemovalRequested == 0); + + /* FIXME: Normally it would go on the standby list, but we're pushing it on the free list */ + MiInsertPageInFreeList(PageFrameIndex); +} + VOID NTAPI MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex, @@ -857,13 +930,11 @@ MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex, PMMPFN Pfn1; /* Setup the PTE */ - Pfn1 = MiGetPfnEntry(PageFrameIndex); + Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); Pfn1->PteAddress = PointerPte; - -#if 0 // When using ARM3 PFN + /* Make this a software PTE */ MI_MAKE_SOFTWARE_PTE(&Pfn1->OriginalPte, MM_READWRITE); -#endif /* Setup the page */ ASSERT(Pfn1->u3.e2.ReferenceCount == 0); @@ -880,7 +951,7 @@ MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex, Pfn1->u4.PteFrame = PteFrame; /* Increase its share count so we don't get rid of it */ - Pfn1 = MiGetPfnEntry(PteFrame); + Pfn1 = MI_PFN_ELEMENT(PteFrame); Pfn1->u2.ShareCount++; } }