[NTOSKRNL]

Remove PAGEOPs and use the argument to pass relevant information where needed,
including generally a section page table entry or a PFN_NUMBER.

In its place, the code looks for an MM_WAIT_ENTRY in the appropriate place and
waits, returning STATUS_MM_RESTART_OPERATION.  Rather than copying the pagein
and CoW operations in the PAGEOP contention case, we just punt back and restart
the operation, resulting in simpler code.

svn path=/trunk/; revision=56441
This commit is contained in:
Art Yerkes 2012-04-28 02:56:31 +00:00
parent 4d93b7e8d5
commit b621664add
6 changed files with 128 additions and 379 deletions

View file

@ -229,7 +229,6 @@ list(APPEND SOURCE
mm/mmfault.c mm/mmfault.c
mm/mminit.c mm/mminit.c
mm/pagefile.c mm/pagefile.c
mm/pageop.c
mm/region.c mm/region.c
mm/rmap.c mm/rmap.c
mm/section.c mm/section.c

View file

@ -215,8 +215,9 @@ _MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
ASSERT(!Entry || IS_SWAP_FROM_SSE(Entry)); ASSERT(!Entry || IS_SWAP_FROM_SSE(Entry));
MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry)); MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry));
} else if (IS_SWAP_FROM_SSE(Entry)) { } else if (IS_SWAP_FROM_SSE(Entry)) {
ASSERT(!IS_SWAP_FROM_SSE(OldEntry)); ASSERT(!IS_SWAP_FROM_SSE(OldEntry) ||
if (OldEntry) SWAPENTRY_FROM_SSE(OldEntry) == MM_WAIT_ENTRY);
if (OldEntry && SWAPENTRY_FROM_SSE(OldEntry) != MM_WAIT_ENTRY)
MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry)); MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry));
} else if (IS_SWAP_FROM_SSE(OldEntry)) { } else if (IS_SWAP_FROM_SSE(OldEntry)) {
ASSERT(!IS_SWAP_FROM_SSE(Entry)); ASSERT(!IS_SWAP_FROM_SSE(Entry));

View file

@ -49,7 +49,6 @@ extern PMMPTE MmDebugPte;
struct _KTRAP_FRAME; struct _KTRAP_FRAME;
struct _EPROCESS; struct _EPROCESS;
struct _MM_RMAP_ENTRY; struct _MM_RMAP_ENTRY;
struct _MM_PAGEOP;
typedef ULONG_PTR SWAPENTRY; typedef ULONG_PTR SWAPENTRY;
// //
@ -84,12 +83,6 @@ typedef ULONG_PTR SWAPENTRY;
#define MM_CORE_DUMP_TYPE_MINIMAL (0x1) #define MM_CORE_DUMP_TYPE_MINIMAL (0x1)
#define MM_CORE_DUMP_TYPE_FULL (0x2) #define MM_CORE_DUMP_TYPE_FULL (0x2)
#define MM_PAGEOP_PAGEIN (1)
#define MM_PAGEOP_PAGEOUT (2)
#define MM_PAGEOP_PAGESYNCH (3)
#define MM_PAGEOP_ACCESSFAULT (4)
#define MM_PAGEOP_CHANGEPROTECT (5)
/* Number of list heads to use */ /* Number of list heads to use */
#define MI_FREE_POOL_LISTS 4 #define MI_FREE_POOL_LISTS 4
@ -415,37 +408,6 @@ extern MMPFNLIST MmStandbyPageListHead;
extern MMPFNLIST MmModifiedPageListHead; extern MMPFNLIST MmModifiedPageListHead;
extern MMPFNLIST MmModifiedNoWritePageListHead; extern MMPFNLIST MmModifiedNoWritePageListHead;
typedef struct _MM_PAGEOP
{
/* Type of operation. */
ULONG OpType;
/* Number of threads interested in this operation. */
ULONG ReferenceCount;
/* Event that will be set when the operation is completed. */
KEVENT CompletionEvent;
/* Status of the operation once it is completed. */
NTSTATUS Status;
/* TRUE if the operation was abandoned. */
BOOLEAN Abandoned;
/* The memory area to be affected by the operation. */
PMEMORY_AREA MArea;
ULONG Hash;
struct _MM_PAGEOP* Next;
struct _ETHREAD* Thread;
/*
* These fields are used to identify the operation if it is against a
* virtual memory area.
*/
HANDLE Pid;
PVOID Address;
/*
* These fields are used to identify the operation if it is against a
* section mapping.
*/
PMM_SECTION_SEGMENT Segment;
ULONGLONG Offset;
} MM_PAGEOP, *PMM_PAGEOP;
typedef struct _MM_MEMORY_CONSUMER typedef struct _MM_MEMORY_CONSUMER
{ {
ULONG PagesUsed; ULONG PagesUsed;
@ -937,7 +899,7 @@ MmPageOutVirtualMemory(
PMMSUPPORT AddressSpace, PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea, PMEMORY_AREA MemoryArea,
PVOID Address, PVOID Address,
struct _MM_PAGEOP* PageOp PFN_NUMBER Page
); );
NTSTATUS NTSTATUS
@ -973,7 +935,7 @@ MmWritePageVirtualMemory(
PMMSUPPORT AddressSpace, PMMSUPPORT AddressSpace,
PMEMORY_AREA MArea, PMEMORY_AREA MArea,
PVOID Address, PVOID Address,
PMM_PAGEOP PageOp PFN_NUMBER Page
); );
/* kmap.c ********************************************************************/ /* kmap.c ********************************************************************/
@ -1007,38 +969,6 @@ PVOID
FASTCALL FASTCALL
MmSafeReadPtr(PVOID Source); MmSafeReadPtr(PVOID Source);
/* pageop.c ******************************************************************/
VOID
NTAPI
MmReleasePageOp(PMM_PAGEOP PageOp);
PMM_PAGEOP
NTAPI
MmGetPageOp(
PMEMORY_AREA MArea,
HANDLE Pid,
PVOID Address,
PMM_SECTION_SEGMENT Segment,
ULONGLONG Offset,
ULONG OpType,
BOOLEAN First
);
PMM_PAGEOP
NTAPI
MmCheckForPageOp(
PMEMORY_AREA MArea,
HANDLE Pid,
PVOID Address,
PMM_SECTION_SEGMENT Segment,
ULONGLONG Offset
);
VOID
NTAPI
MmInitializePageOp(VOID);
/* process.c *****************************************************************/ /* process.c *****************************************************************/
PVOID PVOID
@ -1657,7 +1587,7 @@ MmPageOutSectionView(
PMMSUPPORT AddressSpace, PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea, PMEMORY_AREA MemoryArea,
PVOID Address, PVOID Address,
struct _MM_PAGEOP *PageOp ULONG_PTR Entry
); );
NTSTATUS NTSTATUS

