- Lock always the address space if we changing the virtual mapping. This is necessary because we can create or remove a page table. - If we unmap a section, we have to wait for all pending pageops for the section within the current process. We do this by waiting for all pageops for the section. Modified: trunk/reactos/ntoskrnl/mm/section.c _____
Modified: trunk/reactos/ntoskrnl/mm/section.c --- trunk/reactos/ntoskrnl/mm/section.c 2005-10-29 14:09:00 UTC (rev 18848) +++ trunk/reactos/ntoskrnl/mm/section.c 2005-10-29 14:10:35 UTC (rev 18849) @@ -1278,6 +1278,7 @@
*/ MiCopyFromUserPage(NewPage, PAddress);
+ MmLockAddressSpace(AddressSpace); /* * Delete the old entry. */ @@ -1286,7 +1287,6 @@ /* * Set the PTE to point to the new page */ - MmLockAddressSpace(AddressSpace); Status = MmCreateVirtualMapping(AddressSpace->Process, Address, Region->Protect, @@ -1298,7 +1298,6 @@ KEBUGCHECK(0); return(Status); } - MmInsertRmap(NewPage, AddressSpace->Process, PAddress); if (!NT_SUCCESS(Status)) { DbgPrint("Unable to create virtual mapping\n"); @@ -1314,6 +1313,7 @@ * 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 @@ PFN_TYPE Page;
PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context; + if (Process) + { + MmLockAddressSpace(&Process->AddressSpace); + } + MmDeleteVirtualMapping(Process, Address, FALSE, @@ -1343,14 +1348,21 @@ } 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 @@ 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 @@ if (SwapEntry == 0) { MmShowOutOfSpaceMessagePagingFile(); - + MmLockAddressSpace(AddressSpace); /* * For private pages restore the old mappings. */ @@ -1618,6 +1632,7 @@ 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 @@ * As above: undo our actions. * FIXME: Also free the swap page. */ + MmLockAddressSpace(AddressSpace); if (Context.Private) { Status = MmCreateVirtualMapping(AddressSpace->Process, @@ -1662,6 +1678,7 @@ 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 @@
if (Context.Private) { + MmLockAddressSpace(AddressSpace); Status = MmCreatePageFileMapping(AddressSpace->Process, Address, SwapEntry); + MmUnlockAddressSpace(AddressSpace); if (!NT_SUCCESS(Status)) { KEBUGCHECK(0); @@ -3797,7 +3816,7 @@ } }
-NTSTATUS +STATIC NTSTATUS MmUnmapViewOfSegment(PMADDRESS_SPACE AddressSpace, PVOID BaseAddress) { @@ -3860,6 +3879,8 @@ 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 @@ 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 @@ { Status = MmUnmapViewOfSegment(AddressSpace, BaseAddress); } + MmUnlockAddressSpace(AddressSpace); return(STATUS_SUCCESS); }
@@ -3970,9 +4030,7 @@ return(Status); }
- MmLockAddressSpace(&Process->AddressSpace); Status = MmUnmapViewOfSection(Process, BaseAddress); - MmUnlockAddressSpace(&Process->AddressSpace);
ObDereferenceObject(Process);