[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/mminit.c
mm/pagefile.c
mm/pageop.c
mm/region.c
mm/rmap.c
mm/section.c

View file

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

View file

@ -49,7 +49,6 @@ extern PMMPTE MmDebugPte;
struct _KTRAP_FRAME;
struct _EPROCESS;
struct _MM_RMAP_ENTRY;
struct _MM_PAGEOP;
typedef ULONG_PTR SWAPENTRY;
//
@ -84,12 +83,6 @@ typedef ULONG_PTR SWAPENTRY;
#define MM_CORE_DUMP_TYPE_MINIMAL (0x1)
#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 */
#define MI_FREE_POOL_LISTS 4
@ -415,37 +408,6 @@ extern MMPFNLIST MmStandbyPageListHead;
extern MMPFNLIST MmModifiedPageListHead;
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
{
ULONG PagesUsed;
@ -937,7 +899,7 @@ MmPageOutVirtualMemory(
PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PVOID Address,
struct _MM_PAGEOP* PageOp
PFN_NUMBER Page
);
NTSTATUS
@ -973,7 +935,7 @@ MmWritePageVirtualMemory(
PMMSUPPORT AddressSpace,
PMEMORY_AREA MArea,
PVOID Address,
PMM_PAGEOP PageOp
PFN_NUMBER Page
);
/* kmap.c ********************************************************************/
@ -1007,38 +969,6 @@ PVOID
FASTCALL
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 *****************************************************************/
PVOID
@ -1657,7 +1587,7 @@ MmPageOutSectionView(
PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PVOID Address,
struct _MM_PAGEOP *PageOp
ULONG_PTR Entry
);
NTSTATUS

View file

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

View file

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

View file

@ -127,6 +127,7 @@ typedef struct
BOOLEAN WasDirty;
BOOLEAN Private;
PEPROCESS CallingProcess;
ULONG_PTR SectionEntry;
}
MM_SECTION_PAGEOUT_CONTEXT;
@ -704,43 +705,6 @@ l_Return:
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.
* ARGUMENTS: PFILE_OBJECT to wait for.
@ -831,12 +795,12 @@ MmUnsharePageEntrySectionSegment(PROS_SECTION_OBJECT Section,
PMM_SECTION_SEGMENT Segment,
PLARGE_INTEGER Offset,
BOOLEAN Dirty,
BOOLEAN PageOut)
BOOLEAN PageOut,
ULONG_PTR *InEntry)
{
ULONG_PTR Entry;
ULONG_PTR Entry = InEntry ? *InEntry : MmGetPageEntrySectionSegment(Segment, Offset);
BOOLEAN IsDirectMapped = FALSE;
Entry = MmGetPageEntrySectionSegment(Segment, Offset);
if (Entry == 0)
{
DPRINT1("Entry == 0 for MmUnsharePageEntrySectionSegment\n");
@ -844,7 +808,7 @@ MmUnsharePageEntrySectionSegment(PROS_SECTION_OBJECT Section,
}
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);
}
if (IS_SWAP_FROM_SSE(Entry))
@ -913,10 +877,14 @@ MmUnsharePageEntrySectionSegment(PROS_SECTION_OBJECT Section,
* page without a rmap entry.
*/
MmSetPageEntrySectionSegment(Segment, Offset, Entry);
if (InEntry) *InEntry = Entry;
MiSetPageEvent(NULL, NULL);
}
else
{
MmSetPageEntrySectionSegment(Segment, Offset, 0);
if (InEntry) *InEntry = 0;
MiSetPageEvent(NULL, NULL);
if (!IsDirectMapped)
{
MmReleasePageMemoryConsumer(MC_USER, Page);
@ -946,7 +914,9 @@ MmUnsharePageEntrySectionSegment(PROS_SECTION_OBJECT Section,
}
}
MmSetPageEntrySectionSegment(Segment, Offset, MAKE_SWAP_SSE(SavedSwapEntry));
if (InEntry) *InEntry = MAKE_SWAP_SSE(SavedSwapEntry);
MmSetSavedSwapEntryPage(Page, 0);
MiSetPageEvent(NULL, NULL);
}
MmReleasePageMemoryConsumer(MC_USER, Page);
}
@ -959,7 +929,10 @@ MmUnsharePageEntrySectionSegment(PROS_SECTION_OBJECT Section,
}
else
{
MmSetPageEntrySectionSegment(Segment, Offset, Entry);
if (InEntry)
*InEntry = Entry;
else
MmSetPageEntrySectionSegment(Segment, Offset, Entry);
}
return(SHARE_COUNT_FROM_SSE(Entry) > 0);
}
@ -1232,7 +1205,6 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
ULONG_PTR Entry;
ULONG_PTR Entry1;
ULONG Attributes;
PMM_PAGEOP PageOp;
PMM_REGION Region;
BOOLEAN HasSwapEntry;
PVOID PAddress;
@ -1270,7 +1242,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
* Lock the segment
*/
MmLockSectionSegment(Segment);
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
/*
* Check if this page needs to be mapped COW
*/
@ -1285,112 +1257,42 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
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
* for them
*/
if (PageOp->Thread != PsGetCurrentThread())
if (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
{
MmUnlockSectionSegment(Segment);
MmUnlockAddressSpace(AddressSpace);
Status = MmspWaitForPageOpCompletionEvent(PageOp);
/*
* 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);
}
MiWaitForPageEvent(NULL, NULL);
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);
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);
return(STATUS_MM_RESTART_OPERATION);
}
HasSwapEntry = MmIsPageSwapEntry(Process, Address);
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.
*/
SWAPENTRY SwapEntry;
/*
* Sanity check
@ -1445,8 +1347,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
/*
* Finish the operation
*/
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
MiSetPageEvent(Process, Address);
DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
}
@ -1476,8 +1377,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
/*
* Cleanup and release locks
*/
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
MiSetPageEvent(Process, Address);
DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
}
@ -1518,8 +1418,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
/*
* Cleanup and release locks
*/
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
MiSetPageEvent(Process, Address);
DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
}
@ -1539,6 +1438,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
/*
* Release all our locks and read in the page from disk
*/
MmSetPageEntrySectionSegment(Segment, &Offset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
MmUnlockSectionSegment(Segment);
MmUnlockAddressSpace(AddressSpace);
@ -1573,32 +1473,17 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
* Cleanup and release locks
*/
MmLockAddressSpace(AddressSpace);
PageOp->Status = Status;
MmspCompleteAndReleasePageOp(PageOp);
MiSetPageEvent(Process, Address);
DPRINT("Address 0x%.8X\n", Address);
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
* data
*/
MmLockAddressSpace(AddressSpace);
MmLockSectionSegment(Segment);
Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
MmUnlockSectionSegment(Segment);
@ -1615,8 +1500,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
}
MmInsertRmap(Page, Process, Address);
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
MiSetPageEvent(Process, Address);
DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
}
@ -1660,7 +1544,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
Entry1 = MmGetPageEntrySectionSegment(Segment, &Offset);
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);
}
@ -1687,8 +1571,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
KeBugCheck(MEMORY_MANAGEMENT);
}
MmInsertRmap(Page, Process, Address);
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
MiSetPageEvent(Process, Address);
DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
}
@ -1715,8 +1598,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
KeBugCheck(MEMORY_MANAGEMENT);
}
MmInsertRmap(Page, Process, Address);
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
MiSetPageEvent(Process, Address);
DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
}
@ -1735,7 +1617,6 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
NTSTATUS Status;
PVOID PAddress;
LARGE_INTEGER Offset;
PMM_PAGEOP PageOp;
PMM_REGION Region;
ULONG_PTR Entry;
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
@ -1799,46 +1680,29 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
/*
* Get or create a pageop
*/
PageOp = MmGetPageOp(MemoryArea, NULL, 0, Segment, Offset.LowPart,
MM_PAGEOP_ACCESSFAULT, FALSE);
if (PageOp == NULL)
{
DPRINT1("MmGetPageOp failed\n");
KeBugCheck(MEMORY_MANAGEMENT);
}
MmLockSectionSegment(Segment);
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
/*
* Wait for any other operations to complete
*/
if (PageOp->Thread != PsGetCurrentThread())
if (Entry == SWAPENTRY_FROM_SSE(MM_WAIT_ENTRY))
{
MmUnlockAddressSpace(AddressSpace);
Status = MmspWaitForPageOpCompletionEvent(PageOp);
/*
* 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
*/
MmLockAddressSpace(AddressSpace);
MmspCompleteAndReleasePageOp(PageOp);
DPRINT("Address 0x%.8X\n", Address);
return(STATUS_MM_RESTART_OPERATION);
MmUnlockSectionSegment(Segment);
MmUnlockAddressSpace(AddressSpace);
MiWaitForPageEvent(NULL, NULL);
/*
* Restart the operation
*/
MmLockAddressSpace(AddressSpace);
DPRINT("Address 0x%.8X\n", Address);
return(STATUS_MM_RESTART_OPERATION);
}
/*
* Release locks now we have the pageop
*/
MmUnlockSectionSegment(Segment);
MmUnlockAddressSpace(AddressSpace);
/*
@ -1890,11 +1754,10 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
MmDeleteRmap(OldPage, Process, PAddress);
MmInsertRmap(NewPage, Process, PAddress);
MmLockSectionSegment(Segment);
MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, FALSE, FALSE);
MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, FALSE, FALSE, NULL);
MmUnlockSectionSegment(Segment);
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
MiSetPageEvent(Process, Address);
DPRINT("Address 0x%.8X\n", Address);
return(STATUS_SUCCESS);
}
@ -1904,7 +1767,7 @@ MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address)
{
MM_SECTION_PAGEOUT_CONTEXT* PageOutContext;
BOOLEAN WasDirty;
PFN_NUMBER Page;
PFN_NUMBER Page = 0;
PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context;
if (Process)
@ -1928,7 +1791,8 @@ MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address)
PageOutContext->Segment,
&PageOutContext->Offset,
PageOutContext->WasDirty,
TRUE);
TRUE,
&PageOutContext->SectionEntry);
MmUnlockSectionSegment(PageOutContext->Segment);
}
if (Process)
@ -1940,21 +1804,17 @@ MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address)
{
MmReleasePageMemoryConsumer(MC_USER, Page);
}
DPRINT("PhysicalAddress %x, Address %x\n", Page << PAGE_SHIFT, Address);
}
NTSTATUS
NTAPI
MmPageOutSectionView(PMMSUPPORT AddressSpace,
MEMORY_AREA* MemoryArea,
PVOID Address,
PMM_PAGEOP PageOp)
PVOID Address, ULONG_PTR Entry)
{
PFN_NUMBER Page;
MM_SECTION_PAGEOUT_CONTEXT Context;
SWAPENTRY SwapEntry;
ULONG_PTR Entry;
ULONGLONG FileOffset;
NTSTATUS Status;
PFILE_OBJECT FileObject;
@ -1973,6 +1833,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
*/
Context.Segment = MemoryArea->Data.SectionData.Segment;
Context.Section = MemoryArea->Data.SectionData.Section;
Context.SectionEntry = Entry;
Context.CallingProcess = Process;
Context.Offset.QuadPart = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
@ -1984,6 +1845,8 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
FileObject = Context.Section->FileObject;
DirectMapped = FALSE;
MmLockSectionSegment(Context.Segment);
#ifndef NEWCC
if (FileObject != NULL &&
!(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",
Page, MmGetReferenceCountPage(Page));
PageOp->Status = STATUS_UNSUCCESSFUL;
MmspCompleteAndReleasePageOp(PageOp);
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
MmUnlockSectionSegment(Context.Segment);
return STATUS_UNSUCCESSFUL;
}
/*
* Prepare the context structure for the rmap delete call.
*/
MmLockSectionSegment(Context.Segment);
Entry = MmGetPageEntrySectionSegment(Context.Segment, &Context.Offset);
MmUnlockSectionSegment(Context.Segment);
Context.WasDirty = FALSE;
if (Context.Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
@ -2077,9 +1938,12 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
}
MmDeleteAllRmaps(Page, (PVOID)&Context, MmPageOutDeleteMapping);
MmLockSectionSegment(Context.Segment);
Entry = MmGetPageEntrySectionSegment(Context.Segment, &Context.Offset);
MmUnlockSectionSegment(Context.Segment);
/* Since we passed in a surrogate, we'll get back the page entry
* 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
@ -2117,8 +1981,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry));
MmUnlockSectionSegment(Context.Segment);
MmReleasePageMemoryConsumer(MC_USER, Page);
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
}
@ -2140,8 +2003,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
MmUnlockSectionSegment(Context.Segment);
}
MmReleasePageMemoryConsumer(MC_USER, Page);
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
}
@ -2165,8 +2027,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Bcb, (ULONG_PTR)FileOffset, (ULONG_PTR)Address);
}
#endif
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
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);
}
MmReleasePageMemoryConsumer(MC_USER, Page);
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
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);
MmLockAddressSpace(AddressSpace);
Status = MmCreatePageFileMapping(Process,
@ -2197,8 +2057,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Process, (ULONG_PTR)Address, SwapEntry);
}
MmReleasePageMemoryConsumer(MC_USER, Page);
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
@ -2253,8 +2112,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
MmUnlockSectionSegment(Context.Segment);
}
MmUnlockAddressSpace(AddressSpace);
PageOp->Status = STATUS_UNSUCCESSFUL;
MmspCompleteAndReleasePageOp(PageOp);
MiSetPageEvent(NULL, NULL);
return(STATUS_PAGEFILE_QUOTA);
}
}
@ -2299,8 +2157,7 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
}
MmUnlockAddressSpace(AddressSpace);
PageOp->Status = STATUS_UNSUCCESSFUL;
MmspCompleteAndReleasePageOp(PageOp);
MiSetPageEvent(NULL, NULL);
return(STATUS_UNSUCCESSFUL);
}
@ -2308,12 +2165,13 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
* Otherwise we have succeeded.
*/
DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT);
MmLockSectionSegment(Context.Segment);
MmSetSavedSwapEntryPage(Page, 0);
if (Context.Segment->Flags & MM_PAGEFILE_SEGMENT ||
Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED)
{
MmLockSectionSegment(Context.Segment);
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry));
MmUnlockSectionSegment(Context.Segment);
}
else
{
@ -2323,9 +2181,11 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
if (Context.Private)
{
MmLockAddressSpace(AddressSpace);
MmLockSectionSegment(Context.Segment);
Status = MmCreatePageFileMapping(Process,
Address,
SwapEntry);
MmUnlockSectionSegment(Context.Segment);
MmUnlockAddressSpace(AddressSpace);
if (!NT_SUCCESS(Status))
{
@ -2335,13 +2195,15 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace,
}
else
{
MmLockAddressSpace(AddressSpace);
MmLockSectionSegment(Context.Segment);
Entry = MAKE_SWAP_SSE(SwapEntry);
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
MmUnlockSectionSegment(Context.Segment);
MmUnlockAddressSpace(AddressSpace);
}
MmUnlockSectionSegment(Context.Segment);
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
@ -2350,7 +2212,7 @@ NTAPI
MmWritePageSectionView(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PVOID Address,
PMM_PAGEOP PageOp)
ULONG PageEntry)
{
LARGE_INTEGER Offset;
PROS_SECTION_OBJECT Section;
@ -2447,12 +2309,16 @@ MmWritePageSectionView(PMMSUPPORT AddressSpace,
*/
if (DirectMapped && !Private)
{
LARGE_INTEGER SOffset;
ASSERT(SwapEntry == 0);
SOffset.QuadPart = Offset.QuadPart + Segment->Image.FileOffset;
#ifndef NEWCC
CcRosMarkDirtyCacheSegment(Bcb, (ULONG)(Offset.QuadPart + Segment->Image.FileOffset));
CcRosMarkDirtyCacheSegment(Bcb, Offset.LowPart);
#endif
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
MmLockSectionSegment(Segment);
MmSetPageEntrySectionSegment(Segment, &Offset, PageEntry);
MmUnlockSectionSegment(Segment);
MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
@ -2465,8 +2331,7 @@ MmWritePageSectionView(PMMSUPPORT AddressSpace,
if (SwapEntry == 0)
{
MmSetDirtyAllRmaps(Page);
PageOp->Status = STATUS_UNSUCCESSFUL;
MmspCompleteAndReleasePageOp(PageOp);
MiSetPageEvent(NULL, NULL);
return(STATUS_PAGEFILE_QUOTA);
}
MmSetSavedSwapEntryPage(Page, SwapEntry);
@ -2481,8 +2346,7 @@ MmWritePageSectionView(PMMSUPPORT AddressSpace,
DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
Status);
MmSetDirtyAllRmaps(Page);
PageOp->Status = STATUS_UNSUCCESSFUL;
MmspCompleteAndReleasePageOp(PageOp);
MiSetPageEvent(NULL, NULL);
return(STATUS_UNSUCCESSFUL);
}
@ -2490,8 +2354,7 @@ MmWritePageSectionView(PMMSUPPORT AddressSpace,
* Otherwise we have succeeded.
*/
DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT);
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
MiSetPageEvent(NULL, NULL);
return(STATUS_SUCCESS);
}
@ -4039,8 +3902,6 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
PBCB Bcb;
LARGE_INTEGER Offset;
SWAPENTRY SavedSwapEntry;
PMM_PAGEOP PageOp;
NTSTATUS Status;
PROS_SECTION_OBJECT Section;
PMM_SECTION_SEGMENT Segment;
PMMSUPPORT AddressSpace;
@ -4057,28 +3918,19 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
Section = MemoryArea->Data.SectionData.Section;
Segment = MemoryArea->Data.SectionData.Segment;
PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL, Segment, Offset.LowPart);
while (PageOp)
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
while (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
{
MmUnlockSectionSegment(Segment);
MmUnlockAddressSpace(AddressSpace);
Status = MmspWaitForPageOpCompletionEvent(PageOp);
if (Status != STATUS_SUCCESS)
{
DPRINT1("Failed to wait for page op, status = %x\n", Status);
KeBugCheck(MEMORY_MANAGEMENT);
}
MiWaitForPageEvent(NULL, NULL);
MmLockAddressSpace(AddressSpace);
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
* cache manager.
@ -4136,7 +3988,7 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
else
{
MmDeleteRmap(Page, Process, Address);
MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, Dirty, FALSE);
MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, Dirty, FALSE, NULL);
}
}
}
@ -4208,9 +4060,7 @@ MiRosUnmapViewOfSection(IN PEPROCESS Process,
PMEMORY_AREA MemoryArea;
PMMSUPPORT AddressSpace;
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",
Process, BaseAddress);
@ -4233,40 +4083,6 @@ MiRosUnmapViewOfSection(IN PEPROCESS Process,
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;
if (Section->AllocationAttributes & SEC_IMAGE)