mirror of
https://github.com/reactos/reactos.git
synced 2024-07-31 00:28:56 +00:00
[NTOS]: Implement MiDeleteSystemPageableVm.
[NTOS]: The paged pool free code was behaving incorrectly, assuming that paged pool was "locked down" and never paged out/reused (a valid NT operation mode), while the allocation code was assuming paged pool was a volatile, reusable, pageable resource (normal NT operation mode). The free code now assumes normal operation mode, and actually frees the freed paged pool pages, by using MiDeleteSystemPageableVm. I have a feeling this will make ARM3 paged pool work. svn path=/trunk/; revision=47582
This commit is contained in:
parent
9ef0181983
commit
f4f8ee78d1
|
@ -733,6 +733,15 @@ MiInsertPageInFreeList(
|
||||||
IN PFN_NUMBER PageFrameIndex
|
IN PFN_NUMBER PageFrameIndex
|
||||||
);
|
);
|
||||||
|
|
||||||
|
PFN_NUMBER
|
||||||
|
NTAPI
|
||||||
|
MiDeleteSystemPageableVm(
|
||||||
|
IN PMMPTE PointerPte,
|
||||||
|
IN PFN_NUMBER PageCount,
|
||||||
|
IN ULONG Flags,
|
||||||
|
OUT PPFN_NUMBER ValidPages
|
||||||
|
);
|
||||||
|
|
||||||
PLDR_DATA_TABLE_ENTRY
|
PLDR_DATA_TABLE_ENTRY
|
||||||
NTAPI
|
NTAPI
|
||||||
MiLookupDataTableEntry(
|
MiLookupDataTableEntry(
|
||||||
|
|
|
@ -264,6 +264,7 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType,
|
||||||
// Get the page bit count
|
// Get the page bit count
|
||||||
//
|
//
|
||||||
i = ((SizeInPages - 1) / 1024) + 1;
|
i = ((SizeInPages - 1) / 1024) + 1;
|
||||||
|
DPRINT1("Paged pool expansion: %d %x\n", i, SizeInPages);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if there is enougn paged pool expansion space left
|
// Check if there is enougn paged pool expansion space left
|
||||||
|
@ -666,6 +667,11 @@ MiFreePoolPages(IN PVOID StartingVa)
|
||||||
//
|
//
|
||||||
NumberOfPages = End - i + 1;
|
NumberOfPages = End - i + 1;
|
||||||
|
|
||||||
|
/* Delete the actual pages */
|
||||||
|
PointerPte = MmPagedPoolInfo.FirstPteForPagedPool + i;
|
||||||
|
FreePages = MiDeleteSystemPageableVm(PointerPte, NumberOfPages, 0, NULL);
|
||||||
|
ASSERT(FreePages == NumberOfPages);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Acquire the paged pool lock
|
// Acquire the paged pool lock
|
||||||
//
|
//
|
||||||
|
|
|
@ -29,6 +29,102 @@ MiProtectVirtualMemory(IN PEPROCESS Process,
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS **********************************************************/
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
|
PFN_NUMBER
|
||||||
|
NTAPI
|
||||||
|
MiDeleteSystemPageableVm(IN PMMPTE PointerPte,
|
||||||
|
IN PFN_NUMBER PageCount,
|
||||||
|
IN ULONG Flags,
|
||||||
|
OUT PPFN_NUMBER ValidPages)
|
||||||
|
{
|
||||||
|
PFN_NUMBER ActualPages = 0;
|
||||||
|
PETHREAD CurrentThread;
|
||||||
|
PMMPFN Pfn1, Pfn2;
|
||||||
|
PFN_NUMBER PageFrameIndex, PageTableIndex;
|
||||||
|
KIRQL OldIrql, LockIrql;
|
||||||
|
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now we must raise to APC_LEVEL and mark the thread as owner
|
||||||
|
* We don't actually implement a working set pushlock, so this is only
|
||||||
|
* for internal consistency (and blocking APCs)
|
||||||
|
*/
|
||||||
|
KeRaiseIrql(APC_LEVEL, &LockIrql);
|
||||||
|
CurrentThread = PsGetCurrentThread();
|
||||||
|
KeEnterGuardedRegion();
|
||||||
|
ASSERT((CurrentThread->OwnsSystemWorkingSetExclusive == 0) &&
|
||||||
|
(CurrentThread->OwnsSystemWorkingSetShared == 0));
|
||||||
|
CurrentThread->OwnsSystemWorkingSetExclusive = 1;
|
||||||
|
|
||||||
|
/* Loop all pages */
|
||||||
|
while (PageCount)
|
||||||
|
{
|
||||||
|
/* Make sure there's some data about the page */
|
||||||
|
if (PointerPte->u.Long)
|
||||||
|
{
|
||||||
|
/* As always, only handle current ARM3 scenarios */
|
||||||
|
ASSERT(PointerPte->u.Soft.Prototype == 0);
|
||||||
|
ASSERT(PointerPte->u.Soft.Transition == 0);
|
||||||
|
ASSERT(PointerPte->u.Hard.Valid == 1);
|
||||||
|
|
||||||
|
/* Normally this is one possibility -- freeing a valid page */
|
||||||
|
if (PointerPte->u.Hard.Valid)
|
||||||
|
{
|
||||||
|
/* Get the page PFN */
|
||||||
|
PageFrameIndex = PFN_FROM_PTE(PointerPte);
|
||||||
|
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
||||||
|
|
||||||
|
/* Should not have any working set data yet */
|
||||||
|
ASSERT(Pfn1->u1.WsIndex == 0);
|
||||||
|
|
||||||
|
/* Actual valid, legitimate, pages */
|
||||||
|
if (ValidPages) *ValidPages++;
|
||||||
|
|
||||||
|
/* Get the page table entry */
|
||||||
|
PageTableIndex = Pfn1->u4.PteFrame;
|
||||||
|
DPRINT1("Page table: %lx\n", PageTableIndex);
|
||||||
|
Pfn2 = MiGetPfnEntry(PageTableIndex);
|
||||||
|
|
||||||
|
/* Lock the PFN database */
|
||||||
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
|
||||||
|
/* Delete it the page */
|
||||||
|
MI_SET_PFN_DELETED(Pfn1);
|
||||||
|
MiDecrementShareCount(Pfn1, PageFrameIndex);
|
||||||
|
|
||||||
|
/* Decrement the page table too */
|
||||||
|
#if 0 // ARM3: Dont't trust this yet
|
||||||
|
MiDecrementShareCount(Pfn2, PageTableIndex);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Release the PFN database */
|
||||||
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
|
/* Destroy the PTE */
|
||||||
|
PointerPte->u.Long = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Actual legitimate pages */
|
||||||
|
ActualPages++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keep going */
|
||||||
|
PointerPte++;
|
||||||
|
PageCount--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Re-enable APCs */
|
||||||
|
ASSERT(KeAreAllApcsDisabled() == TRUE);
|
||||||
|
CurrentThread->OwnsSystemWorkingSetExclusive = 0;
|
||||||
|
KeLeaveGuardedRegion();
|
||||||
|
KeLowerIrql(LockIrql);
|
||||||
|
|
||||||
|
/* Flush the entire TLB */
|
||||||
|
KeFlushEntireTb(TRUE, TRUE);
|
||||||
|
|
||||||
|
/* Done */
|
||||||
|
return ActualPages;
|
||||||
|
}
|
||||||
|
|
||||||
LONG
|
LONG
|
||||||
MiGetExceptionInfo(IN PEXCEPTION_POINTERS ExceptionInfo,
|
MiGetExceptionInfo(IN PEXCEPTION_POINTERS ExceptionInfo,
|
||||||
OUT PBOOLEAN HaveBadAddress,
|
OUT PBOOLEAN HaveBadAddress,
|
||||||
|
|
Loading…
Reference in a new issue