mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 12:23:31 +00:00
[NTOSKRNL]
Account for wait entries delaying a view attribute change and interacting with the machinery in CoW copying code, specifically making CoW insert and revoke a wait while copying the page, and make the CoW copy function take both pages as arguments rather than relying on the address space. Also alter the MM_WAIT_ENTRY value a bit to take into account an assert that it must have bit 0x800 set. svn path=/trunk/; revision=56488
This commit is contained in:
+1
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
/* TYPES *********************************************************************/
|
||||
|
||||
#define MM_WAIT_ENTRY 0x7ffff800
|
||||
#define MM_WAIT_ENTRY 0x7ffffc00
|
||||
#define PFN_FROM_SSE(E) ((PFN_NUMBER)((E) >> PAGE_SHIFT))
|
||||
#define IS_SWAP_FROM_SSE(E) ((E) & 0x00000001)
|
||||
#define MM_IS_WAIT_PTE(E) \
|
||||
|
||||
@@ -955,8 +955,8 @@ ExAllocatePageWithPhysPage(PFN_NUMBER Page);
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiCopyFromUserPage(
|
||||
PFN_NUMBER Page,
|
||||
PVOID SourceAddress
|
||||
PFN_NUMBER NewPage,
|
||||
PFN_NUMBER OldPage
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
|
||||
@@ -558,6 +558,7 @@ MmDeletePageFileMapping(PEPROCESS Process, PVOID Address,
|
||||
|
||||
if ((Pte & PA_PRESENT) || !(Pte & 0x800))
|
||||
{
|
||||
DPRINT1("Pte %x (want not 1 and 0x800)\n", Pte);
|
||||
KeBugCheck(MEMORY_MANAGEMENT);
|
||||
}
|
||||
|
||||
|
||||
@@ -959,22 +959,24 @@ BOOLEAN MiIsPageFromCache(PMEMORY_AREA MemoryArea,
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiCopyFromUserPage(PFN_NUMBER DestPage, PVOID SourceAddress)
|
||||
MiCopyFromUserPage(PFN_NUMBER DestPage, PFN_NUMBER SrcPage)
|
||||
{
|
||||
PEPROCESS Process;
|
||||
KIRQL Irql;
|
||||
PVOID TempAddress;
|
||||
KIRQL Irql, Irql2;
|
||||
PVOID DestAddress, SrcAddress;
|
||||
|
||||
ASSERT((ULONG_PTR)SourceAddress % PAGE_SIZE == 0);
|
||||
Process = PsGetCurrentProcess();
|
||||
TempAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql);
|
||||
if (TempAddress == NULL)
|
||||
DestAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql);
|
||||
SrcAddress = MiMapPageInHyperSpace(Process, SrcPage, &Irql2);
|
||||
if (DestAddress == NULL || SrcAddress == NULL)
|
||||
{
|
||||
return(STATUS_NO_MEMORY);
|
||||
}
|
||||
ASSERT((ULONG_PTR)TempAddress % PAGE_SIZE == 0);
|
||||
RtlCopyMemory(TempAddress, SourceAddress, PAGE_SIZE);
|
||||
MiUnmapPageInHyperSpace(Process, TempAddress, Irql);
|
||||
ASSERT((ULONG_PTR)DestAddress % PAGE_SIZE == 0);
|
||||
ASSERT((ULONG_PTR)SrcAddress % PAGE_SIZE == 0);
|
||||
RtlCopyMemory(DestAddress, SrcAddress, PAGE_SIZE);
|
||||
MiUnmapPageInHyperSpace(Process, SrcAddress, Irql2);
|
||||
MiUnmapPageInHyperSpace(Process, DestAddress, Irql);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -1620,6 +1622,7 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
|
||||
PMM_REGION Region;
|
||||
ULONG_PTR Entry;
|
||||
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
|
||||
SWAPENTRY SwapEntry;
|
||||
|
||||
DPRINT("MmAccessFaultSectionView(%x, %x, %x, %x)\n", AddressSpace, MemoryArea, Address);
|
||||
|
||||
@@ -1699,6 +1702,10 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
|
||||
return(STATUS_MM_RESTART_OPERATION);
|
||||
}
|
||||
|
||||
MmDeleteRmap(OldPage, Process, PAddress);
|
||||
MmDeleteVirtualMapping(Process, PAddress, FALSE, NULL, NULL);
|
||||
MmCreatePageFileMapping(Process, PAddress, MM_WAIT_ENTRY);
|
||||
|
||||
/*
|
||||
* Release locks now we have the pageop
|
||||
*/
|
||||
@@ -1720,17 +1727,14 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
|
||||
/*
|
||||
* Copy the old page
|
||||
*/
|
||||
MiCopyFromUserPage(NewPage, PAddress);
|
||||
MiCopyFromUserPage(NewPage, OldPage);
|
||||
|
||||
MmLockAddressSpace(AddressSpace);
|
||||
/*
|
||||
* Delete the old entry.
|
||||
*/
|
||||
MmDeleteVirtualMapping(Process, Address, FALSE, NULL, NULL);
|
||||
|
||||
/*
|
||||
* Set the PTE to point to the new page
|
||||
*/
|
||||
MmDeletePageFileMapping(Process, PAddress, &SwapEntry);
|
||||
Status = MmCreateVirtualMapping(Process,
|
||||
PAddress,
|
||||
Region->Protect,
|
||||
@@ -1751,7 +1755,7 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
|
||||
/*
|
||||
* Unshare the old page.
|
||||
*/
|
||||
MmDeleteRmap(OldPage, Process, PAddress);
|
||||
DPRINT("Swapping page (Old %x New %x)\n", OldPage, NewPage);
|
||||
MmInsertRmap(NewPage, Process, PAddress);
|
||||
MmLockSectionSegment(Segment);
|
||||
MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, FALSE, FALSE, NULL);
|
||||
@@ -2388,9 +2392,18 @@ MmAlterViewAttributes(PMMSUPPORT AddressSpace,
|
||||
{
|
||||
for (i = 0; i < PAGE_ROUND_UP(RegionSize) / PAGE_SIZE; i++)
|
||||
{
|
||||
SWAPENTRY SwapEntry;
|
||||
PVOID Address = (char*)BaseAddress + (i * PAGE_SIZE);
|
||||
ULONG Protect = NewProtect;
|
||||
|
||||
/* Wait for a wait entry to disappear */
|
||||
do {
|
||||
MmGetPageFileMapping(Process, Address, &SwapEntry);
|
||||
if (SwapEntry != MM_WAIT_ENTRY)
|
||||
break;
|
||||
MiWaitForPageEvent(Process, Address);
|
||||
} while (TRUE);
|
||||
|
||||
/*
|
||||
* If we doing COW for this segment then check if the page is
|
||||
* already private.
|
||||
@@ -2404,6 +2417,10 @@ MmAlterViewAttributes(PMMSUPPORT AddressSpace,
|
||||
Offset.QuadPart = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
|
||||
+ MemoryArea->Data.SectionData.ViewOffset.QuadPart;
|
||||
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
|
||||
/*
|
||||
* An MM_WAIT_ENTRY is ok in this case... It'll just count as
|
||||
* IS_SWAP_FROM_SSE and we'll do the right thing.
|
||||
*/
|
||||
Page = MmGetPfnForProcess(Process, Address);
|
||||
|
||||
Protect = PAGE_READONLY;
|
||||
|
||||
Reference in New Issue
Block a user