- 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.

svn path=/trunk/; revision=18849
This commit is contained in:
Hartmut Birr 2005-10-29 14:10:35 +00:00
parent 470db6b8eb
commit 5e158693d9

View file

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