Author: arty
Date: Thu May 3 21:05:06 2012
New Revision: 56488
URL:
http://svn.reactos.org/svn/reactos?rev=56488&view=rev
Log:
[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.
Modified:
trunk/reactos/ntoskrnl/cache/section/newmm.h
trunk/reactos/ntoskrnl/include/internal/mm.h
trunk/reactos/ntoskrnl/mm/i386/page.c
trunk/reactos/ntoskrnl/mm/section.c
Modified: trunk/reactos/ntoskrnl/cache/section/newmm.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cache/section/new…
==============================================================================
--- trunk/reactos/ntoskrnl/cache/section/newmm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/cache/section/newmm.h [iso-8859-1] Thu May 3 21:05:06 2012
@@ -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) \
Modified: trunk/reactos/ntoskrnl/include/internal/mm.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/mm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/mm.h [iso-8859-1] Thu May 3 21:05:06 2012
@@ -955,8 +955,8 @@
NTSTATUS
NTAPI
MiCopyFromUserPage(
- PFN_NUMBER Page,
- PVOID SourceAddress
+ PFN_NUMBER NewPage,
+ PFN_NUMBER OldPage
);
NTSTATUS
Modified: trunk/reactos/ntoskrnl/mm/i386/page.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/i386/page.c?re…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/i386/page.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/i386/page.c [iso-8859-1] Thu May 3 21:05:06 2012
@@ -558,6 +558,7 @@
if ((Pte & PA_PRESENT) || !(Pte & 0x800))
{
+ DPRINT1("Pte %x (want not 1 and 0x800)\n", Pte);
KeBugCheck(MEMORY_MANAGEMENT);
}
Modified: trunk/reactos/ntoskrnl/mm/section.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/section.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] Thu May 3 21:05:06 2012
@@ -959,22 +959,24 @@
NTSTATUS
NTAPI
-MiCopyFromUserPage(PFN_NUMBER DestPage, PVOID SourceAddress)
+MiCopyFromUserPage(PFN_NUMBER DestPage, PFN_NUMBER SrcPage)
{
PEPROCESS Process;
- KIRQL Irql;
- PVOID TempAddress;
-
- ASSERT((ULONG_PTR)SourceAddress % PAGE_SIZE == 0);
+ KIRQL Irql, Irql2;
+ PVOID DestAddress, SrcAddress;
+
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 @@
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 @@
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 @@
/*
* 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 @@
/*
* 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,8 +2392,17 @@
{
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
@@ -2404,6 +2417,10 @@
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;