View file

@ -419,7 +419,6 @@ MmInitSystem(IN ULONG Phase,
MiInitializeUserPfnBitmap(); MiInitializeUserPfnBitmap();
MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory); MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
MmInitializeRmapList(); MmInitializeRmapList();
MmInitializePageOp();
MmInitSectionImplementation(); MmInitSectionImplementation();
MmInitPagingFile(); MmInitPagingFile();

View file

@ -52,7 +52,6 @@ MmPageOutPhysicalAddress(PFN_NUMBER Page)
ULONG Type; ULONG Type;
PVOID Address; PVOID Address;
PEPROCESS Process; PEPROCESS Process;
PMM_PAGEOP PageOp;
ULONGLONG Offset; ULONGLONG Offset;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
@ -126,17 +125,20 @@ MmPageOutPhysicalAddress(PFN_NUMBER Page)
Type = MemoryArea->Type; Type = MemoryArea->Type;
if (Type == MEMORY_AREA_SECTION_VIEW) if (Type == MEMORY_AREA_SECTION_VIEW)
{ {
ULONG Entry;
Offset = MemoryArea->Data.SectionData.ViewOffset.QuadPart + Offset = MemoryArea->Data.SectionData.ViewOffset.QuadPart +
((ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress); ((ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress);
MmLockSectionSegment(MemoryArea->Data.SectionData.Segment);
/* /*
* Get or create a pageop * Get or create a pageop
*/ */
PageOp = MmGetPageOp(MemoryArea, NULL, 0, Entry = MmGetPageEntrySectionSegment
MemoryArea->Data.SectionData.Segment, (MemoryArea->Data.SectionData.Segment, (PLARGE_INTEGER)&Offset);
Offset, MM_PAGEOP_PAGEOUT, TRUE); if (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
if (PageOp == NULL)
{ {
MmUnlockSectionSegment(MemoryArea->Data.SectionData.Segment);
MmUnlockAddressSpace(AddressSpace); MmUnlockAddressSpace(AddressSpace);
if (Address < MmSystemRangeStart) if (Address < MmSystemRangeStart)
{ {
@ -146,16 +148,18 @@ MmPageOutPhysicalAddress(PFN_NUMBER Page)
return(STATUS_UNSUCCESSFUL); return(STATUS_UNSUCCESSFUL);
} }
MmSetPageEntrySectionSegment(MemoryArea->Data.SectionData.Segment, (PLARGE_INTEGER)&Offset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
/* /*
* Release locks now we have a page op. * Release locks now we have a page op.
*/ */
MmUnlockSectionSegment(MemoryArea->Data.SectionData.Segment);
MmUnlockAddressSpace(AddressSpace); MmUnlockAddressSpace(AddressSpace);
/* /*
* Do the actual page out work. * Do the actual page out work.
*/ */
Status = MmPageOutSectionView(AddressSpace, MemoryArea, Status = MmPageOutSectionView(AddressSpace, MemoryArea, Address, Entry);
Address, PageOp);
} }
else if (Type == MEMORY_AREA_CACHE) else if (Type == MEMORY_AREA_CACHE)
{ {

View file

@ -127,6 +127,7 @@ typedef struct
BOOLEAN WasDirty; BOOLEAN WasDirty;
BOOLEAN Private; BOOLEAN Private;
PEPROCESS CallingProcess; PEPROCESS CallingProcess;
ULONG_PTR SectionEntry;
} }
MM_SECTION_PAGEOUT_CONTEXT; MM_SECTION_PAGEOUT_CONTEXT;
@ -704,43 +705,6 @@ l_Return:
return nStatus; return nStatus;
} }
/* Note: Mmsp prefix denotes "Memory Manager Section Private". */
/*
* FUNCTION: Waits in kernel mode up to ten seconds for an MM_PAGEOP event.
* ARGUMENTS: PMM_PAGEOP which event we should wait for.
* RETURNS: Status of the wait.
*/
static NTSTATUS
MmspWaitForPageOpCompletionEvent(PMM_PAGEOP PageOp)
{
LARGE_INTEGER Timeout;
#ifdef __GNUC__ /* TODO: Use other macro to check for suffix to use? */
Timeout.QuadPart = -100000000LL; // 10 sec
#else
Timeout.QuadPart = -100000000; // 10 sec
#endif
return KeWaitForSingleObject(&PageOp->CompletionEvent, 0, KernelMode, FALSE, &Timeout);
}
/*
* FUNCTION: Sets the page op completion event and releases the page op.
* ARGUMENTS: PMM_PAGEOP.
* RETURNS: In shorter time than it takes you to even read this
* description, so don't even think about geting a mug of coffee.
*/
static void
MmspCompleteAndReleasePageOp(PMM_PAGEOP PageOp)
{
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
}
/* /*
* FUNCTION: Waits in kernel mode indefinitely for a file object lock. * FUNCTION: Waits in kernel mode indefinitely for a file object lock.
* ARGUMENTS: PFILE_OBJECT to wait for. * ARGUMENTS: PFILE_OBJECT to wait for.
@ -831,12 +795,12 @@ MmUnsharePageEntrySectionSegment(PROS_SECTION_OBJECT Section,
PMM_SECTION_SEGMENT Segment, PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER Offset, PLARGE_INTEGER Offset,
BOOLEAN Dirty, BOOLEAN Dirty,
BOOLEAN PageOut) BOOLEAN PageOut,
ULONG_PTR *InEntry)
{ {
ULONG_PTR Entry; ULONG_PTR Entry = InEntry ? *InEntry : MmGetPageEntrySectionSegment(Segment, Offset);
BOOLEAN IsDirectMapped = FALSE; BOOLEAN IsDirectMapped = FALSE;
Entry = MmGetPageEntrySectionSegment(Segment, Offset);
if (Entry == 0) if (Entry == 0)
{ {
DPRINT1("Entry == 0 for MmUnsharePageEntrySectionSegment\n"); DPRINT1("Entry == 0 for MmUnsharePageEntrySectionSegment\n");
@ -844,7 +808,7 @@ MmUnsharePageEntrySectionSegment(PROS_SECTION_OBJECT Section,
} }
if (SHARE_COUNT_FROM_SSE(Entry) == 0) if (SHARE_COUNT_FROM_SSE(Entry) == 0)
{ {
DPRINT1("Zero share count for unshare\n"); DPRINT1("Zero share count for unshare (Seg %p Offset %x Page %x)\n", Segment, Offset->LowPart, PFN_FROM_SSE(Entry));
KeBugCheck(MEMORY_MANAGEMENT); KeBugCheck(MEMORY_MANAGEMENT);
} }
if (IS_SWAP_FROM_SSE(Entry)) if (IS_SWAP_FROM_SSE(Entry))
@ -913,10 +877,14 @@ MmUnsharePageEntrySectionSegment(PROS_SECTION_OBJECT Section,
* page without a rmap entry. * page without a rmap entry.
*/ */
MmSetPageEntrySectionSegment(Segment, Offset, Entry); MmSetPageEntrySectionSegment(Segment, Offset, Entry);
if (InEntry) *InEntry = Entry;
MiSetPageEvent(NULL, NULL);
} }
else else
{ {
MmSetPageEntrySectionSegment(Segment, Offset, 0); MmSetPageEntrySectionSegment(Segment, Offset, 0);
if (InEntry) *InEntry = 0;
MiSetPageEvent(NULL, NULL);
if (!IsDirectMapped) if (!IsDirectMapped)
{ {
MmReleasePageMemoryConsumer(MC_USER, Page); MmReleasePageMemoryConsumer(MC_USER, Page);
@ -946,7 +914,9 @@ MmUnsharePageEntrySectionSegment(PROS_SECTION_OBJECT Section,
} }
} }
MmSetPageEntrySectionSegment(Segment, Offset, MAKE_SWAP_SSE(SavedSwapEntry)); MmSetPageEntrySectionSegment(Segment, Offset, MAKE_SWAP_SSE(SavedSwapEntry));
if (InEntry) *InEntry = MAKE_SWAP_SSE(SavedSwapEntry);
MmSetSavedSwapEntryPage(Page, 0); MmSetSavedSwapEntryPage(Page, 0);
MiSetPageEvent(NULL, NULL);
} }
MmReleasePageMemoryConsumer(MC_USER, Page); MmReleasePageMemoryConsumer(MC_USER, Page);
} }
@ -959,6 +929,9 @@ MmUnsharePageEntrySectionSegment(PROS_SECTION_OBJECT Section,
} }
else else
{ {
if (InEntry)
*InEntry = Entry;
else
MmSetPageEntrySectionSegment(Segment, Offset, Entry); MmSetPageEntrySectionSegment(Segment, Offset, Entry);
} }
return(SHARE_COUNT_FROM_SSE(Entry) > 0); return(SHARE_COUNT_FROM_SSE(Entry) > 0);
@ -1232,7 +1205,6 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
ULONG_PTR Entry; ULONG_PTR Entry;
ULONG_PTR Entry1; ULONG_PTR Entry1;
ULONG Attributes; ULONG Attributes;
PMM_PAGEOP PageOp;
PMM_REGION Region; PMM_REGION Region;
BOOLEAN HasSwapEntry; BOOLEAN HasSwapEntry;
PVOID PAddress; PVOID PAddress;
@ -1270,7 +1242,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
* Lock the segment * Lock the segment
*/ */
MmLockSectionSegment(Segment); MmLockSectionSegment(Segment);
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
/* /*
* Check if this page needs to be mapped COW * Check if this page needs to be mapped COW
*/ */
@ -1285,112 +1257,42 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
Attributes = Region->Protect; Attributes = Region->Protect;
} }
/*
* Get or create a page operation descriptor
*/
PageOp = MmGetPageOp(MemoryArea, NULL, 0, Segment, Offset.LowPart, MM_PAGEOP_PAGEIN, FALSE);
if (PageOp == NULL)
{
DPRINT1("MmGetPageOp failed\n");
KeBugCheck(MEMORY_MANAGEMENT);
}
/* /*
* Check if someone else is already handling this fault, if so wait * Check if someone else is already handling this fault, if so wait
* for them * for them
*/ */
if (PageOp->Thread != PsGetCurrentThread()) if (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
{ {
MmUnlockSectionSegment(Segment); MmUnlockSectionSegment(Segment);
MmUnlockAddressSpace(AddressSpace); MmUnlockAddressSpace(AddressSpace);
Status = MmspWaitForPageOpCompletionEvent(PageOp); MiWaitForPageEvent(NULL, NULL);
/*
* Check for various strange conditions
*/
if (Status != STATUS_SUCCESS)
{
DPRINT1("Failed to wait for page op, status = %x\n", Status);
KeBugCheck(MEMORY_MANAGEMENT);
}
if (PageOp->Status == STATUS_PENDING)
{
DPRINT1("Woke for page op before completion\n");
KeBugCheck(MEMORY_MANAGEMENT);
}
MmLockAddressSpace(AddressSpace); MmLockAddressSpace(AddressSpace);
/*
* If this wasn't a pagein then restart the operation
*/
if (PageOp->OpType != MM_PAGEOP_PAGEIN)
{
MmspCompleteAndReleasePageOp(PageOp);
DPRINT("Address 0x%.8X\n", Address); DPRINT("Address 0x%.8X\n", Address);
return(STATUS_MM_RESTART_OPERATION); return(STATUS_MM_RESTART_OPERATION);
} }
/*
* If the thread handling this fault has failed then we don't retry
*/
if (!NT_SUCCESS(PageOp->Status))
{
Status = PageOp->Status;
MmspCompleteAndReleasePageOp(PageOp);
DPRINT("Address 0x%.8X\n", Address);
return(Status);
}
MmLockSectionSegment(Segment);
/*
* If the completed fault was for another address space then set the
* page in this one.
*/
if (!MmIsPagePresent(Process, Address))
{
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
HasSwapEntry = MmIsPageSwapEntry(Process, (PVOID)PAddress);
if (PAGE_FROM_SSE(Entry) == 0 || HasSwapEntry)
{
/*
* The page was a private page in another or in our address space
*/
MmUnlockSectionSegment(Segment);
MmspCompleteAndReleasePageOp(PageOp);
return(STATUS_MM_RESTART_OPERATION);
}
Page = PFN_FROM_SSE(Entry);
MmSharePageEntrySectionSegment(Segment, &Offset);
/* FIXME: Should we call MmCreateVirtualMappingUnsafe if
* (Section->AllocationAttributes & SEC_PHYSICALMEMORY) is true?
*/
Status = MmCreateVirtualMapping(Process,
PAddress,
Attributes,
&Page,
1);
if (!NT_SUCCESS(Status))
{
DPRINT1("Unable to create virtual mapping\n");
KeBugCheck(MEMORY_MANAGEMENT);
}
MmInsertRmap(Page, Process, Address);
}
MmUnlockSectionSegment(Segment);
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
}
HasSwapEntry = MmIsPageSwapEntry(Process, Address); HasSwapEntry = MmIsPageSwapEntry(Process, Address);
if (HasSwapEntry) if (HasSwapEntry)
{ {
SWAPENTRY SwapEntry;
/*
* Is it a wait entry?
*/
MmGetPageFileMapping(Process, Address, &SwapEntry);
if (SwapEntry == MM_WAIT_ENTRY)
{
MmUnlockSectionSegment(Segment);
MmUnlockAddressSpace(AddressSpace);
MiWaitForPageEvent(NULL, NULL);
MmLockAddressSpace(AddressSpace);
return STATUS_MM_RESTART_OPERATION;
}
/* /*
* Must be private page we have swapped out. * Must be private page we have swapped out.
*/ */
SWAPENTRY SwapEntry;
/* /*
* Sanity check * Sanity check
@ -1445,8 +1347,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
/* /*
* Finish the operation * Finish the operation
*/ */
PageOp->Status = STATUS_SUCCESS; MiSetPageEvent(Process, Address);
MmspCompleteAndReleasePageOp(PageOp);
DPRINT("Address 0x%.8X\n", Address); DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
@ -1476,8 +1377,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
/* /*
* Cleanup and release locks * Cleanup and release locks
*/ */
PageOp->Status = STATUS_SUCCESS; MiSetPageEvent(Process, Address);
MmspCompleteAndReleasePageOp(PageOp);
DPRINT("Address 0x%.8X\n", Address); DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
@ -1518,8 +1418,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
/* /*
* Cleanup and release locks * Cleanup and release locks
*/ */
PageOp->Status = STATUS_SUCCESS; MiSetPageEvent(Process, Address);
MmspCompleteAndReleasePageOp(PageOp);
DPRINT("Address 0x%.8X\n", Address); DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
@ -1539,6 +1438,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
/* /*
* Release all our locks and read in the page from disk * Release all our locks and read in the page from disk
*/ */
MmSetPageEntrySectionSegment(Segment, &Offset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
MmUnlockSectionSegment(Segment); MmUnlockSectionSegment(Segment);
MmUnlockAddressSpace(AddressSpace); MmUnlockAddressSpace(AddressSpace);
@ -1573,32 +1473,17 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
* Cleanup and release locks * Cleanup and release locks
*/ */
MmLockAddressSpace(AddressSpace); MmLockAddressSpace(AddressSpace);
PageOp->Status = Status; MiSetPageEvent(Process, Address);
MmspCompleteAndReleasePageOp(PageOp);
DPRINT("Address 0x%.8X\n", Address); DPRINT("Address 0x%.8X\n", Address);
return(Status); return(Status);
} }
/*
* Relock the address space and segment
*/
MmLockAddressSpace(AddressSpace);
MmLockSectionSegment(Segment);
/*
* Check the entry. No one should change the status of a page
* that has a pending page-in.
*/
Entry1 = MmGetPageEntrySectionSegment(Segment, &Offset);
if (Entry != Entry1)
{
DPRINT1("Someone changed ppte entry while we slept\n");
KeBugCheck(MEMORY_MANAGEMENT);
}
/* /*
* Mark the offset within the section as having valid, in-memory * Mark the offset within the section as having valid, in-memory
* data * data
*/ */
MmLockAddressSpace(AddressSpace);
MmLockSectionSegment(Segment);
Entry = MAKE_SSE(Page << PAGE_SHIFT, 1); Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
MmSetPageEntrySectionSegment(Segment, &Offset, Entry); MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
MmUnlockSectionSegment(Segment); MmUnlockSectionSegment(Segment);
@ -1615,8 +1500,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
} }
MmInsertRmap(Page, Process, Address); MmInsertRmap(Page, Process, Address);
PageOp->Status = STATUS_SUCCESS; MiSetPageEvent(Process, Address);
MmspCompleteAndReleasePageOp(PageOp);
DPRINT("Address 0x%.8X\n", Address); DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
@ -1660,7 +1544,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
Entry1 = MmGetPageEntrySectionSegment(Segment, &Offset); Entry1 = MmGetPageEntrySectionSegment(Segment, &Offset);
if (Entry != Entry1) if (Entry != Entry1)
{ {
DPRINT1("Someone changed ppte entry while we slept\n"); DPRINT1("Someone changed ppte entry while we slept (%x vs %x)\n", Entry, Entry1);
KeBugCheck(MEMORY_MANAGEMENT); KeBugCheck(MEMORY_MANAGEMENT);
} }
@ -1687,8 +1571,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
KeBugCheck(MEMORY_MANAGEMENT); KeBugCheck(MEMORY_MANAGEMENT);
} }
MmInsertRmap(Page, Process, Address); MmInsertRmap(Page, Process, Address);
PageOp->Status = STATUS_SUCCESS; MiSetPageEvent(Process, Address);
MmspCompleteAndReleasePageOp(PageOp);
DPRINT("Address 0x%.8X\n", Address); DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
@ -1715,8 +1598,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
KeBugCheck(MEMORY_MANAGEMENT); KeBugCheck(MEMORY_MANAGEMENT);
} }
MmInsertRmap(Page, Process, Address); MmInsertRmap(Page, Process, Address);
PageOp->Status = STATUS_SUCCESS; MiSetPageEvent(Process, Address);
MmspCompleteAndReleasePageOp(PageOp);
DPRINT("Address 0x%.8X\n", Address); DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
@ -1735,7 +1617,6 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
NTSTATUS Status; NTSTATUS Status;
PVOID PAddress; PVOID PAddress;
LARGE_INTEGER Offset; LARGE_INTEGER Offset;
PMM_PAGEOP PageOp;
PMM_REGION Region; PMM_REGION Region;
ULONG_PTR Entry; ULONG_PTR Entry;
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace); PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
@ -1799,39 +1680,21 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
/* /*
* Get or create a pageop * Get or create a pageop
*/ */
PageOp = MmGetPageOp(MemoryArea, NULL, 0, Segment, Offset.LowPart, MmLockSectionSegment(Segment);
MM_PAGEOP_ACCESSFAULT, FALSE); Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
if (PageOp == NULL)
{
DPRINT1("MmGetPageOp failed\n");
KeBugCheck(MEMORY_MANAGEMENT);
}
/* /*
* Wait for any other operations to complete * Wait for any other operations to complete
*/ */
if (PageOp->Thread != PsGetCurrentThread()) if (Entry == SWAPENTRY_FROM_SSE(MM_WAIT_ENTRY))
{ {
MmUnlockSectionSegment(Segment);
MmUnlockAddressSpace(AddressSpace); MmUnlockAddressSpace(AddressSpace);
Status = MmspWaitForPageOpCompletionEvent(PageOp); MiWaitForPageEvent(NULL, NULL);
/*
* Check for various strange conditions
*/
if (Status == STATUS_TIMEOUT)
{
DPRINT1("Failed to wait for page op, status = %x\n", Status);
KeBugCheck(MEMORY_MANAGEMENT);
}
if (PageOp->Status == STATUS_PENDING)
{
DPRINT1("Woke for page op before completion\n");
KeBugCheck(MEMORY_MANAGEMENT);
}
/* /*
* Restart the operation * Restart the operation
*/ */
MmLockAddressSpace(AddressSpace); MmLockAddressSpace(AddressSpace);
MmspCompleteAndReleasePageOp(PageOp);
DPRINT("Address 0x%.8X\n", Address); DPRINT("Address 0x%.8X\n", Address);
return(STATUS_MM_RESTART_OPERATION); return(STATUS_MM_RESTART_OPERATION);
} }
@ -1839,6 +1702,7 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
/* /*
* Release locks now we have the pageop * Release locks now we have the pageop
*/ */
MmUnlockSectionSegment(Segment);
MmUnlockAddressSpace(AddressSpace); MmUnlockAddressSpace(AddressSpace);
/* /*
@ -1890,11 +1754,10 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
MmDeleteRmap(OldPage, Process, PAddress); MmDeleteRmap(OldPage, Process, PAddress);
MmInsertRmap(NewPage, Process, PAddress); MmInsertRmap(NewPage, Process, PAddress);
MmLockSectionSegment(Segment); MmLockSectionSegment(Segment);
MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, FALSE, FALSE); MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, FALSE, FALSE, NULL);
MmUnlockSectionSegment(Segment); MmUnlockSectionSegment(Segment);
PageOp->Status = STATUS_SUCCESS; MiSetPageEvent(Process, Address);
MmspCompleteAndReleasePageOp(PageOp);
DPRINT("Address 0x%.8X\n", Address); DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
@ -1904,7 +1767,7 @@ MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address)
{ {
MM_SECTION_PAGEOUT_CONTEXT* PageOutContext; MM_SECTION_PAGEOUT_CONTEXT* PageOutContext;
BOOLEAN WasDirty; BOOLEAN WasDirty;
PFN_NUMBER Page; PFN_NUMBER Page = 0;
PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context; PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context;
if (Process) if (Process)
@ -1928,7 +1791,8 @@ MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address)
PageOutContext->Segment, PageOutContext->Segment,
&PageOutContext->Offset, &PageOutContext->Offset,
PageOutContext->WasDirty, PageOutContext->WasDirty,
TRUE); TRUE,
&PageOutContext->SectionEntry);
MmUnlockSectionSegment(PageOutContext->Segment); MmUnlockSectionSegment(PageOutContext->Segment);
} }
if (Process) if (Process)
@ -1940,21 +1804,17 @@ MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address)
{ {
MmReleasePageMemoryConsumer(MC_USER, Page); MmReleasePageMemoryConsumer(MC_USER, Page);
} }
DPRINT("PhysicalAddress %x, Address %x\n", Page << PAGE_SHIFT, Address);
} }
NTSTATUS NTSTATUS
NTAPI NTAPI
MmPageOutSectionView(PMMSUPPORT AddressSpace, MmPageOutSectionView(PMMSUPPORT AddressSpace,
MEMORY_AREA* MemoryArea, MEMORY_AREA* MemoryArea,
PVOID Address, PVOID Address, ULONG_PTR Entry)
PMM_PAGEOP PageOp)
{ {
PFN_NUMBER Page; PFN_NUMBER Page;
MM_SECTION_PAGEOUT_CONTEXT Context; MM_SECTION_PAGEOUT_CONTEXT Context;
SWAPENTRY SwapEntry; SWAPENTRY SwapEntry;
ULONG_PTR Entry;
ULONGLONG FileOffset; ULONGLONG FileOffset;
NTSTATUS Status; NTSTATUS Status;
PFILE_OBJECT FileObject; PFILE_OBJECT FileObject;
@ -1973,6 +1833,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
*/ */
Context.Segment = MemoryArea->Data.SectionData.Segment; Context.Segment = MemoryArea->Data.SectionData.Segment;
Context.Section = MemoryArea->Data.SectionData.Section; Context.Section = MemoryArea->Data.SectionData.Section;
Context.SectionEntry = Entry;
Context.CallingProcess = Process; Context.CallingProcess = Process;
Context.Offset.QuadPart = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress Context.Offset.QuadPart = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
@ -1984,6 +1845,8 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
FileObject = Context.Section->FileObject; FileObject = Context.Section->FileObject;
DirectMapped = FALSE; DirectMapped = FALSE;
MmLockSectionSegment(Context.Segment);
#ifndef NEWCC #ifndef NEWCC
if (FileObject != NULL && if (FileObject != NULL &&
!(Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED)) !(Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED))
@ -2035,16 +1898,14 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
{ {
DPRINT("Cannot page out locked section page: 0x%p (RefCount: %d)\n", DPRINT("Cannot page out locked section page: 0x%p (RefCount: %d)\n",
Page, MmGetReferenceCountPage(Page)); Page, MmGetReferenceCountPage(Page));
PageOp->Status = STATUS_UNSUCCESSFUL; MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
MmspCompleteAndReleasePageOp(PageOp); MmUnlockSectionSegment(Context.Segment);
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
/* /*
* Prepare the context structure for the rmap delete call. * Prepare the context structure for the rmap delete call.
*/ */
MmLockSectionSegment(Context.Segment);
Entry = MmGetPageEntrySectionSegment(Context.Segment, &Context.Offset);
MmUnlockSectionSegment(Context.Segment); MmUnlockSectionSegment(Context.Segment);
Context.WasDirty = FALSE; Context.WasDirty = FALSE;
if (Context.Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA || if (Context.Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
@ -2077,9 +1938,12 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
} }
MmDeleteAllRmaps(Page, (PVOID)&Context, MmPageOutDeleteMapping); MmDeleteAllRmaps(Page, (PVOID)&Context, MmPageOutDeleteMapping);
MmLockSectionSegment(Context.Segment);
Entry = MmGetPageEntrySectionSegment(Context.Segment, &Context.Offset); /* Since we passed in a surrogate, we'll get back the page entry
MmUnlockSectionSegment(Context.Segment); * state in our context. This is intended to make intermediate
* decrements of share count not release the wait entry.
*/
Entry = Context.SectionEntry;
/* /*
* If this wasn't a private page then we should have reduced the entry to * If this wasn't a private page then we should have reduced the entry to
@ -2117,8 +1981,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry)); MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry));
MmUnlockSectionSegment(Context.Segment); MmUnlockSectionSegment(Context.Segment);
MmReleasePageMemoryConsumer(MC_USER, Page); MmReleasePageMemoryConsumer(MC_USER, Page);
PageOp->Status = STATUS_SUCCESS; MiSetPageEvent(NULL, NULL);
MmspCompleteAndReleasePageOp(PageOp);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
} }
@ -2140,8 +2003,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
MmUnlockSectionSegment(Context.Segment); MmUnlockSectionSegment(Context.Segment);
} }
MmReleasePageMemoryConsumer(MC_USER, Page); MmReleasePageMemoryConsumer(MC_USER, Page);
PageOp->Status = STATUS_SUCCESS; MiSetPageEvent(NULL, NULL);
MmspCompleteAndReleasePageOp(PageOp);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
} }
@ -2165,8 +2027,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Bcb, (ULONG_PTR)FileOffset, (ULONG_PTR)Address); KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Bcb, (ULONG_PTR)FileOffset, (ULONG_PTR)Address);
} }
#endif #endif
PageOp->Status = STATUS_SUCCESS; MiSetPageEvent(NULL, NULL);
MmspCompleteAndReleasePageOp(PageOp);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
else if (!Context.WasDirty && !DirectMapped && !Context.Private) else if (!Context.WasDirty && !DirectMapped && !Context.Private)
@ -2178,13 +2039,12 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
KeBugCheckEx(MEMORY_MANAGEMENT, SwapEntry, Page, (ULONG_PTR)Process, (ULONG_PTR)Address); KeBugCheckEx(MEMORY_MANAGEMENT, SwapEntry, Page, (ULONG_PTR)Process, (ULONG_PTR)Address);
} }
MmReleasePageMemoryConsumer(MC_USER, Page); MmReleasePageMemoryConsumer(MC_USER, Page);
PageOp->Status = STATUS_SUCCESS; MiSetPageEvent(NULL, NULL);
MmspCompleteAndReleasePageOp(PageOp);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
else if (!Context.WasDirty && Context.Private && SwapEntry != 0) else if (!Context.WasDirty && Context.Private && SwapEntry != 0)
{ {
DPRINT1("Not dirty and private and not swapped (%p:%p)\n", Process, Address); DPRINT("Not dirty and private and not swapped (%p:%p)\n", Process, Address);
MmSetSavedSwapEntryPage(Page, 0); MmSetSavedSwapEntryPage(Page, 0);
MmLockAddressSpace(AddressSpace); MmLockAddressSpace(AddressSpace);
Status = MmCreatePageFileMapping(Process, Status = MmCreatePageFileMapping(Process,
@ -2197,8 +2057,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Process, (ULONG_PTR)Address, SwapEntry); KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Process, (ULONG_PTR)Address, SwapEntry);
} }
MmReleasePageMemoryConsumer(MC_USER, Page); MmReleasePageMemoryConsumer(MC_USER, Page);
PageOp->Status = STATUS_SUCCESS; MiSetPageEvent(NULL, NULL);
MmspCompleteAndReleasePageOp(PageOp);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
@ -2253,8 +2112,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
MmUnlockSectionSegment(Context.Segment); MmUnlockSectionSegment(Context.Segment);
} }
MmUnlockAddressSpace(AddressSpace); MmUnlockAddressSpace(AddressSpace);
PageOp->Status = STATUS_UNSUCCESSFUL; MiSetPageEvent(NULL, NULL);
MmspCompleteAndReleasePageOp(PageOp);
return(STATUS_PAGEFILE_QUOTA); return(STATUS_PAGEFILE_QUOTA);
} }
} }
@ -2299,8 +2157,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry); MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
} }
MmUnlockAddressSpace(AddressSpace); MmUnlockAddressSpace(AddressSpace);
PageOp->Status = STATUS_UNSUCCESSFUL; MiSetPageEvent(NULL, NULL);
MmspCompleteAndReleasePageOp(PageOp);
return(STATUS_UNSUCCESSFUL); return(STATUS_UNSUCCESSFUL);
} }
@ -2308,12 +2165,13 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
* Otherwise we have succeeded. * Otherwise we have succeeded.
*/ */
DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT); DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT);
MmLockSectionSegment(Context.Segment);
MmSetSavedSwapEntryPage(Page, 0); MmSetSavedSwapEntryPage(Page, 0);
if (Context.Segment->Flags & MM_PAGEFILE_SEGMENT || if (Context.Segment->Flags & MM_PAGEFILE_SEGMENT ||
Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED) Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED)
{ {
MmLockSectionSegment(Context.Segment);
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry)); MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry));
MmUnlockSectionSegment(Context.Segment);
} }
else else
{ {
@ -2323,9 +2181,11 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
if (Context.Private) if (Context.Private)
{ {
MmLockAddressSpace(AddressSpace); MmLockAddressSpace(AddressSpace);
MmLockSectionSegment(Context.Segment);
Status = MmCreatePageFileMapping(Process, Status = MmCreatePageFileMapping(Process,
Address, Address,
SwapEntry); SwapEntry);
MmUnlockSectionSegment(Context.Segment);
MmUnlockAddressSpace(AddressSpace); MmUnlockAddressSpace(AddressSpace);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
@ -2335,13 +2195,15 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
} }
else else
{ {
MmLockAddressSpace(AddressSpace);
MmLockSectionSegment(Context.Segment);
Entry = MAKE_SWAP_SSE(SwapEntry); Entry = MAKE_SWAP_SSE(SwapEntry);
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry); MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
MmUnlockSectionSegment(Context.Segment);
MmUnlockAddressSpace(AddressSpace);
} }
MmUnlockSectionSegment(Context.Segment); MiSetPageEvent(NULL, NULL);
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
@ -2350,7 +2212,7 @@ NTAPI
MmWritePageSectionView(PMMSUPPORT AddressSpace, MmWritePageSectionView(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea, PMEMORY_AREA MemoryArea,
PVOID Address, PVOID Address,
PMM_PAGEOP PageOp) ULONG PageEntry)
{ {
LARGE_INTEGER Offset; LARGE_INTEGER Offset;
PROS_SECTION_OBJECT Section; PROS_SECTION_OBJECT Section;
@ -2447,12 +2309,16 @@ MmWritePageSectionView(PMMSUPPORT AddressSpace,
*/ */
if (DirectMapped && !Private) if (DirectMapped && !Private)
{ {
LARGE_INTEGER SOffset;
ASSERT(SwapEntry == 0); ASSERT(SwapEntry == 0);
SOffset.QuadPart = Offset.QuadPart + Segment->Image.FileOffset;
#ifndef NEWCC #ifndef NEWCC
CcRosMarkDirtyCacheSegment(Bcb, (ULONG)(Offset.QuadPart + Segment->Image.FileOffset)); CcRosMarkDirtyCacheSegment(Bcb, Offset.LowPart);
#endif #endif
PageOp->Status = STATUS_SUCCESS; MmLockSectionSegment(Segment);
MmspCompleteAndReleasePageOp(PageOp); MmSetPageEntrySectionSegment(Segment, &Offset, PageEntry);
MmUnlockSectionSegment(Segment);
MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
@ -2465,8 +2331,7 @@ MmWritePageSectionView(PMMSUPPORT AddressSpace,
if (SwapEntry == 0) if (SwapEntry == 0)
{ {
MmSetDirtyAllRmaps(Page); MmSetDirtyAllRmaps(Page);
PageOp->Status = STATUS_UNSUCCESSFUL; MiSetPageEvent(NULL, NULL);
MmspCompleteAndReleasePageOp(PageOp);
return(STATUS_PAGEFILE_QUOTA); return(STATUS_PAGEFILE_QUOTA);
} }
MmSetSavedSwapEntryPage(Page, SwapEntry); MmSetSavedSwapEntryPage(Page, SwapEntry);
@ -2481,8 +2346,7 @@ MmWritePageSectionView(PMMSUPPORT AddressSpace,
DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n", DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
Status); Status);
MmSetDirtyAllRmaps(Page); MmSetDirtyAllRmaps(Page);
PageOp->Status = STATUS_UNSUCCESSFUL; MiSetPageEvent(NULL, NULL);
MmspCompleteAndReleasePageOp(PageOp);
return(STATUS_UNSUCCESSFUL); return(STATUS_UNSUCCESSFUL);
} }
@ -2490,8 +2354,7 @@ MmWritePageSectionView(PMMSUPPORT AddressSpace,
* Otherwise we have succeeded. * Otherwise we have succeeded.
*/ */
DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT); DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT);
PageOp->Status = STATUS_SUCCESS; MiSetPageEvent(NULL, NULL);
MmspCompleteAndReleasePageOp(PageOp);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
@ -4039,8 +3902,6 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
PBCB Bcb; PBCB Bcb;
LARGE_INTEGER Offset; LARGE_INTEGER Offset;
SWAPENTRY SavedSwapEntry; SWAPENTRY SavedSwapEntry;
PMM_PAGEOP PageOp;
NTSTATUS Status;
PROS_SECTION_OBJECT Section; PROS_SECTION_OBJECT Section;
PMM_SECTION_SEGMENT Segment; PMM_SECTION_SEGMENT Segment;
PMMSUPPORT AddressSpace; PMMSUPPORT AddressSpace;
@ -4057,27 +3918,18 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
Section = MemoryArea->Data.SectionData.Section; Section = MemoryArea->Data.SectionData.Section;
Segment = MemoryArea->Data.SectionData.Segment; Segment = MemoryArea->Data.SectionData.Segment;
PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL, Segment, Offset.LowPart); Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
while (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
while (PageOp)
{ {
MmUnlockSectionSegment(Segment); MmUnlockSectionSegment(Segment);
MmUnlockAddressSpace(AddressSpace); MmUnlockAddressSpace(AddressSpace);
Status = MmspWaitForPageOpCompletionEvent(PageOp); MiWaitForPageEvent(NULL, NULL);
if (Status != STATUS_SUCCESS)
{
DPRINT1("Failed to wait for page op, status = %x\n", Status);
KeBugCheck(MEMORY_MANAGEMENT);
}
MmLockAddressSpace(AddressSpace); MmLockAddressSpace(AddressSpace);
MmLockSectionSegment(Segment); MmLockSectionSegment(Segment);
MmspCompleteAndReleasePageOp(PageOp);
PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL, Segment, Offset.LowPart);
}
Entry = MmGetPageEntrySectionSegment(Segment, &Offset); Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
}
/* /*
* For a dirty, datafile, non-private page mark it as dirty in the * For a dirty, datafile, non-private page mark it as dirty in the
@ -4136,7 +3988,7 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
else else
{ {
MmDeleteRmap(Page, Process, Address); MmDeleteRmap(Page, Process, Address);
MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, Dirty, FALSE); MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, Dirty, FALSE, NULL);
} }
} }
} }
@ -4208,8 +4060,6 @@ MiRosUnmapViewOfSection(IN PEPROCESS Process,
PMEMORY_AREA MemoryArea; PMEMORY_AREA MemoryArea;
PMMSUPPORT AddressSpace; PMMSUPPORT AddressSpace;
PROS_SECTION_OBJECT Section; PROS_SECTION_OBJECT Section;
PMM_PAGEOP PageOp;
ULONG_PTR Offset;
PVOID ImageBaseAddress = 0; PVOID ImageBaseAddress = 0;
DPRINT("Opening memory area Process %x BaseAddress %x\n", DPRINT("Opening memory area Process %x BaseAddress %x\n",
@ -4233,40 +4083,6 @@ MiRosUnmapViewOfSection(IN PEPROCESS Process,
MemoryArea->DeleteInProgress = TRUE; MemoryArea->DeleteInProgress = TRUE;
while (MemoryArea->PageOpCount)
{
Offset = PAGE_ROUND_UP((ULONG_PTR)MemoryArea->EndingAddress - (ULONG_PTR)MemoryArea->StartingAddress);
while (Offset)
{
Offset -= PAGE_SIZE;
PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL,
MemoryArea->Data.SectionData.Segment,
Offset + MemoryArea->Data.SectionData.ViewOffset.QuadPart);
if (PageOp)
{
MmUnlockAddressSpace(AddressSpace);
Status = MmspWaitForPageOpCompletionEvent(PageOp);
if (Status != STATUS_SUCCESS)
{
DPRINT1("Failed to wait for page op, status = %x\n", Status);
KeBugCheck(MEMORY_MANAGEMENT);
}
MmLockAddressSpace(AddressSpace);
MmspCompleteAndReleasePageOp(PageOp);
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace,
BaseAddress);
if (MemoryArea == NULL ||
MemoryArea->Type != MEMORY_AREA_SECTION_VIEW)
{
MmUnlockAddressSpace(AddressSpace);
return STATUS_NOT_MAPPED_VIEW;
}
break;
}
}
}
Section = MemoryArea->Data.SectionData.Section; Section = MemoryArea->Data.SectionData.Section;
if (Section->AllocationAttributes & SEC_IMAGE) if (Section->AllocationAttributes & SEC_IMAGE)