diff --git a/reactos/ntoskrnl/mm/section.c b/reactos/ntoskrnl/mm/section.c index f3cf779a697..8653d54e8ee 100644 --- a/reactos/ntoskrnl/mm/section.c +++ b/reactos/ntoskrnl/mm/section.c @@ -1278,6 +1278,7 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace, */ MiCopyFromUserPage(NewPage, PAddress); + MmLockAddressSpace(AddressSpace); /* * Delete the old entry. */ @@ -1286,7 +1287,6 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace, /* * Set the PTE to point to the new page */ - MmLockAddressSpace(AddressSpace); Status = MmCreateVirtualMapping(AddressSpace->Process, Address, Region->Protect, @@ -1298,7 +1298,6 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace, KEBUGCHECK(0); return(Status); } - MmInsertRmap(NewPage, AddressSpace->Process, PAddress); if (!NT_SUCCESS(Status)) { DbgPrint("Unable to create virtual mapping\n"); @@ -1314,6 +1313,7 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace, * Unshare the old page. */ MmDeleteRmap(OldPage, AddressSpace->Process, PAddress); + MmInsertRmap(NewPage, AddressSpace->Process, PAddress); MmLockSectionSegment(Segment); MmUnsharePageEntrySectionSegment(Section, Segment, Offset, FALSE, FALSE); MmUnlockSectionSegment(Segment); @@ -1332,6 +1332,11 @@ MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address) PFN_TYPE Page; PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context; + if (Process) + { + MmLockAddressSpace(&Process->AddressSpace); + } + MmDeleteVirtualMapping(Process, Address, FALSE, @@ -1343,13 +1348,20 @@ MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address) } if (!PageOutContext->Private) { + MmLockSectionSegment(PageOutContext->Segment); MmUnsharePageEntrySectionSegment(PageOutContext->Section, PageOutContext->Segment, PageOutContext->Offset, PageOutContext->WasDirty, TRUE); + MmUnlockSectionSegment(PageOutContext->Segment); } - else + if (Process) + { + MmUnlockAddressSpace(&Process->AddressSpace); + } + + if (PageOutContext->Private) { MmReleasePageMemoryConsumer(MC_USER, Page); } @@ -1561,9 +1573,11 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace, else if (!Context.WasDirty && Context.Private && SwapEntry != 0) { MmSetSavedSwapEntryPage(Page, 0); + MmLockAddressSpace(AddressSpace); Status = MmCreatePageFileMapping(AddressSpace->Process, Address, SwapEntry); + MmUnlockAddressSpace(AddressSpace); if (!NT_SUCCESS(Status)) { KEBUGCHECK(0); @@ -1583,7 +1597,7 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace, if (SwapEntry == 0) { MmShowOutOfSpaceMessagePagingFile(); - + MmLockAddressSpace(AddressSpace); /* * For private pages restore the old mappings. */ @@ -1618,6 +1632,7 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace, Entry = MAKE_SSE(Page << PAGE_SHIFT, 1); MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, Entry); } + MmUnlockAddressSpace(AddressSpace); PageOp->Status = STATUS_UNSUCCESSFUL; MmspCompleteAndReleasePageOp(PageOp); return(STATUS_PAGEFILE_QUOTA); @@ -1636,6 +1651,7 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace, * As above: undo our actions. * FIXME: Also free the swap page. */ + MmLockAddressSpace(AddressSpace); if (Context.Private) { Status = MmCreateVirtualMapping(AddressSpace->Process, @@ -1662,6 +1678,7 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace, Entry = MAKE_SSE(Page << PAGE_SHIFT, 1); MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, Entry); } + MmUnlockAddressSpace(AddressSpace); PageOp->Status = STATUS_UNSUCCESSFUL; MmspCompleteAndReleasePageOp(PageOp); return(STATUS_UNSUCCESSFUL); @@ -1684,9 +1701,11 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace, if (Context.Private) { + MmLockAddressSpace(AddressSpace); Status = MmCreatePageFileMapping(AddressSpace->Process, Address, SwapEntry); + MmUnlockAddressSpace(AddressSpace); if (!NT_SUCCESS(Status)) { KEBUGCHECK(0); @@ -3797,7 +3816,7 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, } } -NTSTATUS +STATIC NTSTATUS MmUnmapViewOfSegment(PMADDRESS_SPACE AddressSpace, PVOID BaseAddress) { @@ -3860,6 +3879,8 @@ MmUnmapViewOfSection(PEPROCESS Process, PMEMORY_AREA MemoryArea; PMADDRESS_SPACE AddressSpace; PSECTION_OBJECT Section; + PMM_PAGEOP PageOp; + ULONG_PTR Offset; DPRINT("Opening memory area Process %x BaseAddress %x\n", Process, BaseAddress); @@ -3867,15 +3888,53 @@ MmUnmapViewOfSection(PEPROCESS Process, ASSERT(Process); AddressSpace = &Process->AddressSpace; + + MmLockAddressSpace(AddressSpace); MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress); if (MemoryArea == NULL || MemoryArea->Type != MEMORY_AREA_SECTION_VIEW || MemoryArea->DeleteInProgress) { + MmUnlockAddressSpace(AddressSpace); return STATUS_NOT_MAPPED_VIEW; } + 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); + if (PageOp) + { + MmUnlockAddressSpace(AddressSpace); + Status = MmspWaitForPageOpCompletionEvent(PageOp); + if (Status != STATUS_SUCCESS) + { + DPRINT1("Failed to wait for page op, status = %x\n", Status); + KEBUGCHECK(0); + } + MmLockAddressSpace(AddressSpace); + 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) @@ -3925,6 +3984,7 @@ MmUnmapViewOfSection(PEPROCESS Process, { Status = MmUnmapViewOfSegment(AddressSpace, BaseAddress); } + MmUnlockAddressSpace(AddressSpace); return(STATUS_SUCCESS); } @@ -3970,9 +4030,7 @@ NtUnmapViewOfSection (HANDLE ProcessHandle, return(Status); } - MmLockAddressSpace(&Process->AddressSpace); Status = MmUnmapViewOfSection(Process, BaseAddress); - MmUnlockAddressSpace(&Process->AddressSpace); ObDereferenceObject(Process);