mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 19:05:52 +00:00
[NTOS]: Remove many hacks in freelist.c regarding the differences between PHYSICAL_PAGE and MMPFN. ReferenceCount field is now accessed directly. LockCount is gone. Type is gone: if a page is used, it has a consumer and is in the ActiveAndValid state, if it's free, it's on the free or zero page list. Get rid of Zero, if a page is zeroed, it is on the zero page list.
[NTOS]: These changes will allow a smoother migration to MMPFN later on. svn path=/trunk/; revision=45577
This commit is contained in:
parent
27494e478b
commit
7872be6071
2 changed files with 97 additions and 220 deletions
|
@ -232,6 +232,8 @@ MiIsBalancerThread(VOID)
|
||||||
PsGetCurrentThread() == MiBalancerThreadId.UniqueThread;
|
PsGetCurrentThread() == MiBalancerThreadId.UniqueThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID NTAPI MiSetConsumer(IN PFN_TYPE Pfn, IN ULONG Consumer);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
|
MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
|
||||||
|
@ -316,8 +318,8 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
|
||||||
{
|
{
|
||||||
KeBugCheck(NO_PAGES_AVAILABLE);
|
KeBugCheck(NO_PAGES_AVAILABLE);
|
||||||
}
|
}
|
||||||
/* Update the Consumer */
|
/* Update the Consumer and make the page active */
|
||||||
MiGetPfnEntry(Page)->u3.e1.PageLocation = Consumer;
|
MiSetConsumer(Page, Consumer);
|
||||||
if(Consumer == MC_USER) MmInsertLRULastUserPage(Page);
|
if(Consumer == MC_USER) MmInsertLRULastUserPage(Page);
|
||||||
*AllocatedPage = Page;
|
*AllocatedPage = Page;
|
||||||
(void)InterlockedDecrementUL(&MiPagesRequired);
|
(void)InterlockedDecrementUL(&MiPagesRequired);
|
||||||
|
|
|
@ -21,11 +21,6 @@
|
||||||
#define MODULE_INVOLVED_IN_ARM3
|
#define MODULE_INVOLVED_IN_ARM3
|
||||||
#include "ARM3/miarm.h"
|
#include "ARM3/miarm.h"
|
||||||
|
|
||||||
/* TYPES *******************************************************************/
|
|
||||||
|
|
||||||
#define MM_PHYSICAL_PAGE_FREE (0x1)
|
|
||||||
#define MM_PHYSICAL_PAGE_USED (0x2)
|
|
||||||
|
|
||||||
/* GLOBALS ****************************************************************/
|
/* GLOBALS ****************************************************************/
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -34,14 +29,9 @@
|
||||||
//
|
//
|
||||||
// REACTOS NT
|
// REACTOS NT
|
||||||
//
|
//
|
||||||
#define Consumer PageLocation
|
#define Consumer u3.e1.PageColor
|
||||||
#define Type CacheAttribute
|
|
||||||
#define Zero PrototypePte
|
|
||||||
#define LockCount u3.e1.PageColor
|
|
||||||
#define RmapListHead AweReferenceCount
|
#define RmapListHead AweReferenceCount
|
||||||
#define SavedSwapEntry u4.EntireFrame
|
#define SavedSwapEntry u4.EntireFrame
|
||||||
#define Flags u3.e1
|
|
||||||
#define ReferenceCount u3.ReferenceCount
|
|
||||||
#define RemoveEntryList(x) RemoveEntryList((PLIST_ENTRY)x)
|
#define RemoveEntryList(x) RemoveEntryList((PLIST_ENTRY)x)
|
||||||
#define InsertTailList(x, y) InsertTailList(x, (PLIST_ENTRY)y)
|
#define InsertTailList(x, y) InsertTailList(x, (PLIST_ENTRY)y)
|
||||||
#define ListEntry u1
|
#define ListEntry u1
|
||||||
|
@ -100,7 +90,6 @@ MmGetLRUFirstUserPage(VOID)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
PageDescriptor = CONTAINING_RECORD(NextListEntry, PHYSICAL_PAGE, ListEntry);
|
PageDescriptor = CONTAINING_RECORD(NextListEntry, PHYSICAL_PAGE, ListEntry);
|
||||||
ASSERT_PFN(PageDescriptor);
|
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
|
||||||
return PageDescriptor - MmPfnDatabase[0];
|
return PageDescriptor - MmPfnDatabase[0];
|
||||||
}
|
}
|
||||||
|
@ -114,9 +103,9 @@ MmInsertLRULastUserPage(PFN_TYPE Pfn)
|
||||||
|
|
||||||
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
Page = MiGetPfnEntry(Pfn);
|
Page = MiGetPfnEntry(Pfn);
|
||||||
ASSERT(Page);
|
// if (!Page->Consumer != MC_USER) DPRINT1("Page Consumer: %d\n", Page->Consumer);
|
||||||
ASSERT(Page->Flags.Type == MM_PHYSICAL_PAGE_USED);
|
ASSERT(Page->Consumer == MC_USER);
|
||||||
ASSERT(Page->Flags.Consumer == MC_USER);
|
ASSERT(Page->u3.e1.PageLocation = ActiveAndValid);
|
||||||
InsertTailList(&UserPageListHead, &Page->ListEntry);
|
InsertTailList(&UserPageListHead, &Page->ListEntry);
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
|
||||||
}
|
}
|
||||||
|
@ -132,9 +121,8 @@ MmGetLRUNextUserPage(PFN_TYPE PreviousPfn)
|
||||||
|
|
||||||
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
Page = MiGetPfnEntry(PreviousPfn);
|
Page = MiGetPfnEntry(PreviousPfn);
|
||||||
ASSERT(Page);
|
ASSERT(Page->Consumer == MC_USER);
|
||||||
ASSERT(Page->Flags.Type == MM_PHYSICAL_PAGE_USED);
|
ASSERT(Page->u3.e1.PageLocation = ActiveAndValid);
|
||||||
ASSERT(Page->Flags.Consumer == MC_USER);
|
|
||||||
NextListEntry = (PLIST_ENTRY)Page->ListEntry.Flink;
|
NextListEntry = (PLIST_ENTRY)Page->ListEntry.Flink;
|
||||||
if (NextListEntry == &UserPageListHead)
|
if (NextListEntry == &UserPageListHead)
|
||||||
{
|
{
|
||||||
|
@ -153,6 +141,14 @@ MmRemoveLRUUserPage(PFN_TYPE Page)
|
||||||
RemoveEntryList(&MiGetPfnEntry(Page)->ListEntry);
|
RemoveEntryList(&MiGetPfnEntry(Page)->ListEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
MiIsPfnInUse(IN PMMPFN Pfn1)
|
||||||
|
{
|
||||||
|
return ((Pfn1->u3.e1.PageLocation != FreePageList) &&
|
||||||
|
(Pfn1->u3.e1.PageLocation != ZeroedPageList));
|
||||||
|
}
|
||||||
|
|
||||||
PFN_NUMBER
|
PFN_NUMBER
|
||||||
NTAPI
|
NTAPI
|
||||||
MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
|
MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
|
||||||
|
@ -209,7 +205,7 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
|
||||||
//
|
//
|
||||||
// If this PFN is in use, ignore it
|
// If this PFN is in use, ignore it
|
||||||
//
|
//
|
||||||
if (Pfn1->Flags.Type != MM_PHYSICAL_PAGE_FREE) continue;
|
if (MiIsPfnInUse(Pfn1)) continue;
|
||||||
|
|
||||||
//
|
//
|
||||||
// If we haven't chosen a start PFN yet and the caller specified an
|
// If we haven't chosen a start PFN yet and the caller specified an
|
||||||
|
@ -244,7 +240,7 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
|
||||||
//
|
//
|
||||||
// Things might've changed for us. Is the page still free?
|
// Things might've changed for us. Is the page still free?
|
||||||
//
|
//
|
||||||
if (Pfn1->Flags.Type != MM_PHYSICAL_PAGE_FREE) break;
|
if (MiIsPfnInUse(Pfn1)) break;
|
||||||
|
|
||||||
//
|
//
|
||||||
// So far so good. Is this the last confirmed valid page?
|
// So far so good. Is this the last confirmed valid page?
|
||||||
|
@ -265,7 +261,7 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
|
||||||
//
|
//
|
||||||
// If this was an unzeroed page, there are now less
|
// If this was an unzeroed page, there are now less
|
||||||
//
|
//
|
||||||
if (Pfn1->Flags.Zero == 0) UnzeroedPageCount--;
|
if (Pfn1->u3.e1.PageLocation == ZeroedPageList) UnzeroedPageCount--;
|
||||||
|
|
||||||
//
|
//
|
||||||
// One less free page
|
// One less free page
|
||||||
|
@ -276,22 +272,25 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
|
||||||
// This PFN is now a used page, set it up
|
// This PFN is now a used page, set it up
|
||||||
//
|
//
|
||||||
RemoveEntryList(&Pfn1->ListEntry);
|
RemoveEntryList(&Pfn1->ListEntry);
|
||||||
Pfn1->Flags.Type = MM_PHYSICAL_PAGE_USED;
|
Pfn1->Consumer = MC_NPPOOL;
|
||||||
Pfn1->Flags.Consumer = MC_NPPOOL;
|
Pfn1->u3.e2.ReferenceCount = 1;
|
||||||
Pfn1->ReferenceCount = 1;
|
|
||||||
Pfn1->LockCount = 0;
|
|
||||||
Pfn1->SavedSwapEntry = 0;
|
Pfn1->SavedSwapEntry = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if it was already zeroed
|
// Check if it was already zeroed
|
||||||
//
|
//
|
||||||
if (Pfn1->Flags.Zero == 0)
|
if (Pfn1->u3.e1.PageLocation != ZeroedPageList)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// It wasn't, so zero it
|
// It wasn't, so zero it
|
||||||
//
|
//
|
||||||
MiZeroPage(MiGetPfnEntryIndex(Pfn1));
|
MiZeroPage(MiGetPfnEntryIndex(Pfn1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Mark it in use
|
||||||
|
//
|
||||||
|
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this is the last PFN, otherwise go on
|
// Check if this is the last PFN, otherwise go on
|
||||||
|
@ -303,8 +302,8 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn,
|
||||||
//
|
//
|
||||||
// Mark the first and last PFN so we can find them later
|
// Mark the first and last PFN so we can find them later
|
||||||
//
|
//
|
||||||
Pfn1->Flags.StartOfAllocation = 1;
|
Pfn1->u3.e1.StartOfAllocation = 1;
|
||||||
(Pfn1 + SizeInPages - 1)->Flags.EndOfAllocation = 1;
|
(Pfn1 + SizeInPages - 1)->u3.e1.EndOfAllocation = 1;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now it's safe to let go of the PFN lock
|
// Now it's safe to let go of the PFN lock
|
||||||
|
@ -466,18 +465,17 @@ MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress,
|
||||||
//
|
//
|
||||||
// Make sure it's really free
|
// Make sure it's really free
|
||||||
//
|
//
|
||||||
ASSERT(Pfn1->Flags.Type == MM_PHYSICAL_PAGE_FREE);
|
ASSERT(MiIsPfnInUse(Pfn1) == FALSE);
|
||||||
ASSERT(Pfn1->ReferenceCount == 0);
|
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Allocate it and mark it
|
// Allocate it and mark it
|
||||||
//
|
//
|
||||||
Pfn1->Flags.Type = MM_PHYSICAL_PAGE_USED;
|
Pfn1->Consumer = MC_NPPOOL;
|
||||||
Pfn1->Flags.Consumer = MC_NPPOOL;
|
Pfn1->u3.e1.StartOfAllocation = 1;
|
||||||
Pfn1->Flags.StartOfAllocation = 1;
|
Pfn1->u3.e1.EndOfAllocation = 1;
|
||||||
Pfn1->Flags.EndOfAllocation = 1;
|
Pfn1->u3.e2.ReferenceCount = 1;
|
||||||
Pfn1->ReferenceCount = 1;
|
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
||||||
Pfn1->LockCount = 0;
|
|
||||||
Pfn1->SavedSwapEntry = 0;
|
Pfn1->SavedSwapEntry = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -513,29 +511,27 @@ MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress,
|
||||||
//
|
//
|
||||||
// Make sure it's free and if this is our first pass, zeroed
|
// Make sure it's free and if this is our first pass, zeroed
|
||||||
//
|
//
|
||||||
if (Pfn1->Flags.Type != MM_PHYSICAL_PAGE_FREE) continue;
|
if (!MiIsPfnInUse(Pfn1)) continue;
|
||||||
if (Pfn1->Flags.Zero != LookForZeroedPages) continue;
|
if ((Pfn1->u3.e1.PageLocation == ZeroedPageList) != LookForZeroedPages) continue;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
//
|
//
|
||||||
ASSERT(Pfn1->ReferenceCount == 0);
|
ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now setup the page and mark it
|
// Now setup the page and mark it
|
||||||
//
|
//
|
||||||
Pfn1->Flags.Type = MM_PHYSICAL_PAGE_USED;
|
Pfn1->Consumer = MC_NPPOOL;
|
||||||
Pfn1->Flags.Consumer = MC_NPPOOL;
|
Pfn1->u3.e2.ReferenceCount = 1;
|
||||||
Pfn1->ReferenceCount = 1;
|
Pfn1->u3.e1.StartOfAllocation = 1;
|
||||||
Pfn1->Flags.StartOfAllocation = 1;
|
Pfn1->u3.e1.EndOfAllocation = 1;
|
||||||
Pfn1->Flags.EndOfAllocation = 1;
|
|
||||||
Pfn1->LockCount = 0;
|
|
||||||
Pfn1->SavedSwapEntry = 0;
|
Pfn1->SavedSwapEntry = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// If this page was unzeroed, we've consumed such a page
|
// If this page was unzeroed, we've consumed such a page
|
||||||
//
|
//
|
||||||
if (!Pfn1->Flags.Zero) UnzeroedPageCount--;
|
if (Pfn1->u3.e1.PageLocation != ZeroedPageList) UnzeroedPageCount--;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Decrease available pages
|
// Decrease available pages
|
||||||
|
@ -603,7 +599,8 @@ MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress,
|
||||||
//
|
//
|
||||||
Pfn1 = MiGetPfnEntry(Page);
|
Pfn1 = MiGetPfnEntry(Page);
|
||||||
ASSERT(Pfn1);
|
ASSERT(Pfn1);
|
||||||
if (Pfn1->Flags.Zero == 0) MiZeroPage(Page);
|
if (Pfn1->u3.e1.PageLocation != ZeroedPageList) MiZeroPage(Page);
|
||||||
|
Pfn1->u3.e1.PageLocation = ActiveAndValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -620,7 +617,7 @@ MmDumpPfnDatabase(VOID)
|
||||||
{
|
{
|
||||||
ULONG i;
|
ULONG i;
|
||||||
PPHYSICAL_PAGE Pfn1;
|
PPHYSICAL_PAGE Pfn1;
|
||||||
PCHAR State = "????", Consumer = "Unknown";
|
PCHAR State = "????", Type = "Unknown";
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
ULONG Totals[5] = {0}, FreePages = 0;
|
ULONG Totals[5] = {0}, FreePages = 0;
|
||||||
|
|
||||||
|
@ -637,67 +634,63 @@ MmDumpPfnDatabase(VOID)
|
||||||
//
|
//
|
||||||
// Get the consumer
|
// Get the consumer
|
||||||
//
|
//
|
||||||
switch (Pfn1->Flags.Consumer)
|
switch (Pfn1->Consumer)
|
||||||
{
|
{
|
||||||
case MC_NPPOOL:
|
case MC_NPPOOL:
|
||||||
|
|
||||||
Consumer = "Nonpaged Pool";
|
Type = "Nonpaged Pool";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MC_PPOOL:
|
case MC_PPOOL:
|
||||||
|
|
||||||
Consumer = "Paged Pool";
|
Type = "Paged Pool";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MC_CACHE:
|
case MC_CACHE:
|
||||||
|
|
||||||
Consumer = "File System Cache";
|
Type = "File System Cache";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MC_USER:
|
case MC_USER:
|
||||||
|
|
||||||
Consumer = "Process Working Set";
|
Type = "Process Working Set";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MC_SYSTEM:
|
case MC_SYSTEM:
|
||||||
|
|
||||||
Consumer = "System";
|
Type = "System";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the type
|
// Get the type
|
||||||
//
|
//
|
||||||
switch (Pfn1->Flags.Type)
|
if (MiIsPfnInUse(Pfn1))
|
||||||
{
|
{
|
||||||
case MM_PHYSICAL_PAGE_USED:
|
State = "Used";
|
||||||
|
Totals[Pfn1->Consumer]++;
|
||||||
State = "Used";
|
|
||||||
Totals[Pfn1->Flags.Consumer]++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MM_PHYSICAL_PAGE_FREE:
|
|
||||||
|
|
||||||
State = "Free";
|
|
||||||
Consumer = "Free";
|
|
||||||
FreePages++;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
State = "Free";
|
||||||
|
Type = "Free";
|
||||||
|
FreePages++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Pretty-print the page
|
// Pretty-print the page
|
||||||
//
|
//
|
||||||
DbgPrint("0x%08p:\t%04s\t%20s\t(%02d.%02d) [%08p])\n",
|
DbgPrint("0x%08p:\t%04s\t%20s\t(%02d) [%08p])\n",
|
||||||
i << PAGE_SHIFT,
|
i << PAGE_SHIFT,
|
||||||
State,
|
State,
|
||||||
Consumer,
|
Type,
|
||||||
Pfn1->ReferenceCount,
|
Pfn1->u3.e2.ReferenceCount,
|
||||||
Pfn1->LockCount,
|
|
||||||
Pfn1->RmapListHead);
|
Pfn1->RmapListHead);
|
||||||
}
|
}
|
||||||
|
|
||||||
DbgPrint("Nonpaged Pool: %d pages\t[%d KB]\n", Totals[MC_NPPOOL], (Totals[MC_NPPOOL] << PAGE_SHIFT) / 1024);
|
DbgPrint("Nonpaged Pool: %d pages\t[%d KB]\n", Totals[MC_NPPOOL], (Totals[MC_NPPOOL] << PAGE_SHIFT) / 1024);
|
||||||
DbgPrint("Paged Pool: %d pages\t[%d KB]\n", Totals[MC_PPOOL], (Totals[MC_PPOOL] << PAGE_SHIFT) / 1024);
|
DbgPrint("Paged Pool: %d pages\t[%d KB]\n", Totals[MC_PPOOL], (Totals[MC_PPOOL] << PAGE_SHIFT) / 1024);
|
||||||
DbgPrint("File System Cache: %d pages\t[%d KB]\n", Totals[MC_CACHE], (Totals[MC_CACHE] << PAGE_SHIFT) / 1024);
|
DbgPrint("File System Cache: %d pages\t[%d KB]\n", Totals[MC_CACHE], (Totals[MC_CACHE] << PAGE_SHIFT) / 1024);
|
||||||
DbgPrint("Process Working Set: %d pages\t[%d KB]\n", Totals[MC_USER], (Totals[MC_USER] << PAGE_SHIFT) / 1024);
|
DbgPrint("Process Working Set: %d pages\t[%d KB]\n", Totals[MC_USER], (Totals[MC_USER] << PAGE_SHIFT) / 1024);
|
||||||
DbgPrint("System: %d pages\t[%d KB]\n", Totals[MC_SYSTEM], (Totals[MC_SYSTEM] << PAGE_SHIFT) / 1024);
|
DbgPrint("System: %d pages\t[%d KB]\n", Totals[MC_SYSTEM], (Totals[MC_SYSTEM] << PAGE_SHIFT) / 1024);
|
||||||
|
@ -723,9 +716,9 @@ MmInitializePageList(VOID)
|
||||||
|
|
||||||
/* This is what a used page looks like */
|
/* This is what a used page looks like */
|
||||||
RtlZeroMemory(&UsedPage, sizeof(UsedPage));
|
RtlZeroMemory(&UsedPage, sizeof(UsedPage));
|
||||||
UsedPage.Flags.Type = MM_PHYSICAL_PAGE_USED;
|
UsedPage.Consumer = MC_NPPOOL;
|
||||||
UsedPage.Flags.Consumer = MC_NPPOOL;
|
UsedPage.u3.e1.PageLocation = ActiveAndValid;
|
||||||
UsedPage.ReferenceCount = 1;
|
UsedPage.u3.e2.ReferenceCount = 1;
|
||||||
|
|
||||||
/* Loop the memory descriptors */
|
/* Loop the memory descriptors */
|
||||||
for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
|
for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
|
||||||
|
@ -759,7 +752,7 @@ MmInitializePageList(VOID)
|
||||||
for (i = 0; i < Md->PageCount; i++)
|
for (i = 0; i < Md->PageCount; i++)
|
||||||
{
|
{
|
||||||
/* Mark it as a free page */
|
/* Mark it as a free page */
|
||||||
MmPfnDatabase[0][Md->BasePage + i].Flags.Type = MM_PHYSICAL_PAGE_FREE;
|
MmPfnDatabase[0][Md->BasePage + i].u3.e1.PageLocation = FreePageList;
|
||||||
InsertTailList(&FreeUnzeroedPageListHead,
|
InsertTailList(&FreeUnzeroedPageListHead,
|
||||||
&MmPfnDatabase[0][Md->BasePage + i].ListEntry);
|
&MmPfnDatabase[0][Md->BasePage + i].ListEntry);
|
||||||
UnzeroedPageCount++;
|
UnzeroedPageCount++;
|
||||||
|
@ -782,7 +775,7 @@ MmInitializePageList(VOID)
|
||||||
for (i = MxOldFreeDescriptor.BasePage; i < MxFreeDescriptor->BasePage; i++)
|
for (i = MxOldFreeDescriptor.BasePage; i < MxFreeDescriptor->BasePage; i++)
|
||||||
{
|
{
|
||||||
/* Ensure this page was not added previously */
|
/* Ensure this page was not added previously */
|
||||||
ASSERT(MmPfnDatabase[0][i].Flags.Type == 0);
|
ASSERT(MmPfnDatabase[0][i].Consumer == 0);
|
||||||
|
|
||||||
/* Mark it as used kernel memory */
|
/* Mark it as used kernel memory */
|
||||||
MmPfnDatabase[0][i] = UsedPage;
|
MmPfnDatabase[0][i] = UsedPage;
|
||||||
|
@ -859,13 +852,8 @@ MmReferencePage(PFN_TYPE Pfn)
|
||||||
|
|
||||||
Page = MiGetPfnEntry(Pfn);
|
Page = MiGetPfnEntry(Pfn);
|
||||||
ASSERT(Page);
|
ASSERT(Page);
|
||||||
if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED)
|
|
||||||
{
|
|
||||||
DPRINT1("Referencing non-used page\n");
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
Page->ReferenceCount++;
|
Page->u3.e2.ReferenceCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
|
@ -881,13 +869,8 @@ MmGetReferenceCountPage(PFN_TYPE Pfn)
|
||||||
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
Page = MiGetPfnEntry(Pfn);
|
Page = MiGetPfnEntry(Pfn);
|
||||||
ASSERT(Page);
|
ASSERT(Page);
|
||||||
if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED)
|
|
||||||
{
|
|
||||||
DPRINT1("Getting reference count for free page\n");
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
RCount = Page->ReferenceCount;
|
RCount = Page->u3.e2.ReferenceCount;
|
||||||
|
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
|
||||||
return(RCount);
|
return(RCount);
|
||||||
|
@ -897,10 +880,16 @@ BOOLEAN
|
||||||
NTAPI
|
NTAPI
|
||||||
MmIsPageInUse(PFN_TYPE Pfn)
|
MmIsPageInUse(PFN_TYPE Pfn)
|
||||||
{
|
{
|
||||||
|
return MiIsPfnInUse(MiGetPfnEntry(Pfn));
|
||||||
|
}
|
||||||
|
|
||||||
DPRINT("MmIsPageInUse(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
|
VOID
|
||||||
|
NTAPI
|
||||||
return (MiGetPfnEntry(Pfn)->Flags.Type == MM_PHYSICAL_PAGE_USED);
|
MiSetConsumer(IN PFN_TYPE Pfn,
|
||||||
|
IN ULONG Type)
|
||||||
|
{
|
||||||
|
MiGetPfnEntry(Pfn)->Consumer = Type;
|
||||||
|
MiGetPfnEntry(Pfn)->u3.e1.PageLocation = ActiveAndValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -914,45 +903,12 @@ MmDereferencePage(PFN_TYPE Pfn)
|
||||||
Page = MiGetPfnEntry(Pfn);
|
Page = MiGetPfnEntry(Pfn);
|
||||||
ASSERT(Page);
|
ASSERT(Page);
|
||||||
|
|
||||||
if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED)
|
Page->u3.e2.ReferenceCount--;
|
||||||
{
|
if (Page->u3.e2.ReferenceCount == 0)
|
||||||
DPRINT1("Dereferencing free page\n");
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
if (Page->ReferenceCount == 0)
|
|
||||||
{
|
|
||||||
DPRINT1("Derefrencing page with reference count 0\n");
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
Page->ReferenceCount--;
|
|
||||||
if (Page->ReferenceCount == 0)
|
|
||||||
{
|
{
|
||||||
MmAvailablePages++;
|
MmAvailablePages++;
|
||||||
if (Page->Flags.Consumer == MC_USER) RemoveEntryList(&Page->ListEntry);
|
if (Page->Consumer == MC_USER) RemoveEntryList(&Page->ListEntry);
|
||||||
if (Page->RmapListHead != (LONG)NULL)
|
Page->u3.e1.PageLocation = FreePageList;
|
||||||
{
|
|
||||||
DPRINT1("Freeing page with rmap entries.\n");
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
if (Page->LockCount > 0)
|
|
||||||
{
|
|
||||||
DPRINT1("Freeing locked page\n");
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
if (Page->SavedSwapEntry != 0)
|
|
||||||
{
|
|
||||||
DPRINT1("Freeing page with swap entry.\n");
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED)
|
|
||||||
{
|
|
||||||
DPRINT1("Freeing page with flags %x\n",
|
|
||||||
Page->Flags.Type);
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
Page->Flags.Type = MM_PHYSICAL_PAGE_FREE;
|
|
||||||
Page->Flags.Consumer = MC_MAXIMUM;
|
|
||||||
InsertTailList(&FreeUnzeroedPageListHead,
|
InsertTailList(&FreeUnzeroedPageListHead,
|
||||||
&Page->ListEntry);
|
&Page->ListEntry);
|
||||||
UnzeroedPageCount++;
|
UnzeroedPageCount++;
|
||||||
|
@ -963,73 +919,9 @@ MmDereferencePage(PFN_TYPE Pfn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG
|
|
||||||
NTAPI
|
|
||||||
MmGetLockCountPage(PFN_TYPE Pfn)
|
|
||||||
{
|
|
||||||
KIRQL oldIrql;
|
|
||||||
ULONG CurrentLockCount;
|
|
||||||
PPHYSICAL_PAGE Page;
|
|
||||||
|
|
||||||
DPRINT("MmGetLockCountPage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
|
|
||||||
|
|
||||||
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
|
||||||
|
|
||||||
Page = MiGetPfnEntry(Pfn);
|
|
||||||
ASSERT(Page);
|
|
||||||
if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED)
|
|
||||||
{
|
|
||||||
DPRINT1("Getting lock count for free page\n");
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
CurrentLockCount = Page->LockCount;
|
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
|
|
||||||
|
|
||||||
return(CurrentLockCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
MmLockPage(PFN_TYPE Pfn)
|
|
||||||
{
|
|
||||||
PPHYSICAL_PAGE Page;
|
|
||||||
|
|
||||||
DPRINT("MmLockPage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
|
|
||||||
|
|
||||||
Page = MiGetPfnEntry(Pfn);
|
|
||||||
ASSERT(Page);
|
|
||||||
if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED)
|
|
||||||
{
|
|
||||||
DPRINT1("Locking free page\n");
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
Page->LockCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
MmUnlockPage(PFN_TYPE Pfn)
|
|
||||||
{
|
|
||||||
PPHYSICAL_PAGE Page;
|
|
||||||
|
|
||||||
DPRINT("MmUnlockPage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
|
|
||||||
|
|
||||||
Page = MiGetPfnEntry(Pfn);
|
|
||||||
ASSERT(Page);
|
|
||||||
if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED)
|
|
||||||
{
|
|
||||||
DPRINT1("Unlocking free page\n");
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
Page->LockCount--;
|
|
||||||
}
|
|
||||||
|
|
||||||
PFN_TYPE
|
PFN_TYPE
|
||||||
NTAPI
|
NTAPI
|
||||||
MmAllocPage(ULONG Consumer, SWAPENTRY SwapEntry)
|
MmAllocPage(ULONG Type, SWAPENTRY SwapEntry)
|
||||||
{
|
{
|
||||||
PFN_TYPE PfnOffset;
|
PFN_TYPE PfnOffset;
|
||||||
PLIST_ENTRY ListEntry;
|
PLIST_ENTRY ListEntry;
|
||||||
|
@ -1065,29 +957,19 @@ MmAllocPage(ULONG Consumer, SWAPENTRY SwapEntry)
|
||||||
PageDescriptor = CONTAINING_RECORD(ListEntry, PHYSICAL_PAGE, ListEntry);
|
PageDescriptor = CONTAINING_RECORD(ListEntry, PHYSICAL_PAGE, ListEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PageDescriptor->Flags.Type != MM_PHYSICAL_PAGE_FREE)
|
PageDescriptor->Consumer = Type;
|
||||||
{
|
PageDescriptor->u3.e2.ReferenceCount = 1;
|
||||||
DPRINT1("Got non-free page from freelist\n");
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
if (PageDescriptor->ReferenceCount != 0)
|
|
||||||
{
|
|
||||||
DPRINT1("%d\n", PageDescriptor->ReferenceCount);
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
PageDescriptor->Flags.Type = MM_PHYSICAL_PAGE_USED;
|
|
||||||
PageDescriptor->Flags.Consumer = Consumer;
|
|
||||||
PageDescriptor->ReferenceCount = 1;
|
|
||||||
PageDescriptor->LockCount = 0;
|
|
||||||
PageDescriptor->SavedSwapEntry = SwapEntry;
|
PageDescriptor->SavedSwapEntry = SwapEntry;
|
||||||
|
|
||||||
MmAvailablePages--;
|
MmAvailablePages--;
|
||||||
|
|
||||||
PfnOffset = PageDescriptor - MmPfnDatabase[0];
|
PfnOffset = PageDescriptor - MmPfnDatabase[0];
|
||||||
if ((NeedClear) && (Consumer != MC_SYSTEM))
|
if ((NeedClear) && (Type != MC_SYSTEM))
|
||||||
{
|
{
|
||||||
MiZeroPage(PfnOffset);
|
MiZeroPage(PfnOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PageDescriptor->u3.e1.PageLocation = ActiveAndValid;
|
||||||
return PfnOffset;
|
return PfnOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1135,11 +1017,6 @@ MmZeroPageThreadMain(PVOID Ignored)
|
||||||
KernelMode,
|
KernelMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
NULL);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("ZeroPageThread: Wait failed\n");
|
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ZeroPageThreadShouldTerminate)
|
if (ZeroPageThreadShouldTerminate)
|
||||||
{
|
{
|
||||||
|
@ -1154,14 +1031,12 @@ MmZeroPageThreadMain(PVOID Ignored)
|
||||||
UnzeroedPageCount--;
|
UnzeroedPageCount--;
|
||||||
PageDescriptor = CONTAINING_RECORD(ListEntry, PHYSICAL_PAGE, ListEntry);
|
PageDescriptor = CONTAINING_RECORD(ListEntry, PHYSICAL_PAGE, ListEntry);
|
||||||
/* We set the page to used, because MmCreateVirtualMapping failed with unused pages */
|
/* We set the page to used, because MmCreateVirtualMapping failed with unused pages */
|
||||||
PageDescriptor->Flags.Type = MM_PHYSICAL_PAGE_USED;
|
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
|
||||||
Pfn = PageDescriptor - MmPfnDatabase[0];
|
Pfn = PageDescriptor - MmPfnDatabase[0];
|
||||||
Status = MiZeroPage(Pfn);
|
Status = MiZeroPage(Pfn);
|
||||||
|
|
||||||
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
PageDescriptor->Flags.Zero = 1;
|
PageDescriptor->u3.e1.PageLocation = ZeroedPageList;
|
||||||
PageDescriptor->Flags.Type = MM_PHYSICAL_PAGE_FREE;
|
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
InsertHeadList(&FreeZeroedPageListHead, ListEntry);
|
InsertHeadList(&FreeZeroedPageListHead, ListEntry);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue