mirror of
https://github.com/reactos/reactos.git
synced 2025-05-23 02:56:09 +00:00
[NTOSKRNL]
Slightly refactor MiMapViewOfDataSection and NtAllocateVirtualMemory svn path=/trunk/; revision=64588
This commit is contained in:
parent
d5cfae9ac2
commit
1b6c4fe27c
2 changed files with 129 additions and 112 deletions
|
@ -1253,7 +1253,9 @@ MiMapViewOfDataSection(IN PCONTROL_AREA ControlArea,
|
|||
{
|
||||
PMMVAD_LONG Vad;
|
||||
PETHREAD Thread = PsGetCurrentThread();
|
||||
PMMSUPPORT AddressSpace;
|
||||
ULONG_PTR StartAddress, EndingAddress;
|
||||
ULONG_PTR ViewSizeInPages;
|
||||
PSUBSECTION Subsection;
|
||||
PSEGMENT Segment;
|
||||
PFN_NUMBER PteOffset;
|
||||
|
@ -1263,6 +1265,7 @@ MiMapViewOfDataSection(IN PCONTROL_AREA ControlArea,
|
|||
MMPTE TempPte;
|
||||
PMMADDRESS_NODE Parent;
|
||||
TABLE_SEARCH_RESULT Result;
|
||||
DPRINT("Mapping ARM3 data section\n");
|
||||
|
||||
/* Get the segment for this section */
|
||||
Segment = ControlArea->Segment;
|
||||
|
@ -1340,75 +1343,8 @@ MiMapViewOfDataSection(IN PCONTROL_AREA ControlArea,
|
|||
/* ARM3 does not currently support large pages */
|
||||
ASSERT(Segment->SegmentFlags.LargePages == 0);
|
||||
|
||||
/* Did the caller specify an address? */
|
||||
if (!(*BaseAddress) && !(Section->Address.StartingVpn))
|
||||
{
|
||||
/* ARM3 does not support these flags yet */
|
||||
ASSERT(Process->VmTopDown == 0);
|
||||
ASSERT(ZeroBits == 0);
|
||||
|
||||
/* Which way should we search? */
|
||||
if (AllocationType & MEM_TOP_DOWN)
|
||||
{
|
||||
/* No, find an address top-down */
|
||||
Result = MiFindEmptyAddressRangeDownTree(*ViewSize,
|
||||
(ULONG_PTR)MM_HIGHEST_VAD_ADDRESS,
|
||||
_64K,
|
||||
&Process->VadRoot,
|
||||
&StartAddress,
|
||||
&Parent);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No, find an address bottom-up */
|
||||
Result = MiFindEmptyAddressRangeInTree(*ViewSize,
|
||||
_64K,
|
||||
&Process->VadRoot,
|
||||
&Parent,
|
||||
&StartAddress);
|
||||
}
|
||||
|
||||
/* Check if we found a suitable location */
|
||||
if (Result == TableFoundNode)
|
||||
{
|
||||
DPRINT1("Not enough free space to insert this section!\n");
|
||||
MiDereferenceControlArea(ControlArea);
|
||||
return STATUS_CONFLICTING_ADDRESSES;
|
||||
}
|
||||
|
||||
/* Get the ending address, which is the last piece we need for the VAD */
|
||||
EndingAddress = (StartAddress + *ViewSize - 1) | (PAGE_SIZE - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Is it SEC_BASED, or did the caller manually specify an address? */
|
||||
if (!(*BaseAddress))
|
||||
{
|
||||
/* It is a SEC_BASED mapping, use the address that was generated */
|
||||
StartAddress = Section->Address.StartingVpn + SectionOffset->LowPart;
|
||||
DPRINT("BASED: 0x%p\n", StartAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just align what the caller gave us */
|
||||
StartAddress = ROUND_UP((ULONG_PTR)*BaseAddress, _64K);
|
||||
}
|
||||
|
||||
/* Get the ending address, which is the last piece we need for the VAD */
|
||||
EndingAddress = (StartAddress + *ViewSize - 1) | (PAGE_SIZE - 1);
|
||||
|
||||
/* Make sure it doesn't conflict with an existing allocation */
|
||||
Result = MiCheckForConflictingNode(StartAddress >> PAGE_SHIFT,
|
||||
EndingAddress >> PAGE_SHIFT,
|
||||
&Process->VadRoot,
|
||||
&Parent);
|
||||
if (Result == TableFoundNode)
|
||||
{
|
||||
DPRINT1("Conflict with SEC_BASED or manually based section!\n");
|
||||
MiDereferenceControlArea(ControlArea);
|
||||
return STATUS_CONFLICTING_ADDRESSES;
|
||||
}
|
||||
}
|
||||
/* Calculate how many pages the region spans */
|
||||
ViewSizeInPages = BYTES_TO_PAGES(*ViewSize);
|
||||
|
||||
/* A VAD can now be allocated. Do so and zero it out */
|
||||
/* FIXME: we are allocating a LONG VAD for ReactOS compatibility only */
|
||||
|
@ -1419,12 +1355,11 @@ MiMapViewOfDataSection(IN PCONTROL_AREA ControlArea,
|
|||
MiDereferenceControlArea(ControlArea);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
RtlZeroMemory(Vad, sizeof(MMVAD_LONG));
|
||||
Vad->u4.Banked = (PVOID)0xDEADBABE;
|
||||
|
||||
/* Write all the data required in the VAD for handling a fault */
|
||||
Vad->StartingVpn = StartAddress >> PAGE_SHIFT;
|
||||
Vad->EndingVpn = EndingAddress >> PAGE_SHIFT;
|
||||
Vad->ControlArea = ControlArea;
|
||||
Vad->u.VadFlags.Protection = ProtectionMask;
|
||||
Vad->u2.VadFlags2.FileOffset = (ULONG)(SectionOffset->QuadPart >> 16);
|
||||
|
@ -1438,7 +1373,7 @@ MiMapViewOfDataSection(IN PCONTROL_AREA ControlArea,
|
|||
|
||||
/* Finally, write down the first and last prototype PTE */
|
||||
Vad->FirstPrototypePte = &Subsection->SubsectionBase[PteOffset];
|
||||
PteOffset += (Vad->EndingVpn - Vad->StartingVpn);
|
||||
PteOffset += ViewSizeInPages - 1;
|
||||
ASSERT(PteOffset < Subsection->PtesInSubsection);
|
||||
Vad->LastContiguousPte = &Subsection->SubsectionBase[PteOffset];
|
||||
|
||||
|
@ -1448,19 +1383,6 @@ MiMapViewOfDataSection(IN PCONTROL_AREA ControlArea,
|
|||
/* FIXME: Should setup VAD bitmap */
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
/* Pretend as if we own the working set */
|
||||
MiLockProcessWorkingSetUnsafe(Process, Thread);
|
||||
|
||||
/* Insert the VAD */
|
||||
Process->VadRoot.NodeHint = Vad;
|
||||
MiInsertNode(&Process->VadRoot, (PVOID)Vad, Parent, Result);
|
||||
|
||||
/* Release the working set */
|
||||
MiUnlockProcessWorkingSetUnsafe(Process, Thread);
|
||||
|
||||
/* Windows stores this for accounting purposes, do so as well */
|
||||
if (!Segment->u2.FirstMappedVa) Segment->u2.FirstMappedVa = (PVOID)StartAddress;
|
||||
|
||||
/* Check if anything was committed */
|
||||
if (QuotaCharge)
|
||||
{
|
||||
|
@ -1499,6 +1421,114 @@ MiMapViewOfDataSection(IN PCONTROL_AREA ControlArea,
|
|||
KeReleaseGuardedMutexUnsafe(&MmSectionCommitMutex);
|
||||
}
|
||||
|
||||
/* Is it SEC_BASED, or did the caller manually specify an address? */
|
||||
if (*BaseAddress != NULL)
|
||||
{
|
||||
/* Just align what the caller gave us */
|
||||
StartAddress = ROUND_UP((ULONG_PTR)*BaseAddress, _64K);
|
||||
}
|
||||
else if (Section->Address.StartingVpn != 0)
|
||||
{
|
||||
/* It is a SEC_BASED mapping, use the address that was generated */
|
||||
StartAddress = Section->Address.StartingVpn + SectionOffset->LowPart;
|
||||
}
|
||||
else
|
||||
{
|
||||
StartAddress = 0;
|
||||
}
|
||||
|
||||
/* Lock the address space and make sure the process is alive */
|
||||
AddressSpace = MmGetCurrentAddressSpace();
|
||||
MmLockAddressSpace(AddressSpace);
|
||||
if (Process->VmDeleted)
|
||||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
ExFreePoolWithTag(Vad, 'ldaV');
|
||||
DPRINT1("The process is dying\n");
|
||||
return STATUS_PROCESS_IS_TERMINATING;
|
||||
}
|
||||
|
||||
/* Did the caller specify an address? */
|
||||
if (StartAddress == 0)
|
||||
{
|
||||
/* ARM3 does not support these flags yet */
|
||||
ASSERT(Process->VmTopDown == 0);
|
||||
ASSERT(ZeroBits == 0);
|
||||
|
||||
/* Which way should we search? */
|
||||
if (AllocationType & MEM_TOP_DOWN)
|
||||
{
|
||||
/* No, find an address top-down */
|
||||
Result = MiFindEmptyAddressRangeDownTree(*ViewSize,
|
||||
(ULONG_PTR)MM_HIGHEST_VAD_ADDRESS,
|
||||
_64K,
|
||||
&Process->VadRoot,
|
||||
&StartAddress,
|
||||
&Parent);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No, find an address bottom-up */
|
||||
Result = MiFindEmptyAddressRangeInTree(*ViewSize,
|
||||
_64K,
|
||||
&Process->VadRoot,
|
||||
&Parent,
|
||||
&StartAddress);
|
||||
}
|
||||
|
||||
/* Check if we found a suitable location */
|
||||
if (Result == TableFoundNode)
|
||||
{
|
||||
DPRINT1("Not enough free space to insert this section!\n");
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
MiDereferenceControlArea(ControlArea);
|
||||
ExFreePoolWithTag(Vad, 'ldaV');
|
||||
return STATUS_CONFLICTING_ADDRESSES;
|
||||
}
|
||||
|
||||
/* Get the ending address, which is the last piece we need for the VAD */
|
||||
EndingAddress = StartAddress + (ViewSizeInPages * PAGE_SIZE) - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the ending address, which is the last piece we need for the VAD */
|
||||
EndingAddress = StartAddress + (ViewSizeInPages * PAGE_SIZE) - 1;
|
||||
|
||||
/* Make sure it doesn't conflict with an existing allocation */
|
||||
Result = MiCheckForConflictingNode(StartAddress >> PAGE_SHIFT,
|
||||
EndingAddress >> PAGE_SHIFT,
|
||||
&Process->VadRoot,
|
||||
&Parent);
|
||||
if (Result == TableFoundNode)
|
||||
{
|
||||
DPRINT1("Conflict with SEC_BASED or manually based section!\n");
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
MiDereferenceControlArea(ControlArea);
|
||||
ExFreePoolWithTag(Vad, 'ldaV');
|
||||
return STATUS_CONFLICTING_ADDRESSES;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now set the VAD address */
|
||||
Vad->StartingVpn = StartAddress >> PAGE_SHIFT;
|
||||
Vad->EndingVpn = EndingAddress >> PAGE_SHIFT;
|
||||
|
||||
/* Pretend as if we own the working set */
|
||||
MiLockProcessWorkingSetUnsafe(Process, Thread);
|
||||
|
||||
/* Insert the VAD */
|
||||
Process->VadRoot.NodeHint = Vad;
|
||||
MiInsertNode(&Process->VadRoot, (PVOID)Vad, Parent, Result);
|
||||
|
||||
/* Release the working set */
|
||||
MiUnlockProcessWorkingSetUnsafe(Process, Thread);
|
||||
|
||||
/* Unlock the address space */
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
|
||||
/* Windows stores this for accounting purposes, do so as well */
|
||||
if (!Segment->u2.FirstMappedVa) Segment->u2.FirstMappedVa = (PVOID)StartAddress;
|
||||
|
||||
/* Finally, let the caller know where, and for what size, the view was mapped */
|
||||
*ViewSize = (ULONG_PTR)EndingAddress - (ULONG_PTR)StartAddress + 1;
|
||||
*BaseAddress = (PVOID)StartAddress;
|
||||
|
@ -2786,33 +2816,20 @@ MmMapViewOfArm3Section(IN PVOID SectionObject,
|
|||
Attached = TRUE;
|
||||
}
|
||||
|
||||
/* Lock the address space and make sure the process is alive */
|
||||
MmLockAddressSpace(&Process->Vm);
|
||||
if (!Process->VmDeleted)
|
||||
{
|
||||
/* Do the actual mapping */
|
||||
DPRINT("Mapping ARM3 data section\n");
|
||||
Status = MiMapViewOfDataSection(ControlArea,
|
||||
Process,
|
||||
BaseAddress,
|
||||
SectionOffset,
|
||||
ViewSize,
|
||||
Section,
|
||||
InheritDisposition,
|
||||
ProtectionMask,
|
||||
CommitSize,
|
||||
ZeroBits,
|
||||
AllocationType);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The process is being terminated, fail */
|
||||
DPRINT1("The process is dying\n");
|
||||
Status = STATUS_PROCESS_IS_TERMINATING;
|
||||
}
|
||||
/* Do the actual mapping */
|
||||
Status = MiMapViewOfDataSection(ControlArea,
|
||||
Process,
|
||||
BaseAddress,
|
||||
SectionOffset,
|
||||
ViewSize,
|
||||
Section,
|
||||
InheritDisposition,
|
||||
ProtectionMask,
|
||||
CommitSize,
|
||||
ZeroBits,
|
||||
AllocationType);
|
||||
|
||||
/* Unlock the address space and detatch if needed, then return status */
|
||||
MmUnlockAddressSpace(&Process->Vm);
|
||||
/* Detatch if needed, then return status */
|
||||
if (Attached) KeUnstackDetachProcess(&ApcState);
|
||||
return Status;
|
||||
}
|
||||
|
|
|
@ -4599,6 +4599,7 @@ NtAllocateVirtualMemory(IN HANDLE ProcessHandle,
|
|||
Vad->u.VadFlags.Protection = ProtectionMask;
|
||||
Vad->u.VadFlags.PrivateMemory = 1;
|
||||
Vad->u.VadFlags.CommitCharge = AllocationType & MEM_COMMIT ? PageCount : 0;
|
||||
Vad->ControlArea = NULL; // For Memory-Area hack
|
||||
|
||||
//
|
||||
// Lock the address space and make sure the process isn't already dead
|
||||
|
@ -4692,7 +4693,6 @@ NtAllocateVirtualMemory(IN HANDLE ProcessHandle,
|
|||
// Lock the working set and insert the VAD into the process VAD tree
|
||||
//
|
||||
MiLockProcessWorkingSetUnsafe(Process, CurrentThread);
|
||||
Vad->ControlArea = NULL; // For Memory-Area hack
|
||||
Process->VadRoot.NodeHint = Vad;
|
||||
MiInsertNode(&Process->VadRoot, (PVOID)Vad, Parent, Result);
|
||||
MiUnlockProcessWorkingSetUnsafe(Process, CurrentThread);
|
||||
|
|
Loading…
Reference in a new issue