Author: sginsberg
Date: Mon Mar 26 13:00:16 2012
New Revision: 56234
URL: http://svn.reactos.org/svn/reactos?rev=56234&view=rev
Log:
[NTOS]
- Fix a crazy bug in KiTrap0EHandler, it didn't enable interrupts unless it trapped when interrupts were already disabled (during a page fault during page fault handling, for example). This seems to have worked because the old non-newcc version of MiReadPage appears to rely on a page fault to bring the paged out page in. Thanks Timo.
Modified:
trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
Modified: trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/traphdlr.…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] Mon Mar 26 13:00:16 2012
@@ -1183,27 +1183,23 @@
while (TRUE);
}
}
-
+
/* Save CR2 */
Cr2 = __readcr2();
-
- /* HACK: Check if interrupts are disabled and enable them */
+
+ /* Enable interupts */
+ _enable();
+
+ /* Check if we faulted with interrupts disabled */
if (!(TrapFrame->EFlags & EFLAGS_INTERRUPT_MASK))
{
- /* Enable interupts */
- _enable();
-#ifdef HACK_ABOVE_FIXED
- if (!(TrapFrame->EFlags & EFLAGS_INTERRUPT_MASK))
- {
- /* This is illegal */
- KeBugCheckWithTf(IRQL_NOT_LESS_OR_EQUAL,
- Cr2,
- -1,
- TrapFrame->ErrCode & 2 ? TRUE : FALSE,
- TrapFrame->Eip,
- TrapFrame);
- }
-#endif
+ /* This is completely illegal, bugcheck the system */
+ KeBugCheckWithTf(IRQL_NOT_LESS_OR_EQUAL,
+ Cr2,
+ -1,
+ TrapFrame->ErrCode & 2 ? TRUE : FALSE,
+ TrapFrame->Eip,
+ TrapFrame);
}
/* Check for S-LIST fault in kernel mode */
Author: sir_richard
Date: Mon Mar 26 07:41:47 2012
New Revision: 56233
URL: http://svn.reactos.org/svn/reactos?rev=56233&view=rev
Log:
[NTOS]: Add support for determining transition vs. demand zero faults (the former should not yet happen).
[NTOS]: Add a function for removing transition pages from either the standby or modified page lists (not yet used).
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/pagfault.…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] Mon Mar 26 07:41:47 2012
@@ -446,6 +446,151 @@
NTSTATUS
NTAPI
+MiResolveTransitionFault(IN PVOID FaultingAddress,
+ IN PMMPTE PointerPte,
+ IN PEPROCESS CurrentProcess,
+ IN KIRQL OldIrql,
+ OUT PVOID *InPageBlock)
+{
+ PFN_NUMBER PageFrameIndex;
+ PMMPFN Pfn1;
+ MMPTE TempPte;
+ PMMPTE PointerToPteForProtoPage;
+ USHORT NewRefCount;
+ DPRINT1("Transition fault on 0x%p with PTE 0x%lx in process %s\n", FaultingAddress, PointerPte, CurrentProcess->ImageFileName);
+
+ /* Windowss does this check */
+ ASSERT(*InPageBlock == NULL);
+
+ /* ARM3 doesn't support this path */
+ ASSERT(OldIrql != MM_NOIRQL);
+
+ /* Capture the PTE and make sure it's in transition format */
+ TempPte = *PointerPte;
+ ASSERT((TempPte.u.Soft.Valid == 0) &&
+ (TempPte.u.Soft.Prototype == 0) &&
+ (TempPte.u.Soft.Transition == 1));
+
+ /* Get the PFN and the PFN entry */
+ PageFrameIndex = TempPte.u.Trans.PageFrameNumber;
+ DPRINT1("Transition PFN: %lx\n", PageFrameIndex);
+ Pfn1 = MiGetPfnEntry(PageFrameIndex);
+
+ /* One more transition fault! */
+ InterlockedIncrement(&KeGetCurrentPrcb()->MmTransitionCount);
+
+ /* This is from ARM3 -- Windows normally handles this here */
+ ASSERT(Pfn1->u4.InPageError == 0);
+
+ /* Not supported in ARM3 */
+ ASSERT(Pfn1->u3.e1.ReadInProgress == 0);
+
+ /* Windows checks there's some free pages and this isn't an in-page error */
+ ASSERT(MmAvailablePages >= 0);
+ ASSERT(Pfn1->u4.InPageError == 0);
+
+ /* Was this a transition page in the valid list, or free/zero list? */
+ if (Pfn1->u3.e1.PageLocation == ActiveAndValid)
+ {
+ /* All Windows does here is a bunch of sanity checks */
+ DPRINT1("Transition in active list\n");
+ ASSERT((Pfn1->PteAddress >= MiAddressToPte(MmPagedPoolStart)) &&
+ (Pfn1->PteAddress <= MiAddressToPte(MmPagedPoolEnd)));
+ ASSERT(Pfn1->u2.ShareCount != 0);
+ ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
+ }
+ else
+ {
+ /* Otherwise, the page is removed from its list */
+ DPRINT1("Transition page in free/zero list\n");
+ MiUnlinkPageFromList(Pfn1);
+
+ /* Windows does these checks -- perhaps a macro? */
+ ASSERT(Pfn1->u2.ShareCount == 0);
+ ASSERT(Pfn1->u2.ShareCount == 0);
+ ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
+
+ /* Check if this was a prototype PTE */
+ if ((Pfn1->u3.e1.PrototypePte == 1) &&
+ (Pfn1->OriginalPte.u.Soft.Prototype == 1))
+ {
+ DPRINT1("Prototype floating page not yet supported\n");
+ ASSERT(FALSE);
+ }
+
+ /* FIXME: Update counter */
+
+ /* We must be the first reference */
+ NewRefCount = InterlockedIncrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount);
+ ASSERT(NewRefCount == 1);
+ }
+
+ /* At this point, there should no longer be any in-page errors */
+ ASSERT(Pfn1->u4.InPageError == 0);
+
+ /* Check if this was a PFN with no more share references */
+ if (Pfn1->u2.ShareCount == 0)
+ {
+ /* Windows checks for these... maybe a macro? */
+ ASSERT(Pfn1->u3.e2.ReferenceCount != 0);
+ ASSERT(Pfn1->u2.ShareCount == 0);
+
+ /* Was this the last active reference to it */
+ DPRINT1("Page share count is zero\n");
+ if (Pfn1->u3.e2.ReferenceCount == 1)
+ {
+ /* The page should be leaking somewhere on the free/zero list */
+ DPRINT1("Page reference count is one\n");
+ ASSERT(Pfn1->u3.e1.PageLocation != ActiveAndValid);
+ if ((Pfn1->u3.e1.PrototypePte == 1) &&
+ (Pfn1->OriginalPte.u.Soft.Prototype == 1))
+ {
+ /* Do extra processing if it was a prototype page */
+ DPRINT1("Prototype floating page not yet supported\n");
+ ASSERT(FALSE);
+ }
+
+ /* FIXME: Update counter */
+ }
+ }
+
+ /* Bump the share count and make the page valid */
+ Pfn1->u2.ShareCount++;
+ Pfn1->u3.e1.PageLocation = ActiveAndValid;
+
+ /* Prototype PTEs are in paged pool, which itself might be in transition */
+ if (FaultingAddress >= MmSystemRangeStart)
+ {
+ /* Check if this is a paged pool PTE in transition state */
+ PointerToPteForProtoPage = MiAddressToPte(PointerPte);
+ TempPte = *PointerToPteForProtoPage;
+ if ((TempPte.u.Hard.Valid == 0) && (TempPte.u.Soft.Transition == 1))
+ {
+ /* This isn't yet supported */
+ DPRINT1("Double transition fault not yet supported\n");
+ ASSERT(FALSE);
+ }
+ }
+
+ /* Build the transition PTE -- maybe a macro? */
+ ASSERT(PointerPte->u.Hard.Valid == 0);
+ ASSERT(PointerPte->u.Trans.Prototype == 0);
+ ASSERT(PointerPte->u.Trans.Transition == 1);
+ TempPte.u.Long = (PointerPte->u.Long & ~0xFFF) |
+ (MmProtectToPteMask[PointerPte->u.Trans.Protection]) |
+ MiDetermineUserGlobalPteMask(PointerPte);
+
+ /* FIXME: Set dirty bit */
+
+ /* Write the valid PTE */
+ MI_WRITE_VALID_PTE(PointerPte, TempPte);
+
+ /* Return success */
+ return STATUS_PAGE_FAULT_TRANSITION;
+}
+
+NTSTATUS
+NTAPI
MiResolveProtoPteFault(IN BOOLEAN StoreInstruction,
IN PVOID Address,
IN PMMPTE PointerPte,
@@ -457,10 +602,11 @@
IN KIRQL OldIrql,
IN PVOID TrapInformation)
{
- MMPTE TempPte;
+ MMPTE TempPte, PteContents;
PMMPFN Pfn1;
PFN_NUMBER PageFrameIndex;
NTSTATUS Status;
+ PVOID InPageBlock = NULL;
/* Must be called with an invalid, prototype PTE, with the PFN lock held */
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
@@ -497,19 +643,50 @@
return STATUS_ACCESS_VIOLATION;
}
- /* This is the only thing we support right now */
- ASSERT(TempPte.u.Soft.PageFileHigh == 0);
- ASSERT(TempPte.u.Proto.ReadOnly == 0);
- ASSERT(PointerPte > MiHighestUserPte);
+ /* Check for access rights on the PTE proper */
+ PteContents = *PointerPte;
+ if (PteContents.u.Soft.PageFileHigh != MI_PTE_LOOKUP_NEEDED)
+ {
+ if (!PteContents.u.Proto.ReadOnly)
+ {
+ /* FIXME: CHECK FOR ACCESS AND COW */
+ }
+ }
+ else
+ {
+ /* FIXME: Should check for COW */
+ }
+
+ /* Check for clone PTEs */
+ if (PointerPte <= MiHighestUserPte) ASSERT(Process->CloneRoot == NULL);
+
+ /* We don't support mapped files yet */
ASSERT(TempPte.u.Soft.Prototype == 0);
- ASSERT(TempPte.u.Soft.Transition == 0);
-
- /* Resolve the demand zero fault */
- Status = MiResolveDemandZeroFault(Address,
- PointerProtoPte,
- Process,
- OldIrql);
- ASSERT(NT_SUCCESS(Status));
+
+ /* We might however have transition PTEs */
+ if (TempPte.u.Soft.Transition == 1)
+ {
+ /* Resolve the transition fault */
+ ASSERT(OldIrql != MM_NOIRQL);
+ Status = MiResolveTransitionFault(Address,
+ PointerProtoPte,
+ Process,
+ OldIrql,
+ &InPageBlock);
+ ASSERT(NT_SUCCESS(Status));
+ }
+ else
+ {
+ /* We also don't support paged out pages */
+ ASSERT(TempPte.u.Soft.PageFileHigh == 0);
+
+ /* Resolve the demand zero fault */
+ Status = MiResolveDemandZeroFault(Address,
+ PointerProtoPte,
+ Process,
+ OldIrql);
+ ASSERT(NT_SUCCESS(Status));
+ }
/* Complete the prototype PTE fault -- this will release the PFN lock */
ASSERT(PointerPte->u.Hard.Valid == 0);
Modified: trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c [iso-8859-1] Mon Mar 26 07:41:47 2012
@@ -225,6 +225,124 @@
// MI_PFN_CURRENT_USAGE = MI_USAGE_NOT_SET;
// memcpy(MI_PFN_CURRENT_PROCESS_NAME, "Not Set", 16);
#endif
+}
+
+VOID
+NTAPI
+MiUnlinkPageFromList(IN PMMPFN Pfn)
+{
+ PMMPFNLIST ListHead;
+ PFN_NUMBER OldFlink, OldBlink;
+
+ /* Make sure the PFN lock is held */
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+ /* ARM3 should only call this for dead pages */
+ ASSERT(Pfn->u3.e2.ReferenceCount == 0);
+
+ /* Transition pages are supposed to be standby/modified/nowrite */
+ ListHead = MmPageLocationList[Pfn->u3.e1.PageLocation];
+ ASSERT(ListHead->ListName >= StandbyPageList);
+
+ /* Check if this was standby, or modified */
+ if (ListHead == &MmStandbyPageListHead)
+ {
+ /* Should not be a ROM page */
+ ASSERT(Pfn->u3.e1.Rom == 0);
+
+ /* Get the exact list */
+ ListHead = &MmStandbyPageListByPriority[Pfn->u4.Priority];
+
+ /* See if we hit any thresholds */
+ if (MmAvailablePages == MmHighMemoryThreshold)
+ {
+ /* Clear the high memory event */
+ KeClearEvent(MiHighMemoryEvent);
+ }
+ else if (MmAvailablePages == MmLowMemoryThreshold)
+ {
+ /* Signal the low memory event */
+ KeSetEvent(MiLowMemoryEvent, 0, FALSE);
+ }
+
+ /* Decrease transition page counter */
+ ASSERT(Pfn->u3.e1.PrototypePte == 1); /* Only supported ARM3 case */
+ MmTransitionSharedPages--;
+
+ /* One less page */
+ if (--MmAvailablePages < MmMinimumFreePages)
+ {
+ /* FIXME: Should wake up the MPW and working set manager, if we had one */
+ DPRINT1("Running low on pages: %d remaining\n", MmAvailablePages);
+
+ /* Call RosMm and see if it can release any pages for us */
+ MmRebalanceMemoryConsumers();
+ }
+ }
+ else if (ListHead == &MmModifiedPageListHead)
+ {
+ /* Only shared memory (page-file backed) modified pages are supported */
+ ASSERT(Pfn->OriginalPte.u.Soft.Prototype == 0);
+
+ /* Decrement the counters */
+ ListHead->Total--;
+ MmTotalPagesForPagingFile--;
+
+ /* Pick the correct colored list */
+ ListHead = &MmModifiedPageListByColor[0];
+
+ /* Decrease transition page counter */
+ ASSERT(Pfn->u3.e1.PrototypePte == 1); /* Only supported ARM3 case */
+ MmTransitionSharedPages--;
+ }
+ else if (ListHead == &MmModifiedNoWritePageListHead)
+ {
+ /* List not yet supported */
+ ASSERT(FALSE);
+ }
+
+ /* Nothing should be in progress and the list should not be empty */
+ ASSERT(Pfn->u3.e1.WriteInProgress == 0);
+ ASSERT(Pfn->u3.e1.ReadInProgress == 0);
+ ASSERT(ListHead->Total != 0);
+
+ /* Get the forward and back pointers */
+ OldFlink = Pfn->u1.Flink;
+ OldBlink = Pfn->u2.Blink;
+
+ /* Check if the next entry is the list head */
+ if (OldFlink != LIST_HEAD)
+ {
+ /* It is not, so set the backlink of the actual entry, to our backlink */
+ MI_PFN_ELEMENT(OldFlink)->u2.Blink = OldBlink;
+ }
+ else
+ {
+ /* Set the list head's backlink instead */
+ ListHead->Blink = OldBlink;
+ }
+
+ /* Check if the back entry is the list head */
+ if (OldBlink != LIST_HEAD)
+ {
+ /* It is not, so set the backlink of the actual entry, to our backlink */
+ MI_PFN_ELEMENT(OldBlink)->u1.Flink = OldFlink;
+ }
+ else
+ {
+ /* Set the list head's backlink instead */
+ ListHead->Flink = OldFlink;
+ }
+
+ /* ReactOS Hack */
+ Pfn->OriginalPte.u.Long = 0;
+
+ /* We are not on a list anymore */
+ Pfn->u1.Flink = Pfn->u2.Blink = 0;
+ ASSERT_LIST_INVARIANT(ListHead);
+
+ /* Remove one entry from the list */
+ ListHead->Total--;
}
PFN_NUMBER
Author: sir_richard
Date: Mon Mar 26 07:26:36 2012
New Revision: 56232
URL: http://svn.reactos.org/svn/reactos?rev=56232&view=rev
Log:
[NTOS]: Perform system space mappings under the SystemSpaceViewLockPointer guarded mutex.
[NTOS]: Expand system space view buckets when they are running low.
[NTOS]: Support SEC_BASED section creates and mappings, implement based VAD parsing.
[NTOS]: Support section mappings at a fixed base address and check for conflicts.
[NTOS]: Define 8 prioritized standyby lists and initialize them. Also define the modified page list.
[NTOS]: Support mapping with SEC_COMMIT less than the entire size of the section.
[NTOS]: Detect and assert if ARM3 sections are attempted to be unmapped, since this isn't supported yet.
[NTOS]: Clean up some DPRINTs and clarify ARM3 ASSERTs vs. Windows ASSERTs.
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
trunk/reactos/ntoskrnl/mm/ARM3/mminit.c
trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c
trunk/reactos/ntoskrnl/mm/ARM3/section.c
trunk/reactos/ntoskrnl/mm/ARM3/vadnode.c
trunk/reactos/ntoskrnl/mm/section.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/miarm.h?r…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] Mon Mar 26 07:26:36 2012
@@ -26,7 +26,7 @@
MI_SESSION_IMAGE_SIZE + \
MI_SESSION_WORKING_SET_SIZE)
-#define MI_SYSTEM_VIEW_SIZE (16 * _1MB)
+#define MI_SYSTEM_VIEW_SIZE (32 * _1MB)
#define MI_HIGHEST_USER_ADDRESS (PVOID)0x7FFEFFFF
#define MI_USER_PROBE_ADDRESS (PVOID)0x7FFF0000
@@ -526,6 +526,7 @@
extern MM_PAGED_POOL_INFO MmPagedPoolInfo;
extern RTL_BITMAP MiPfnBitMap;
extern KGUARDED_MUTEX MmPagedPoolMutex;
+extern KGUARDED_MUTEX MmSectionCommitMutex;
extern PVOID MmPagedPoolStart;
extern PVOID MmPagedPoolEnd;
extern PVOID MmNonPagedSystemStart;
@@ -557,6 +558,7 @@
extern ULONG MmMaximumNonPagedPoolPercent;
extern ULONG MmLargeStackSize;
extern PMMCOLOR_TABLES MmFreePagesByColor[FreePageList + 1];
+extern MMPFNLIST MmStandbyPageListByPriority[8];
extern ULONG MmProductType;
extern MM_SYSTEMSIZE MmSystemSize;
extern PKEVENT MiLowMemoryEvent;
@@ -600,6 +602,9 @@
extern PVOID MiSessionViewStart; // 0xBE000000
extern ULONG MmMaximumDeadKernelStacks;
extern SLIST_HEADER MmDeadStackSListHead;
+extern MM_AVL_TABLE MmSectionBasedRoot;
+extern KGUARDED_MUTEX MmSectionBasedMutex;
+extern PVOID MmHighSectionBase;
BOOLEAN
FORCEINLINE
@@ -1264,6 +1269,12 @@
IN PMMPFN Entry
);
+VOID
+NTAPI
+MiUnlinkPageFromList(
+ IN PMMPFN Pfn
+);
+
PFN_NUMBER
NTAPI
MiAllocatePfn(
@@ -1405,6 +1416,16 @@
NTSTATUS
NTAPI
+MiFindEmptyAddressRangeDownBasedTree(
+ IN SIZE_T Length,
+ IN ULONG_PTR BoundaryAddress,
+ IN ULONG_PTR Alignment,
+ IN PMM_AVL_TABLE Table,
+ OUT PULONG_PTR Base
+);
+
+NTSTATUS
+NTAPI
MiFindEmptyAddressRangeInTree(
IN SIZE_T Length,
IN ULONG_PTR Alignment,
@@ -1418,6 +1439,28 @@
MiInsertVad(
IN PMMVAD Vad,
IN PEPROCESS Process
+);
+
+VOID
+NTAPI
+MiInsertBasedSection(
+ IN PSECTION Section
+);
+
+NTSTATUS
+NTAPI
+MiUnmapViewOfSection(
+ IN PEPROCESS Process,
+ IN PVOID BaseAddress,
+ IN ULONG Flags
+);
+
+NTSTATUS
+NTAPI
+MiRosUnmapViewOfSection(
+ IN PEPROCESS Process,
+ IN PVOID BaseAddress,
+ IN ULONG Flags
);
VOID
@@ -1520,10 +1563,24 @@
IN ULONG Protect
);
+NTSTATUS
+NTAPI
+MiRosUnmapViewInSystemSpace(
+ IN PVOID MappedBase
+);
+
POOL_TYPE
NTAPI
MmDeterminePoolType(
IN PVOID PoolAddress
+);
+
+VOID
+NTAPI
+MiMakePdeExistAndMakeValid(
+ IN PMMPTE PointerPde,
+ IN PEPROCESS TargetProcess,
+ IN KIRQL OldIrql
);
//
Modified: trunk/reactos/ntoskrnl/mm/ARM3/mminit.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/mminit.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/mminit.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/mminit.c [iso-8859-1] Mon Mar 26 07:26:36 2012
@@ -149,7 +149,7 @@
// The system view space, on the other hand, is where sections that are memory
// mapped into "system space" end up.
//
-// By default, it is a 16MB region.
+// By default, it is a 16MB region, but we hack it to be 32MB for ReactOS
//
PVOID MiSystemViewStart;
SIZE_T MmSystemViewSize;
@@ -1134,7 +1134,7 @@
/* See how many pages are in this run */
i = Entry->PageCount;
BasePage = Entry->BasePage;
-
+
/* Loop each page */
Pfn1 = MiGetPfnEntry(BasePage);
while (i--)
@@ -2062,12 +2062,27 @@
/* Initialize session space address layout */
MiInitializeSessionSpaceLayout();
+
+ /* Set the based section highest address */
+ MmHighSectionBase = (PVOID)((ULONG_PTR)MmHighestUserAddress - 0x800000);
+
+ /* Loop all 8 standby lists */
+ for (i = 0; i < 8; i++)
+ {
+ /* Initialize them */
+ MmStandbyPageListByPriority[i].Total = 0;
+ MmStandbyPageListByPriority[i].ListName = StandbyPageList;
+ MmStandbyPageListByPriority[i].Flink = MM_EMPTY_LIST;
+ MmStandbyPageListByPriority[i].Blink = MM_EMPTY_LIST;
+ }
/* Initialize the user mode image list */
InitializeListHead(&MmLoadedUserImageList);
- /* Initialize the paged pool mutex */
+ /* Initialize the paged pool mutex and the section commit mutex */
KeInitializeGuardedMutex(&MmPagedPoolMutex);
+ KeInitializeGuardedMutex(&MmSectionCommitMutex);
+ KeInitializeGuardedMutex(&MmSectionBasedMutex);
/* Initialize the Loader Lock */
KeInitializeMutant(&MmSystemLoadLock, FALSE);
Modified: trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/pfnlist.c [iso-8859-1] Mon Mar 26 07:26:36 2012
@@ -35,10 +35,15 @@
BOOLEAN MmMirroring;
ULONG MmSystemPageColor;
+ULONG MmTransitionSharedPages;
+ULONG MmTotalPagesForPagingFile;
+
MMPFNLIST MmZeroedPageListHead = {0, ZeroedPageList, LIST_HEAD, LIST_HEAD};
MMPFNLIST MmFreePageListHead = {0, FreePageList, LIST_HEAD, LIST_HEAD};
MMPFNLIST MmStandbyPageListHead = {0, StandbyPageList, LIST_HEAD, LIST_HEAD};
+MMPFNLIST MmStandbyPageListByPriority[8];
MMPFNLIST MmModifiedPageListHead = {0, ModifiedPageList, LIST_HEAD, LIST_HEAD};
+MMPFNLIST MmModifiedPageListByColor[1] = {{0, ModifiedPageList, LIST_HEAD, LIST_HEAD}};
MMPFNLIST MmModifiedNoWritePageListHead = {0, ModifiedNoWritePageList, LIST_HEAD, LIST_HEAD};
MMPFNLIST MmBadPageListHead = {0, BadPageList, LIST_HEAD, LIST_HEAD};
MMPFNLIST MmRomPageListHead = {0, StandbyPageList, LIST_HEAD, LIST_HEAD};
Modified: trunk/reactos/ntoskrnl/mm/ARM3/section.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/section.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/section.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/section.c [iso-8859-1] Mon Mar 26 07:26:36 2012
@@ -82,6 +82,10 @@
};
MMSESSION MmSession;
+KGUARDED_MUTEX MmSectionCommitMutex;
+MM_AVL_TABLE MmSectionBasedRoot;
+KGUARDED_MUTEX MmSectionBasedMutex;
+PVOID MmHighSectionBase;
/* PRIVATE FUNCTIONS **********************************************************/
@@ -243,19 +247,87 @@
IN PCONTROL_AREA ControlArea)
{
PVOID Base;
- ULONG Entry, Hash, i;
+ ULONG Entry, Hash, i, HashSize;
+ PMMVIEW OldTable;
PAGED_CODE();
/* Only global mappings supported for now */
ASSERT(Session == &MmSession);
- /* Stay within 4GB and don't go past the number of hash entries available */
+ /* Stay within 4GB */
ASSERT(Buckets < MI_SYSTEM_VIEW_BUCKET_SIZE);
- ASSERT(Session->SystemSpaceHashEntries < Session->SystemSpaceHashSize);
+
+ /* Lock system space */
+ KeAcquireGuardedMutex(Session->SystemSpaceViewLockPointer);
+
+ /* Check if we're going to exhaust hash entries */
+ if ((Session->SystemSpaceHashEntries + 8) > Session->SystemSpaceHashSize)
+ {
+ /* Double the hash size */
+ HashSize = Session->SystemSpaceHashSize * 2;
+
+ /* Save the old table and allocate a new one */
+ OldTable = Session->SystemSpaceViewTable;
+ Session->SystemSpaceViewTable = ExAllocatePoolWithTag(NonPagedPool,
+ HashSize *
+ sizeof(MMVIEW),
+ ' mM');
+ if (!Session->SystemSpaceViewTable)
+ {
+ /* Failed to allocate a new table, keep the old one for now */
+ Session->SystemSpaceViewTable = OldTable;
+ }
+ else
+ {
+ /* Clear the new table and set the new ahsh and key */
+ RtlZeroMemory(Session->SystemSpaceViewTable, HashSize * sizeof(MMVIEW));
+ Session->SystemSpaceHashSize = HashSize;
+ Session->SystemSpaceHashKey = Session->SystemSpaceHashSize - 1;
+
+ /* Loop the old table */
+ for (i = 0; i < Session->SystemSpaceHashSize / 2; i++)
+ {
+ /* Check if the entry was valid */
+ if (OldTable[i].Entry)
+ {
+ /* Re-hash the old entry and search for space in the new table */
+ Hash = (OldTable[i].Entry >> 16) % Session->SystemSpaceHashKey;
+ while (Session->SystemSpaceViewTable[Hash].Entry)
+ {
+ /* Loop back at the beginning if we had an overflow */
+ if (++Hash >= Session->SystemSpaceHashSize) Hash = 0;
+ }
+
+ /* Write the old entry in the new table */
+ Session->SystemSpaceViewTable[Hash] = OldTable[i];
+ }
+ }
+
+ /* Free the old table */
+ ExFreePool(OldTable);
+ }
+ }
+
+ /* Check if we ran out */
+ if (Session->SystemSpaceHashEntries == Session->SystemSpaceHashSize)
+ {
+ DPRINT1("Ran out of system view hash entries\n");
+ KeReleaseGuardedMutex(Session->SystemSpaceViewLockPointer);
+ return NULL;
+ }
/* Find space where to map this view */
i = RtlFindClearBitsAndSet(Session->SystemSpaceBitMap, Buckets, 0);
- ASSERT(i != 0xFFFFFFFF);
+ if (i == 0xFFFFFFFF)
+ {
+ /* Out of space, fail */
+ Session->BitmapFailures++;
+ DPRINT1("Out of system view space\n");
+ KeReleaseGuardedMutex(Session->SystemSpaceViewLockPointer);
+ return NULL;
+ }
+
+ /* Compute the base address */
Base = (PVOID)((ULONG_PTR)Session->SystemSpaceViewStart + (i * MI_SYSTEM_VIEW_BUCKET_SIZE));
/* Get the hash entry for this allocation */
@@ -275,6 +347,7 @@
/* Hash entry found, increment total and return the base address */
Session->SystemSpaceHashEntries++;
+ KeReleaseGuardedMutex(Session->SystemSpaceViewLockPointer);
return Base;
}
@@ -701,30 +774,25 @@
PSEGMENT Segment;
PFN_NUMBER PteOffset;
NTSTATUS Status;
-
- /* Get the segment and subection for this section */
+ ULONG QuotaCharge = 0, QuotaExcess = 0;
+ PMMPTE PointerPte, LastPte;
+ MMPTE TempPte;
+
+ /* Get the segment for this section */
Segment = ControlArea->Segment;
- Subsection = (PSUBSECTION)(ControlArea + 1);
-
- /* Non-pagefile-backed sections not supported */
- ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
- ASSERT(ControlArea->u.Flags.Rom == 0);
- ASSERT(ControlArea->FilePointer == NULL);
- ASSERT(Segment->SegmentFlags.TotalNumberOfPtes4132 == 0);
-
- /* Based sections not supported */
- ASSERT(Section->Address.StartingVpn == 0);
-
- /* These flags/parameters are not supported */
+
+ /* One can only reserve a file-based mapping, not shared memory! */
+ if ((AllocationType & MEM_RESERVE) && !(ControlArea->FilePointer))
+ {
+ return STATUS_INVALID_PARAMETER_9;
+ }
+
+ /* This flag determines alignment, but ARM3 does not yet support it */
ASSERT((AllocationType & MEM_DOS_LIM) == 0);
- ASSERT((AllocationType & MEM_RESERVE) == 0);
- ASSERT(Process->VmTopDown == 0);
- ASSERT(Section->u.Flags.CopyOnWrite == FALSE);
- ASSERT(ZeroBits == 0);
/* First, increase the map count. No purging is supported yet */
Status = MiCheckPurgeAndUpMapCount(ControlArea, FALSE);
- ASSERT(NT_SUCCESS(Status));
+ if (!NT_SUCCESS(Status)) return Status;
/* Check if the caller specified the view size */
if (!(*ViewSize))
@@ -742,29 +810,57 @@
SectionOffset->LowPart &= ~((ULONG)_64K - 1);
}
- /* We must be dealing with a 64KB aligned offset */
+ /* We must be dealing with a 64KB aligned offset. This is a Windows ASSERT */
ASSERT((SectionOffset->LowPart & ((ULONG)_64K - 1)) == 0);
/* It's illegal to try to map more than 2GB */
+ /* FIXME: Should dereference the control area */
if (*ViewSize >= 0x80000000) return STATUS_INVALID_VIEW_SIZE;
+
+ /* Windows ASSERTs for this flag */
+ ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
+
+ /* Get the subsection. We don't support LARGE_CONTROL_AREA in ARM3 */
+ ASSERT(ControlArea->u.Flags.Rom == 0);
+ Subsection = (PSUBSECTION)(ControlArea + 1);
+
+ /* Sections with extended segments are not supported in ARM3 */
+ ASSERT(Segment->SegmentFlags.TotalNumberOfPtes4132 == 0);
/* Within this section, figure out which PTEs will describe the view */
PteOffset = (PFN_NUMBER)(SectionOffset->QuadPart >> PAGE_SHIFT);
- /* The offset must be in this segment's PTE chunk and it must be valid */
+ /* The offset must be in this segment's PTE chunk and it must be valid. Windows ASSERTs */
ASSERT(PteOffset < Segment->TotalNumberOfPtes);
ASSERT(((SectionOffset->QuadPart + *ViewSize + PAGE_SIZE - 1) >> PAGE_SHIFT) >= PteOffset);
/* In ARM3, only one subsection is used for now. It must contain these PTEs */
ASSERT(PteOffset < Subsection->PtesInSubsection);
+
+ /* In ARM3, only page-file backed sections (shared memory) are supported now */
+ ASSERT(ControlArea->FilePointer == NULL);
+
+ /* Windows ASSERTs for this too -- there must be a subsection base address */
ASSERT(Subsection->SubsectionBase != NULL);
- /* In ARM3, only MEM_COMMIT is supported for now. The PTEs must've been committed */
- ASSERT(Segment->NumberOfCommittedPages >= Segment->TotalNumberOfPtes);
+ /* Compute how much commit space the segment will take */
+ if ((CommitSize) && (Segment->NumberOfCommittedPages < Segment->TotalNumberOfPtes))
+ {
+ PointerPte = &Subsection->SubsectionBase[PteOffset];
+ LastPte = PointerPte + BYTES_TO_PAGES(CommitSize);
+ QuotaCharge = LastPte - PointerPte;
+ }
+
+ /* ARM3 does not currently support large pages */
+ ASSERT(Segment->SegmentFlags.LargePages == 0);
/* Did the caller specify an address? */
- if (!(*BaseAddress))
- {
+ 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)
{
@@ -787,21 +883,43 @@
&StartAddress);
ASSERT(NT_SUCCESS(Status));
}
+
+ /* Get the ending address, which is the last piece we need for the VAD */
+ EndingAddress = (StartAddress + *ViewSize - 1) | (PAGE_SIZE - 1);
}
else
{
- /* This (rather easy) code path is not yet implemented */
- UNIMPLEMENTED;
- while (TRUE);
- }
-
- /* Get the ending address, which is the last piece we need for the VAD */
- EndingAddress = (StartAddress + *ViewSize - 1) | (PAGE_SIZE - 1);
+ /* 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 */
+ if (MiCheckForConflictingNode(StartAddress >> PAGE_SHIFT,
+ EndingAddress >> PAGE_SHIFT,
+ &Process->VadRoot))
+ {
+ DPRINT1("Conflict with SEC_BASED or manually based section!\n");
+ return STATUS_CONFLICTING_ADDRESSES; // FIXME: CA Leak
+ }
+ }
/* A VAD can now be allocated. Do so and zero it out */
/* FIXME: we are allocating a LONG VAD for ReactOS compatibility only */
+ ASSERT((AllocationType & MEM_RESERVE) == 0); /* ARM3 does not support this */
Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD_LONG), 'ldaV');
- ASSERT(Vad);
+ if (!Vad) return STATUS_INSUFFICIENT_RESOURCES; /* FIXME: CA Leak */
RtlZeroMemory(Vad, sizeof(MMVAD_LONG));
Vad->u4.Banked = (PVOID)0xDEADBABE;
@@ -822,10 +940,10 @@
/* Finally, write down the first and last prototype PTE */
Vad->FirstPrototypePte = &Subsection->SubsectionBase[PteOffset];
PteOffset += (Vad->EndingVpn - Vad->StartingVpn);
+ ASSERT(PteOffset < Subsection->PtesInSubsection);
Vad->LastContiguousPte = &Subsection->SubsectionBase[PteOffset];
- /* Make sure the last PTE is valid and still within the subsection */
- ASSERT(PteOffset < Subsection->PtesInSubsection);
+ /* Make sure the prototype PTE ranges make sense, this is a Windows ASSERT */
ASSERT(Vad->FirstPrototypePte <= Vad->LastContiguousPte);
/* FIXME: Should setup VAD bitmap */
@@ -842,11 +960,49 @@
/* 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)
+ {
+ /* Set the start and end PTE addresses, and pick the template PTE */
+ PointerPte = Vad->FirstPrototypePte;
+ LastPte = PointerPte + BYTES_TO_PAGES(CommitSize);
+ TempPte = Segment->SegmentPteTemplate;
+
+ /* Acquire the commit lock and loop all prototype PTEs to be committed */
+ KeAcquireGuardedMutexUnsafe(&MmSectionCommitMutex);
+ while (PointerPte < LastPte)
+ {
+ /* Make sure the PTE is already invalid */
+ if (PointerPte->u.Long == 0)
+ {
+ /* And write the invalid PTE */
+ MI_WRITE_INVALID_PTE(PointerPte, TempPte);
+ }
+ else
+ {
+ /* The PTE is valid, so skip it */
+ QuotaExcess++;
+ }
+
+ /* Move to the next PTE */
+ PointerPte++;
+ }
+
+ /* Now check how many pages exactly we committed, and update accounting */
+ ASSERT(QuotaCharge >= QuotaExcess);
+ QuotaCharge -= QuotaExcess;
+ Segment->NumberOfCommittedPages += QuotaCharge;
+ ASSERT(Segment->NumberOfCommittedPages <= Segment->TotalNumberOfPtes);
+
+ /* Now that we're done, release the lock */
+ KeReleaseGuardedMutexUnsafe(&MmSectionCommitMutex);
+ }
/* 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;
- DPRINT1("Start and region: 0x%p, 0x%p\n", *BaseAddress, *ViewSize);
+ DPRINT("Start and region: 0x%p, 0x%p\n", *BaseAddress, *ViewSize);
return STATUS_SUCCESS;
}
@@ -1226,7 +1382,6 @@
ASSERT(FileHandle == NULL);
ASSERT(FileObject == NULL);
ASSERT((AllocationAttributes & SEC_LARGE_PAGES) == 0);
- ASSERT((AllocationAttributes & SEC_BASED) == 0);
/* Make the same sanity checks that the Nt interface should've validated */
ASSERT((AllocationAttributes & ~(SEC_COMMIT | SEC_RESERVE | SEC_BASED |
@@ -1258,10 +1413,10 @@
ProtectionMask,
AllocationAttributes);
ASSERT(NT_SUCCESS(Status));
+ ASSERT(NewSegment != NULL);
/* Set the initial section object data */
Section.InitialPageProtection = SectionPageProtection;
- Section.Segment = NULL;
Section.SizeOfSection.QuadPart = NewSegment->SizeOfSegment;
Section.Segment = NewSegment;
@@ -1296,6 +1451,49 @@
/* Now copy the local section object from the stack into this new object */
RtlCopyMemory(NewSection, &Section, sizeof(SECTION));
NewSection->Address.StartingVpn = 0;
+ NewSection->u.Flags.UserReference = TRUE;
+
+ /* Migrate the attribute into a flag */
+ if (AllocationAttributes & SEC_NO_CHANGE) NewSection->u.Flags.NoChange = TRUE;
+
+ /* If R/W access is not requested, this might eventually become a CoW mapping */
+ if (!(SectionPageProtection & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE)))
+ {
+ NewSection->u.Flags.CopyOnWrite = TRUE;
+ }
+
+ /* Is this a "based" allocation, in which all mappings are identical? */
+ if (AllocationAttributes & SEC_BASED)
+ {
+ /* Convert the flag, and make sure the section isn't too big */
+ NewSection->u.Flags.Based = TRUE;
+ if (NewSection->SizeOfSection.QuadPart > (ULONG_PTR)MmHighSectionBase)
+ {
+ DPRINT1("BASED section is too large\n");
+ ObDereferenceObject(NewSection);
+ return STATUS_NO_MEMORY;
+ }
+
+ /* Lock the VAD tree during the search */
+ KeAcquireGuardedMutex(&MmSectionBasedMutex);
+
+ /* Find an address top-down */
+ Status = MiFindEmptyAddressRangeDownBasedTree(NewSection->SizeOfSection.LowPart,
+ (ULONG_PTR)MmHighSectionBase,
+ _64K,
+ &MmSectionBasedRoot,
+ &NewSection->Address.StartingVpn);
+ ASSERT(NT_SUCCESS(Status));
+
+ /* Compute the ending address and insert it into the VAD tree */
+ NewSection->Address.EndingVpn = NewSection->Address.StartingVpn +
+ NewSection->SizeOfSection.LowPart -
+ 1;
+ MiInsertBasedSection(NewSection);
+
+ /* Finally release the lock */
+ KeReleaseGuardedMutex(&MmSectionBasedMutex);
+ }
/* Return the object and the creation status */
*SectionObject = (PVOID)NewSection;
@@ -1421,7 +1619,7 @@
if (!Process->VmDeleted)
{
/* Do the actual mapping */
- DPRINT1("Mapping ARM3 data section\n");
+ DPRINT("Mapping ARM3 data section\n");
Status = MiMapViewOfDataSection(ControlArea,
Process,
BaseAddress,
@@ -1494,6 +1692,30 @@
return STATUS_NOT_IMPLEMENTED;
}
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+MmUnmapViewInSystemSpace(IN PVOID MappedBase)
+{
+ PMEMORY_AREA MemoryArea;
+ PAGED_CODE();
+
+ /* Was this mapped by RosMm? */
+ MemoryArea = MmLocateMemoryAreaByAddress(MmGetKernelAddressSpace(), MappedBase);
+ if ((MemoryArea) && (MemoryArea->Type != MEMORY_AREA_OWNED_BY_ARM3))
+ {
+ return MiRosUnmapViewInSystemSpace(MappedBase);
+ }
+
+ /* It was not, call the ARM3 routine */
+ ASSERT(FALSE);
+ return STATUS_SUCCESS;
+// DPRINT("ARM3 unmapping\n");
+// return MiUnmapViewInSystemSpace(&MmSession, MappedBase);
+}
+
/* SYSTEM CALLS ***************************************************************/
NTSTATUS
Modified: trunk/reactos/ntoskrnl/mm/ARM3/vadnode.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/vadnode.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/vadnode.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/vadnode.c [iso-8859-1] Mon Mar 26 07:26:36 2012
@@ -163,6 +163,21 @@
VOID
NTAPI
+MiInsertBasedSection(IN PSECTION Section)
+{
+ TABLE_SEARCH_RESULT Result;
+ PMMADDRESS_NODE Parent = NULL;
+ ASSERT(Section->Address.EndingVpn >= Section->Address.StartingVpn);
+
+ /* Find the parent VAD and where this child should be inserted */
+ Result = RtlpFindAvlTableNodeOrParent(&MmSectionBasedRoot, (PVOID)Section->Address.StartingVpn, &Parent);
+ ASSERT(Result != TableFoundNode);
+ ASSERT((Parent != NULL) || (Result == TableEmptyTree));
+ MiInsertNode(&MmSectionBasedRoot, &Section->Address, Parent, Result);
+}
+
+VOID
+NTAPI
MiRemoveNode(IN PMMADDRESS_NODE Node,
IN PMM_AVL_TABLE Table)
{
@@ -471,4 +486,101 @@
return TableFoundNode;
}
+NTSTATUS
+NTAPI
+MiFindEmptyAddressRangeDownBasedTree(IN SIZE_T Length,
+ IN ULONG_PTR BoundaryAddress,
+ IN ULONG_PTR Alignment,
+ IN PMM_AVL_TABLE Table,
+ OUT PULONG_PTR Base)
+{
+ PMMADDRESS_NODE Node, LowestNode;
+ ULONG_PTR LowVpn, BestVpn;
+
+ /* Sanity checks */
+ ASSERT(Table == &MmSectionBasedRoot);
+ ASSERT(BoundaryAddress);
+ ASSERT(BoundaryAddress <= ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1));
+
+ /* Compute page length, make sure the boundary address is valid */
+ Length = ROUND_TO_PAGES(Length);
+ if ((BoundaryAddress + 1) < Length) return STATUS_NO_MEMORY;
+
+ /* Check if the table is empty */
+ BestVpn = ROUND_UP(BoundaryAddress + 1 - Length, Alignment);
+ if (Table->NumberGenericTableElements == 0)
+ {
+ /* Tree is empty, the candidate address is already the best one */
+ *Base = BestVpn;
+ return STATUS_SUCCESS;
+ }
+
+ /* Go to the right-most node which should be the biggest address */
+ Node = Table->BalancedRoot.RightChild;
+ while (RtlRightChildAvl(Node)) Node = RtlRightChildAvl(Node);
+
+ /* Check if we can fit in here */
+ LowVpn = ROUND_UP(Node->EndingVpn, Alignment);
+ if ((LowVpn < BoundaryAddress) && (Length < (BoundaryAddress - LowVpn)))
+ {
+ /* Return the address */
+ *Base = ROUND_UP(BoundaryAddress - Length, Alignment);
+ return STATUS_SUCCESS;
+ }
+
+ /* Now loop the Vad nodes */
+ do
+ {
+ /* Break out if we've reached the last node */
+ LowestNode = MiGetPreviousNode(Node);
+ if (!LowestNode) break;
+
+ /* Check if this node could contain the requested address */
+ LowVpn = ROUND_UP(LowestNode->EndingVpn + 1, Alignment);
+ if ((LowestNode->EndingVpn < BestVpn) &&
+ (Length <= (Node->StartingVpn - LowVpn)))
+ {
+ /* Check if it fits in perfectly */
+ if ((BestVpn > LowestNode->EndingVpn) &&
+ (BoundaryAddress < Node->StartingVpn))
+ {
+ /* Return the optimal VPN address */
+ *Base = BestVpn;
+ return STATUS_SUCCESS;
+ }
+
+ /* It doesn't, check if it can partly fit */
+ if (Node->StartingVpn > LowVpn)
+ {
+ /* Return an aligned base address within this node */
+ *Base = ROUND_UP(Node->StartingVpn - Length, Alignment);
+ return STATUS_SUCCESS;
+ }
+ }
+
+ /* Move to the next node */
+ Node = LowestNode;
+ } while (TRUE);
+
+ /* Check if there's enough space before the lowest Vad */
+ if ((Node->StartingVpn > (ULONG_PTR)MI_LOWEST_VAD_ADDRESS) &&
+ ((Node->StartingVpn - (ULONG_PTR)MI_LOWEST_VAD_ADDRESS) > Length))
+ {
+ /* Check if it fits in perfectly */
+ if (BoundaryAddress < Node->StartingVpn)
+ {
+ /* Return the optimal VPN address */
+ *Base = BestVpn;
+ return STATUS_SUCCESS;
+ }
+
+ /* Return an aligned base address within this node */
+ *Base = ROUND_UP(Node->StartingVpn - Length, Alignment);
+ return STATUS_SUCCESS;
+ }
+
+ /* No address space left at all */
+ return STATUS_NO_MEMORY;
+}
+
/* EOF */
Modified: trunk/reactos/ntoskrnl/mm/section.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/section.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] Mon Mar 26 07:26:36 2012
@@ -2855,6 +2855,10 @@
DPRINT("Creating Section Object Type\n");
+ /* Initialize the section based root */
+ ASSERT(MmSectionBasedRoot.NumberGenericTableElements == 0);
+ MmSectionBasedRoot.BalancedRoot.u1.Parent = &MmSectionBasedRoot.BalancedRoot;
+
/* Initialize the Section object type */
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
RtlInitUnicodeString(&Name, L"Section");
@@ -4231,6 +4235,7 @@
MemoryArea->Type != MEMORY_AREA_SECTION_VIEW ||
MemoryArea->DeleteInProgress)
{
+ ASSERT(MemoryArea->Type != MEMORY_AREA_OWNED_BY_ARM3);
MmUnlockAddressSpace(AddressSpace);
return STATUS_NOT_MAPPED_VIEW;
}
@@ -4538,7 +4543,7 @@
if (MiIsRosSectionObject(SectionObject) == FALSE)
{
- DPRINT1("Mapping ARM3 section into %s\n", Process->ImageFileName);
+ DPRINT("Mapping ARM3 section into %s\n", Process->ImageFileName);
return MmMapViewOfArm3Section(SectionObject,
Process,
BaseAddress,
@@ -4875,7 +4880,6 @@
if (MiIsRosSectionObject(SectionObject) == FALSE)
{
- DPRINT1("ARM3 System Mapping\n");
return MiMapViewInSystemSpace(SectionObject,
&MmSession,
MappedBase,
@@ -4917,11 +4921,9 @@
return Status;
}
-/*
- * @implemented
- */
-NTSTATUS NTAPI
-MmUnmapViewInSystemSpace (IN PVOID MappedBase)
+NTSTATUS
+NTAPI
+MiRosUnmapViewInSystemSpace(IN PVOID MappedBase)
{
PMMSUPPORT AddressSpace;
NTSTATUS Status;
@@ -4938,7 +4940,6 @@
return Status;
}
-
/**********************************************************************
* NAME EXPORTED