mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
Revert "[NTOS/MM]
- Fix PFNs tracing
- Add private pages to the process working set"
This reverts commit 4c5351bf55
.
Not ready for prime time
This commit is contained in:
parent
7b3faadaf5
commit
1c528cbf84
13 changed files with 88 additions and 364 deletions
|
@ -665,6 +665,7 @@ CcRosMapVacbInKernelSpace(
|
|||
{
|
||||
PFN_NUMBER PageFrameNumber;
|
||||
|
||||
MI_SET_USAGE(MI_USAGE_CACHE);
|
||||
Status = MmRequestPageMemoryConsumer(MC_CACHE, TRUE, &PageFrameNumber);
|
||||
if (PageFrameNumber == 0)
|
||||
{
|
||||
|
@ -906,6 +907,25 @@ Retry:
|
|||
InsertTailList(&VacbLruListHead, ¤t->VacbLruListEntry);
|
||||
KeReleaseQueuedSpinLock(LockQueueMasterLock, oldIrql);
|
||||
|
||||
MI_SET_USAGE(MI_USAGE_CACHE);
|
||||
#if MI_TRACE_PFNS
|
||||
if ((SharedCacheMap->FileObject) && (SharedCacheMap->FileObject->FileName.Buffer))
|
||||
{
|
||||
PWCHAR pos;
|
||||
ULONG len = 0;
|
||||
pos = wcsrchr(SharedCacheMap->FileObject->FileName.Buffer, '\\');
|
||||
if (pos)
|
||||
{
|
||||
len = wcslen(pos) * sizeof(WCHAR);
|
||||
snprintf(MI_PFN_CURRENT_PROCESS_NAME, min(16, len), "%S", pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(MI_PFN_CURRENT_PROCESS_NAME, min(16, len), "%wZ", &SharedCacheMap->FileObject->FileName);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Reference it to allow release */
|
||||
CcRosVacbIncRefCount(current);
|
||||
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
#include <internal/arch/mm.h>
|
||||
|
||||
#define MI_TRACE_PFNS 1
|
||||
|
||||
/* TYPES *********************************************************************/
|
||||
|
||||
struct _EPROCESS;
|
||||
|
@ -250,45 +248,9 @@ MM_RMAP_ENTRY, *PMM_RMAP_ENTRY;
|
|||
extern ULONG MI_PFN_CURRENT_USAGE;
|
||||
extern CHAR MI_PFN_CURRENT_PROCESS_NAME[16];
|
||||
#define MI_SET_USAGE(x) MI_PFN_CURRENT_USAGE = x
|
||||
#define MI_SET_PROCESS2(x) memcpy(MI_PFN_CURRENT_PROCESS_NAME, x, min(sizeof(x), sizeof(MI_PFN_CURRENT_PROCESS_NAME)))
|
||||
FORCEINLINE
|
||||
void
|
||||
MI_SET_PROCESS(PEPROCESS Process)
|
||||
{
|
||||
if (!Process)
|
||||
MI_SET_PROCESS2("Kernel");
|
||||
else if (Process == (PEPROCESS)1)
|
||||
MI_SET_PROCESS2("Hydra");
|
||||
else
|
||||
MI_SET_PROCESS2(Process->ImageFileName);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
void
|
||||
MI_SET_PROCESS_USTR(PUNICODE_STRING ustr)
|
||||
{
|
||||
PWSTR pos, strEnd;
|
||||
int i;
|
||||
|
||||
if (!ustr->Buffer || ustr->Length == 0)
|
||||
{
|
||||
MI_PFN_CURRENT_PROCESS_NAME[0] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
pos = strEnd = &ustr->Buffer[ustr->Length / sizeof(WCHAR)];
|
||||
while ((*pos != L'\\') && (pos > ustr->Buffer))
|
||||
pos--;
|
||||
|
||||
if (*pos == L'\\')
|
||||
pos++;
|
||||
|
||||
for (i = 0; i < sizeof(MI_PFN_CURRENT_PROCESS_NAME) && pos <= strEnd; i++, pos++)
|
||||
MI_PFN_CURRENT_PROCESS_NAME[i] = (CHAR)*pos;
|
||||
}
|
||||
#define MI_SET_PROCESS2(x) memcpy(MI_PFN_CURRENT_PROCESS_NAME, x, 16)
|
||||
#else
|
||||
#define MI_SET_USAGE(x)
|
||||
#define MI_SET_PROCESS(x)
|
||||
#define MI_SET_PROCESS2(x)
|
||||
#endif
|
||||
|
||||
|
@ -316,9 +278,6 @@ typedef enum _MI_PFN_USAGES
|
|||
MI_USAGE_PFN_DATABASE,
|
||||
MI_USAGE_BOOT_DRIVER,
|
||||
MI_USAGE_INIT_MEMORY,
|
||||
MI_USAGE_PAGE_FILE,
|
||||
MI_USAGE_COW,
|
||||
MI_USAGE_WSLE,
|
||||
MI_USAGE_FREE_PAGE
|
||||
} MI_PFN_USAGES;
|
||||
|
||||
|
@ -399,7 +358,6 @@ typedef struct _MMPFN
|
|||
#if MI_TRACE_PFNS
|
||||
MI_PFN_USAGES PfnUsage;
|
||||
CHAR ProcessName[16];
|
||||
#define MI_SET_PFN_PROCESS_NAME(pfn, x) memcpy(pfn->ProcessName, x, min(sizeof(x), sizeof(pfn->ProcessName)))
|
||||
#endif
|
||||
|
||||
// HACK until WS lists are supported
|
||||
|
|
|
@ -1058,10 +1058,6 @@ VOID
|
|||
NTAPI
|
||||
MiInsertInWorkingSetList(_Inout_ PMMSUPPORT Vm, _In_ PVOID Address, _In_ ULONG Protection);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MiRemoveFromWorkingSetList(_Inout_ PMMSUPPORT Vm, _In_ PVOID Address);
|
||||
|
||||
//
|
||||
// New ARM3<->RosMM PAGE Architecture
|
||||
//
|
||||
|
|
|
@ -801,7 +801,7 @@ MiBuildPfnDatabaseFromPages(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|||
Pfn1->u3.e1.CacheAttribute = MiNonCached;
|
||||
#if MI_TRACE_PFNS
|
||||
Pfn1->PfnUsage = MI_USAGE_INIT_MEMORY;
|
||||
MI_SET_PFN_PROCESS_NAME(Pfn1, "Initial PDE");
|
||||
memcpy(Pfn1->ProcessName, "Initial PDE", 16);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
@ -848,7 +848,7 @@ MiBuildPfnDatabaseFromPages(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|||
Pfn2->u3.e1.CacheAttribute = MiNonCached;
|
||||
#if MI_TRACE_PFNS
|
||||
Pfn2->PfnUsage = MI_USAGE_INIT_MEMORY;
|
||||
MI_SET_PFN_PROCESS_NAME(Pfn2, "Initial PTE");
|
||||
memcpy(Pfn1->ProcessName, "Initial PTE", 16);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -697,6 +697,16 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
|||
/* Increment demand zero faults */
|
||||
KeGetCurrentPrcb()->MmDemandZeroCount++;
|
||||
|
||||
/* Do we have the lock? */
|
||||
if (HaveLock)
|
||||
{
|
||||
/* Release it */
|
||||
MiReleasePfnLock(OldIrql);
|
||||
|
||||
/* Update performance counters */
|
||||
if (Process > HYDRA_PROCESS) Process->NumberOfPrivatePages++;
|
||||
}
|
||||
|
||||
/* Zero the page if need be */
|
||||
if (NeedZero) MiZeroPfn(PageFrameNumber);
|
||||
|
||||
|
@ -735,23 +745,6 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
|||
ASSERT(Pfn1->u3.e1.PrototypePte == 0);
|
||||
}
|
||||
|
||||
/* Add the page to our working set, if it's not a proto PTE */
|
||||
if ((Process > HYDRA_PROCESS) && (PointerPte == MiAddressToPte(Address)))
|
||||
{
|
||||
/* FIXME: Also support session VM scenario */
|
||||
MiInsertInWorkingSetList(&Process->Vm, Address, Protection);
|
||||
}
|
||||
|
||||
/* Do we have the lock? */
|
||||
if (HaveLock)
|
||||
{
|
||||
/* Release it */
|
||||
MiReleasePfnLock(OldIrql);
|
||||
|
||||
/* Update performance counters */
|
||||
if (Process > HYDRA_PROCESS) Process->NumberOfPrivatePages++;
|
||||
}
|
||||
|
||||
//
|
||||
// It's all good now
|
||||
//
|
||||
|
@ -906,9 +899,6 @@ MiResolvePageFileFault(_In_ BOOLEAN StoreInstruction,
|
|||
ASSERT(CurrentProcess > HYDRA_PROCESS);
|
||||
ASSERT(*OldIrql != MM_NOIRQL);
|
||||
|
||||
MI_SET_USAGE(MI_USAGE_PAGE_FILE);
|
||||
MI_SET_PROCESS(CurrentProcess);
|
||||
|
||||
/* We must hold the PFN lock */
|
||||
MI_ASSERT_PFN_LOCK_HELD();
|
||||
|
||||
|
@ -969,9 +959,6 @@ MiResolvePageFileFault(_In_ BOOLEAN StoreInstruction,
|
|||
KeSetEvent(Pfn1->u1.Event, IO_NO_INCREMENT, FALSE);
|
||||
}
|
||||
|
||||
/* And we can insert this into the working set */
|
||||
MiInsertInWorkingSetList(&CurrentProcess->Vm, FaultingAddress, Protection);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -989,8 +976,6 @@ MiResolveTransitionFault(IN BOOLEAN StoreInstruction,
|
|||
PMMPFN Pfn1;
|
||||
MMPTE TempPte;
|
||||
PMMPTE PointerToPteForProtoPage;
|
||||
ULONG Protection;
|
||||
|
||||
DPRINT("Transition fault on 0x%p with PTE 0x%p in process %s\n",
|
||||
FaultingAddress, PointerPte, CurrentProcess->ImageFileName);
|
||||
|
||||
|
@ -1084,9 +1069,8 @@ MiResolveTransitionFault(IN BOOLEAN StoreInstruction,
|
|||
ASSERT(PointerPte->u.Hard.Valid == 0);
|
||||
ASSERT(PointerPte->u.Trans.Prototype == 0);
|
||||
ASSERT(PointerPte->u.Trans.Transition == 1);
|
||||
Protection = TempPte.u.Trans.Protection;
|
||||
TempPte.u.Long = (PointerPte->u.Long & ~0xFFF) |
|
||||
(MmProtectToPteMask[Protection]) |
|
||||
(MmProtectToPteMask[PointerPte->u.Trans.Protection]) |
|
||||
MiDetermineUserGlobalPteMask(PointerPte);
|
||||
|
||||
/* Is the PTE writeable? */
|
||||
|
@ -1106,10 +1090,6 @@ MiResolveTransitionFault(IN BOOLEAN StoreInstruction,
|
|||
/* Write the valid PTE */
|
||||
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
||||
|
||||
/* If this was a user fault, add it to the working set */
|
||||
if (CurrentProcess > HYDRA_PROCESS)
|
||||
MiInsertInWorkingSetList(&CurrentProcess->Vm, FaultingAddress, Protection);
|
||||
|
||||
/* Return success */
|
||||
return STATUS_PAGE_FAULT_TRANSITION;
|
||||
}
|
||||
|
@ -1230,9 +1210,6 @@ MiResolveProtoPteFault(IN BOOLEAN StoreInstruction,
|
|||
ASSERT(TempPte.u.Hard.Valid == 1);
|
||||
ProtoPageFrameIndex = PFN_FROM_PTE(&TempPte);
|
||||
|
||||
MI_SET_USAGE(MI_USAGE_COW);
|
||||
MI_SET_PROCESS(Process);
|
||||
|
||||
/* Get a new page for the private copy */
|
||||
if (Process > HYDRA_PROCESS)
|
||||
Color = MI_GET_NEXT_PROCESS_COLOR(Process);
|
||||
|
@ -1268,13 +1245,6 @@ MiResolveProtoPteFault(IN BOOLEAN StoreInstruction,
|
|||
/* And finally, write the valid PTE */
|
||||
MI_WRITE_VALID_PTE(PointerPte, PteContents);
|
||||
|
||||
/* Add the page to our working set */
|
||||
if (Process > HYDRA_PROCESS)
|
||||
{
|
||||
/* FIXME: Also support session VM scenario */
|
||||
MiInsertInWorkingSetList(&Process->Vm, Address, Protection);
|
||||
}
|
||||
|
||||
/* The caller expects us to release the PFN lock */
|
||||
MiReleasePfnLock(OldIrql);
|
||||
return Status;
|
||||
|
@ -2235,15 +2205,11 @@ UserFault:
|
|||
{
|
||||
PFN_NUMBER PageFrameIndex, OldPageFrameIndex;
|
||||
PMMPFN Pfn1;
|
||||
ProtectionCode = TempPte.u.Soft.Protection;
|
||||
|
||||
LockIrql = MiAcquirePfnLock();
|
||||
|
||||
ASSERT(MmAvailablePages > 0);
|
||||
|
||||
MI_SET_USAGE(MI_USAGE_COW);
|
||||
MI_SET_PROCESS(CurrentProcess);
|
||||
|
||||
/* Allocate a new page and copy it */
|
||||
PageFrameIndex = MiRemoveAnyPage(MI_GET_NEXT_PROCESS_COLOR(CurrentProcess));
|
||||
OldPageFrameIndex = PFN_FROM_PTE(&TempPte);
|
||||
|
@ -2265,9 +2231,6 @@ UserFault:
|
|||
|
||||
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
||||
|
||||
/* We can now add it to our working set */
|
||||
MiInsertInWorkingSetList(&CurrentProcess->Vm, Address, ProtectionCode);
|
||||
|
||||
MiReleasePfnLock(LockIrql);
|
||||
|
||||
/* Return the status */
|
||||
|
@ -2384,7 +2347,6 @@ UserFault:
|
|||
TempPte.u.Soft.Protection = ProtectionCode;
|
||||
MI_WRITE_INVALID_PTE(PointerPte, TempPte);
|
||||
}
|
||||
ProtectionCode = PointerPte->u.Soft.Protection;
|
||||
|
||||
/* Lock the PFN database since we're going to grab a page */
|
||||
OldIrql = MiAcquirePfnLock();
|
||||
|
@ -2422,6 +2384,9 @@ UserFault:
|
|||
/* One more demand-zero fault */
|
||||
KeGetCurrentPrcb()->MmDemandZeroCount++;
|
||||
|
||||
/* And we're done with the lock */
|
||||
MiReleasePfnLock(OldIrql);
|
||||
|
||||
/* Fault on user PDE, or fault on user PTE? */
|
||||
if (PointerPte <= MiHighestUserPte)
|
||||
{
|
||||
|
@ -2448,12 +2413,6 @@ UserFault:
|
|||
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
|
||||
ASSERT(Pfn1->u1.Event == NULL);
|
||||
|
||||
/* We can now insert it into the working set */
|
||||
MiInsertInWorkingSetList(&CurrentProcess->Vm, Address, ProtectionCode);
|
||||
|
||||
/* And we're done with the lock */
|
||||
MiReleasePfnLock(OldIrql);
|
||||
|
||||
/* Demand zero */
|
||||
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
||||
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
|
||||
|
|
|
@ -254,8 +254,8 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry)
|
|||
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;
|
||||
MI_SET_PROCESS2("Not Set");
|
||||
// MI_PFN_CURRENT_USAGE = MI_USAGE_NOT_SET;
|
||||
// memcpy(MI_PFN_CURRENT_PROCESS_NAME, "Not Set", 16);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -459,11 +459,11 @@ MiRemovePageByColor(IN PFN_NUMBER PageIndex,
|
|||
MiDecrementAvailablePages();
|
||||
|
||||
#if MI_TRACE_PFNS
|
||||
ASSERT(MI_PFN_CURRENT_USAGE != MI_USAGE_NOT_SET);
|
||||
//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;
|
||||
MI_SET_PROCESS2("Not Set");
|
||||
//MI_PFN_CURRENT_USAGE = MI_USAGE_NOT_SET;
|
||||
//memcpy(MI_PFN_CURRENT_PROCESS_NAME, "Not Set", 16);
|
||||
#endif
|
||||
|
||||
/* Return the page */
|
||||
|
@ -937,8 +937,9 @@ MiInsertPageInList(IN PMMPFNLIST ListHead,
|
|||
ColorHead->Count++;
|
||||
|
||||
#if MI_TRACE_PFNS
|
||||
ASSERT(MI_PFN_CURRENT_USAGE == MI_USAGE_NOT_SET);
|
||||
//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
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
#define GROW_WSLE 1
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
|
@ -864,34 +862,18 @@ MiGetFirstFreeWsleIndex(_Inout_ PMMSUPPORT Vm)
|
|||
if (WsList->LastEntry == WsList->LastInitializedWsle)
|
||||
{
|
||||
/* We must grow our array. Allocate a new page */
|
||||
PVOID Address = &WsList->Wsle[WsList->LastInitializedWsle + 1];
|
||||
PMMPTE PointerPte = MiAddressToPte(Address);
|
||||
PMMPTE PointerPte = MiAddressToPte(&WsList->Wsle[WsList->LastInitializedWsle + 1]);
|
||||
MMPTE TempPte;
|
||||
|
||||
MI_SET_USAGE(MI_USAGE_WSLE);
|
||||
MI_SET_PROCESS(PsGetCurrentProcess());
|
||||
|
||||
/* We must be at page boundary */
|
||||
ASSERT(Address == ALIGN_DOWN_POINTER_BY(Address, PAGE_SIZE));
|
||||
|
||||
PFN_NUMBER PageFrameIndex = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
|
||||
|
||||
MiInitializePfn(PageFrameIndex, PointerPte, TRUE);
|
||||
|
||||
TempPte = ValidKernelPteLocal;
|
||||
TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
|
||||
MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte, PointerPte, MM_READWRITE, PageFrameIndex);
|
||||
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
||||
|
||||
WsList->LastInitializedWsle += PAGE_SIZE / sizeof(MMWSLE);
|
||||
|
||||
/* Make sure we are staying on the same page */
|
||||
ASSERT(Address == ALIGN_DOWN_POINTER_BY(&WsList->Wsle[WsList->LastInitializedWsle], PAGE_SIZE));
|
||||
|
||||
/* We must insert this page in our working set ! */
|
||||
MiInsertInWorkingSetList(Vm, &WsList->Wsle[WsList->LastInitializedWsle], MM_READWRITE);
|
||||
|
||||
/* Now the last entry is the tail of our WSLE array */
|
||||
ASSERT(WsList->Wsle[WsList->LastEntry].u1.e1.VirtualPageNumber == ((ULONG_PTR)&WsList->Wsle[WsList->LastInitializedWsle]) >> PAGE_SHIFT);
|
||||
}
|
||||
|
||||
/* At this point we must be good to go */
|
||||
|
@ -927,26 +909,18 @@ MiGetFirstFreeWsleIndex(_Inout_ PMMSUPPORT Vm)
|
|||
|
||||
VOID
|
||||
NTAPI
|
||||
MiInsertInWorkingSetList(
|
||||
_Inout_ PMMSUPPORT Vm,
|
||||
_In_ PVOID Address,
|
||||
_In_ ULONG Protection)
|
||||
MiInsertInWorkingSetList(_Inout_ PMMSUPPORT Vm, _In_ PVOID Address, _In_ ULONG Protection)
|
||||
{
|
||||
ULONG WsIndex = MiGetFirstFreeWsleIndex(Vm);
|
||||
PMMWSLE WsleEntry = &Vm->VmWorkingSetList->Wsle[WsIndex];
|
||||
PMMPTE PointerPte = MiAddressToPte(Address);
|
||||
PMMPFN Pfn1;
|
||||
PMMPFN Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
|
||||
|
||||
/* Make sure we got a rounded address */
|
||||
Address = ALIGN_DOWN_POINTER_BY(Address, PAGE_SIZE);
|
||||
|
||||
/* Make sure we are locking the right things */
|
||||
/* Make sure we are locking the right thing */
|
||||
ASSERT(MM_ANY_WS_LOCK_HELD(PsGetCurrentThread()));
|
||||
MI_ASSERT_PFN_LOCK_HELD();
|
||||
|
||||
/* Make sure we are adding a paged-in address */
|
||||
ASSERT(PointerPte->u.Hard.Valid == 1);
|
||||
Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
|
||||
|
||||
/* The Pfn must be an active one */
|
||||
ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid);
|
||||
|
@ -957,11 +931,6 @@ MiInsertInWorkingSetList(
|
|||
|
||||
/* Shared pages not supported yet */
|
||||
ASSERT(Pfn1->u1.WsIndex == 0);
|
||||
ASSERT(Pfn1->u3.e1.PrototypePte == 0);
|
||||
|
||||
/* Nor are "ROS PFN" */
|
||||
ASSERT(MI_IS_ROS_PFN(Pfn1) == FALSE);
|
||||
|
||||
WsleEntry->u1.e1.Direct = 1;
|
||||
|
||||
Pfn1->u1.WsIndex = WsIndex;
|
||||
|
@ -972,177 +941,6 @@ MiInsertInWorkingSetList(
|
|||
Vm->PeakWorkingSetSize = Vm->WorkingSetSize;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
MiShrinkWorkingSet(_Inout_ PMMSUPPORT Vm)
|
||||
{
|
||||
PMMWSL WsList = Vm->VmWorkingSetList;
|
||||
ULONG LastValid = WsList->LastEntry;
|
||||
|
||||
while(WsList->Wsle[LastValid].u1.e1.Valid == 0)
|
||||
{
|
||||
LastValid--;
|
||||
}
|
||||
|
||||
if (LastValid != WsList->LastEntry)
|
||||
{
|
||||
/* There was a hole behind us. Handle this */
|
||||
PMMWSLE NextFree = &WsList->Wsle[LastValid + 1];
|
||||
if (NextFree->u1.Free.PreviousFree == MMWSLE_PREVIOUS_FREE_INVALID)
|
||||
{
|
||||
/* This was actually our first free entry. */
|
||||
ASSERT(WsList->FirstFree == LastValid + 1);
|
||||
WsList->FirstFree = MMWSLE_NEXT_FREE_INVALID;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The previous one is now the last in the queue */
|
||||
PMMWSLE PreviousFree = &WsList->Wsle[NextFree->u1.Free.PreviousFree];
|
||||
|
||||
ASSERT(PreviousFree->u1.Free.MustBeZero == 0);
|
||||
PreviousFree->u1.Free.NextFree = MMWSLE_NEXT_FREE_INVALID;
|
||||
}
|
||||
|
||||
/* Nuke everyone */
|
||||
RtlZeroMemory(&WsList->Wsle[LastValid + 1], (WsList->LastEntry - LastValid) * sizeof(MMWSLE));
|
||||
WsList->LastEntry = LastValid;
|
||||
}
|
||||
|
||||
if (LastValid < WsList->FirstDynamic)
|
||||
{
|
||||
/* Do not mess around with the protected ones */
|
||||
return;
|
||||
}
|
||||
|
||||
/* See if we should shrink our array */
|
||||
if (LastValid == (WsList->LastInitializedWsle - (PAGE_SIZE / sizeof(MMWSLE)) + 1))
|
||||
{
|
||||
PVOID WsleArrayQueue = ALIGN_DOWN_POINTER_BY(&WsList->Wsle[LastValid], PAGE_SIZE);
|
||||
PEPROCESS Process = MmGetAddressSpaceOwner(Vm);
|
||||
|
||||
ASSERT(WsList->Wsle[WsList->LastEntry].u1.e1.VirtualPageNumber == ((ULONG_PTR)WsleArrayQueue) >> PAGE_SHIFT);
|
||||
|
||||
/* Kernel address space not supported yet */
|
||||
ASSERT(Process != NULL);
|
||||
|
||||
/* Nuke the PTE. This will remove the virtual address from the working set */
|
||||
MiDeletePte(MiAddressToPte(WsleArrayQueue), WsleArrayQueue, Process, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MiRemoveFromWorkingSetList(
|
||||
_Inout_ PMMSUPPORT Vm,
|
||||
_In_ PVOID Address)
|
||||
{
|
||||
PMMWSL WsList = Vm->VmWorkingSetList;
|
||||
ULONG WsIndex;
|
||||
PMMWSLE WsleEntry;
|
||||
PMMPTE PointerPte = MiAddressToPte(Address);
|
||||
PMMPFN Pfn1;
|
||||
|
||||
/* Make sure we got a rounded address */
|
||||
Address = ALIGN_DOWN_POINTER_BY(Address, PAGE_SIZE);
|
||||
|
||||
/* Make sure we are locking the right things */
|
||||
ASSERT(MM_ANY_WS_LOCK_HELD(PsGetCurrentThread()));
|
||||
MI_ASSERT_PFN_LOCK_HELD();
|
||||
|
||||
/* Make sure we are removing a paged-in address */
|
||||
ASSERT(PointerPte->u.Hard.Valid == 1);
|
||||
Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
|
||||
|
||||
/* The Pfn must be an active one */
|
||||
ASSERT(Pfn1->u3.e1.PageLocation == ActiveAndValid);
|
||||
|
||||
WsIndex = Pfn1->u1.WsIndex;
|
||||
WsleEntry = &Vm->VmWorkingSetList->Wsle[WsIndex];
|
||||
|
||||
/* Shared page not handled yet */
|
||||
ASSERT(Pfn1->u3.e1.PrototypePte == 0);
|
||||
ASSERT(WsleEntry->u1.e1.Direct == 1);
|
||||
/* Nor are "ROS PFN" */
|
||||
ASSERT(MI_IS_ROS_PFN(Pfn1) == FALSE);
|
||||
|
||||
/* Some sanity checks */
|
||||
ASSERT(WsIndex >= WsList->FirstDynamic);
|
||||
ASSERT(WsIndex <= WsList->LastEntry);
|
||||
ASSERT(WsIndex <= WsList->LastInitializedWsle);
|
||||
ASSERT(WsleEntry->u1.e1.Valid == 1);
|
||||
ASSERT(WsleEntry->u1.e1.VirtualPageNumber == ((ULONG_PTR)Address) >> PAGE_SHIFT);
|
||||
|
||||
/* Let this go */
|
||||
Pfn1->u1.WsIndex = 0;
|
||||
|
||||
/* Nuke it */
|
||||
WsleEntry->u1.Long = 0;
|
||||
|
||||
/* Insert our entry into the free list */
|
||||
if (WsIndex == WsList->LastEntry)
|
||||
{
|
||||
/* Let's shrink the active list */
|
||||
WsList->LastEntry--;
|
||||
MiShrinkWorkingSet(Vm);
|
||||
}
|
||||
else if (WsList->FirstFree > WsList->LastEntry)
|
||||
{
|
||||
/* We are the first free entry to be inserted */
|
||||
WsList->FirstFree = WsIndex;
|
||||
WsleEntry->u1.Free.PreviousFree = MMWSLE_PREVIOUS_FREE_INVALID;
|
||||
WsleEntry->u1.Free.NextFree = MMWSLE_NEXT_FREE_INVALID;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Keep this sorted */
|
||||
PMMWSLE NextFree = &WsList->Wsle[WsList->FirstFree];
|
||||
PMMWSLE PreviousFree = NULL;
|
||||
|
||||
ASSERT(NextFree->u1.Free.MustBeZero == 0);
|
||||
|
||||
while (NextFree < WsleEntry)
|
||||
{
|
||||
PreviousFree = NextFree;
|
||||
if (NextFree->u1.Free.NextFree != MMWSLE_NEXT_FREE_INVALID)
|
||||
{
|
||||
NextFree = &WsList->Wsle[NextFree->u1.Free.NextFree];
|
||||
ASSERT(NextFree->u1.Free.MustBeZero == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
NextFree = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(PreviousFree || NextFree);
|
||||
|
||||
if (PreviousFree)
|
||||
{
|
||||
ASSERT((NextFree != NULL) || (PreviousFree->u1.Free.NextFree == MMWSLE_NEXT_FREE_INVALID));
|
||||
PreviousFree->u1.Free.NextFree = WsIndex;
|
||||
WsleEntry->u1.Free.PreviousFree = PreviousFree - WsList->Wsle;
|
||||
}
|
||||
else
|
||||
{
|
||||
WsleEntry->u1.Free.PreviousFree = MMWSLE_PREVIOUS_FREE_INVALID;
|
||||
ASSERT(NextFree->u1.Free.PreviousFree == MMWSLE_PREVIOUS_FREE_INVALID);
|
||||
WsList->FirstFree = WsIndex;
|
||||
}
|
||||
|
||||
if (NextFree)
|
||||
{
|
||||
NextFree->u1.Free.PreviousFree = WsIndex;
|
||||
WsleEntry->u1.Free.NextFree = NextFree - WsList->Wsle;
|
||||
}
|
||||
else
|
||||
{
|
||||
WsleEntry->u1.Free.NextFree = MMWSLE_NEXT_FREE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
Vm->WorkingSetSize -= PAGE_SIZE;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
|
|
|
@ -188,7 +188,14 @@ MiLoadImageSection(IN OUT PVOID *SectionPtr,
|
|||
/* Some debug stuff */
|
||||
MI_SET_USAGE(MI_USAGE_DRIVER_PAGE);
|
||||
#if MI_TRACE_PFNS
|
||||
MI_SET_PROCESS_USTR(FileName);
|
||||
if (FileName->Buffer)
|
||||
{
|
||||
PWCHAR pos = NULL;
|
||||
ULONG len = 0;
|
||||
pos = wcsrchr(FileName->Buffer, '\\');
|
||||
len = wcslen(pos) * sizeof(WCHAR);
|
||||
if (pos) snprintf(MI_PFN_CURRENT_PROCESS_NAME, min(16, len), "%S", pos);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Grab a page */
|
||||
|
|
|
@ -503,9 +503,6 @@ MiDeletePte(IN PMMPTE PointerPte,
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Remove this address from the WS list */
|
||||
MiRemoveFromWorkingSetList(&CurrentProcess->Vm, VirtualAddress);
|
||||
|
||||
/* Make sure the saved PTE address is valid */
|
||||
if ((PMMPTE)((ULONG_PTR)Pfn1->PteAddress & ~0x1) != PointerPte)
|
||||
{
|
||||
|
@ -2306,15 +2303,13 @@ MiProtectVirtualMemory(IN PEPROCESS Process,
|
|||
{
|
||||
KIRQL OldIrql = MiAcquirePfnLock();
|
||||
|
||||
/* Remove this from the working set */
|
||||
MiRemoveFromWorkingSetList(AddressSpace, MiPteToAddress(PointerPte));
|
||||
|
||||
/* Mark the PTE as transition and change its protection */
|
||||
PteContents.u.Hard.Valid = 0;
|
||||
PteContents.u.Soft.Transition = 1;
|
||||
PteContents.u.Trans.Protection = ProtectionMask;
|
||||
/* Decrease PFN share count and write the PTE */
|
||||
MiDecrementShareCount(Pfn1, PFN_FROM_PTE(&PteContents));
|
||||
// FIXME: remove the page from the WS
|
||||
MI_WRITE_INVALID_PTE(PointerPte, PteContents);
|
||||
#ifdef CONFIG_SMP
|
||||
// FIXME: Should invalidate entry in every CPU TLB
|
||||
|
@ -2452,10 +2447,8 @@ MiMakePdeExistAndMakeValid(IN PMMPDE PointerPde,
|
|||
|
||||
VOID
|
||||
NTAPI
|
||||
MiProcessValidPteList(
|
||||
_Inout_ PMMSUPPORT Vm,
|
||||
_Inout_ PMMPTE *ValidPteList,
|
||||
_In_ ULONG Count)
|
||||
MiProcessValidPteList(IN PMMPTE *ValidPteList,
|
||||
IN ULONG Count)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
ULONG i;
|
||||
|
@ -2475,11 +2468,6 @@ MiProcessValidPteList(
|
|||
TempPte = *ValidPteList[i];
|
||||
ASSERT(TempPte.u.Hard.Valid == 1);
|
||||
|
||||
//
|
||||
// We can now remove this addres from the working set
|
||||
//
|
||||
MiRemoveFromWorkingSetList(Vm, MiPteToAddress(ValidPteList[i]));
|
||||
|
||||
//
|
||||
// Get the PFN entry for the page itself, and then for its page table
|
||||
//
|
||||
|
@ -2521,6 +2509,7 @@ MiDecommitPages(IN PVOID StartingAddress,
|
|||
ULONG CommitReduction = 0;
|
||||
PMMPTE ValidPteList[256];
|
||||
ULONG PteCount = 0;
|
||||
PMMPFN Pfn1;
|
||||
MMPTE PteContents;
|
||||
PETHREAD CurrentThread = PsGetCurrentThread();
|
||||
|
||||
|
@ -2552,10 +2541,10 @@ MiDecommitPages(IN PVOID StartingAddress,
|
|||
// such, and does not flush the entire TLB all the time, but right
|
||||
// now we have bigger problems to worry about than TLB flushing.
|
||||
//
|
||||
PointerPde = MiPteToPde(PointerPte);
|
||||
PointerPde = MiAddressToPde(StartingAddress);
|
||||
if (PteCount)
|
||||
{
|
||||
MiProcessValidPteList(&Process->Vm, ValidPteList, PteCount);
|
||||
MiProcessValidPteList(ValidPteList, PteCount);
|
||||
PteCount = 0;
|
||||
}
|
||||
|
||||
|
@ -2590,13 +2579,21 @@ MiDecommitPages(IN PVOID StartingAddress,
|
|||
//Process->NumberOfPrivatePages--;
|
||||
if (PteContents.u.Hard.Valid)
|
||||
{
|
||||
//
|
||||
// It's valid. At this point make sure that it is not a ROS
|
||||
// PFN. Also, we don't support ProtoPTEs in this code path.
|
||||
//
|
||||
Pfn1 = MiGetPfnEntry(PteContents.u.Hard.PageFrameNumber);
|
||||
ASSERT(MI_IS_ROS_PFN(Pfn1) == FALSE);
|
||||
ASSERT(Pfn1->u3.e1.PrototypePte == FALSE);
|
||||
|
||||
//
|
||||
// Flush any pending PTEs that we had not yet flushed, if our
|
||||
// list has gotten too big, then add this PTE to the flush list.
|
||||
//
|
||||
if (PteCount == 256)
|
||||
{
|
||||
MiProcessValidPteList(&Process->Vm, ValidPteList, PteCount);
|
||||
MiProcessValidPteList(ValidPteList, PteCount);
|
||||
PteCount = 0;
|
||||
}
|
||||
ValidPteList[PteCount++] = PointerPte;
|
||||
|
@ -2626,7 +2623,7 @@ MiDecommitPages(IN PVOID StartingAddress,
|
|||
// This used to be a zero PTE and it no longer is, so we must add a
|
||||
// reference to the pagetable.
|
||||
//
|
||||
MiIncrementPageTableReferences(MiPteToAddress(PointerPte));
|
||||
MiIncrementPageTableReferences(StartingAddress);
|
||||
|
||||
//
|
||||
// Next, we account for decommitted PTEs and make the PTE as such
|
||||
|
@ -2636,16 +2633,17 @@ MiDecommitPages(IN PVOID StartingAddress,
|
|||
}
|
||||
|
||||
//
|
||||
// Move to the next PTE
|
||||
// Move to the next PTE and the next address
|
||||
//
|
||||
PointerPte++;
|
||||
StartingAddress = (PVOID)((ULONG_PTR)StartingAddress + PAGE_SIZE);
|
||||
}
|
||||
|
||||
//
|
||||
// Flush any dangling PTEs from the loop in the last page table, and then
|
||||
// release the working set and return the commit reduction accounting.
|
||||
//
|
||||
if (PteCount) MiProcessValidPteList(&Process->Vm, ValidPteList, PteCount);
|
||||
if (PteCount) MiProcessValidPteList(ValidPteList, PteCount);
|
||||
MiUnlockProcessWorkingSetUnsafe(Process, CurrentThread);
|
||||
return CommitReduction;
|
||||
}
|
||||
|
|
|
@ -574,21 +574,6 @@ MmAllocPage(ULONG Type)
|
|||
|
||||
OldIrql = MiAcquirePfnLock();
|
||||
|
||||
#if MI_TRACE_PFNS
|
||||
switch(Type)
|
||||
{
|
||||
case MC_CACHE:
|
||||
case MC_SYSTEM:
|
||||
MI_SET_USAGE(MI_USAGE_CACHE);
|
||||
break;
|
||||
case MC_USER:
|
||||
MI_SET_USAGE(MI_USAGE_SECTION);
|
||||
break;
|
||||
default:
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
#endif
|
||||
|
||||
PfnOffset = MiRemoveZeroPage(MI_GET_NEXT_COLOR());
|
||||
if (!PfnOffset)
|
||||
{
|
||||
|
|
|
@ -264,10 +264,6 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
|
|||
|
||||
MI_WRITE_INVALID_PTE(PointerPde, DemandZeroPde);
|
||||
// Tiny HACK: Parameter 1 is the architecture specific FaultCode for an access violation (i.e. page is present)
|
||||
|
||||
/* Lock the working set, as this will add this address to it */
|
||||
MiLockProcessWorkingSetUnsafe(Process, PsGetCurrentThread());
|
||||
|
||||
Status = MiDispatchFault(0x1,
|
||||
Pt,
|
||||
PointerPde,
|
||||
|
@ -279,8 +275,6 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
|
|||
DBG_UNREFERENCED_LOCAL_VARIABLE(Status);
|
||||
ASSERT(KeAreAllApcsDisabled() == TRUE);
|
||||
ASSERT(PointerPde->u.Hard.Valid == 1);
|
||||
|
||||
MiUnlockProcessWorkingSetUnsafe(Process, PsGetCurrentThread());
|
||||
}
|
||||
return (PULONG)MiAddressToPte(Address);
|
||||
}
|
||||
|
|
|
@ -331,16 +331,13 @@ MmFreeMemoryArea(
|
|||
ASSERT(AddressSpace != MmGetKernelAddressSpace());
|
||||
if (MiQueryPageTableReferences((PVOID)Address) == 0)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
/* No PTE relies on this PDE. Release it */
|
||||
MiLockProcessWorkingSet(Process, PsGetCurrentThread());
|
||||
OldIrql = MiAcquirePfnLock();
|
||||
KIRQL OldIrql = MiAcquirePfnLock();
|
||||
PMMPDE PointerPde = MiAddressToPde(Address);
|
||||
ASSERT(PointerPde->u.Hard.Valid == 1);
|
||||
MiDeletePte(PointerPde, MiPdeToPte(PointerPde), Process, NULL);
|
||||
ASSERT(PointerPde->u.Hard.Valid == 0);
|
||||
MiReleasePfnLock(OldIrql);
|
||||
MiUnlockProcessWorkingSet(Process, PsGetCurrentThread());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1163,6 +1163,8 @@ MiReadPage(PMEMORY_AREA MemoryArea,
|
|||
* Allocate a page, this is rather complicated by the possibility
|
||||
* we might have to move other things out of memory
|
||||
*/
|
||||
MI_SET_USAGE(MI_USAGE_SECTION);
|
||||
MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
|
||||
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, Page);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
|
@ -1622,6 +1624,9 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
|||
((Offset.QuadPart >= (LONGLONG)PAGE_ROUND_UP(Segment->RawLength.QuadPart) &&
|
||||
(Section->AllocationAttributes & SEC_IMAGE))))
|
||||
{
|
||||
MI_SET_USAGE(MI_USAGE_SECTION);
|
||||
if (Process) MI_SET_PROCESS2(Process->ImageFileName);
|
||||
if (!Process) MI_SET_PROCESS2("Kernel Section");
|
||||
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
|
@ -1702,6 +1707,9 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
|||
MmUnlockSectionSegment(Segment);
|
||||
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
MI_SET_USAGE(MI_USAGE_SECTION);
|
||||
if (Process) MI_SET_PROCESS2(Process->ImageFileName);
|
||||
if (!Process) MI_SET_PROCESS2("Kernel Section");
|
||||
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
|
@ -1870,6 +1878,9 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
|
|||
/*
|
||||
* Allocate a page
|
||||
*/
|
||||
MI_SET_USAGE(MI_USAGE_SECTION);
|
||||
if (Process) MI_SET_PROCESS2(Process->ImageFileName);
|
||||
if (!Process) MI_SET_PROCESS2("Kernel Section");
|
||||
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &NewPage);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue