Author: jgardou
Date: Sat Aug 27 13:17:10 2016
New Revision: 72472

URL: http://svn.reactos.org/svn/reactos?rev=72472&view=rev
Log:
[NTOS/MM]
 - Keep the control area as being created through the whole creation process in 
MmCreateArm3Section
 - Use the segment length to find a suitable place for SEC_BASED sections
 - Properly remove the global section node when deleting a based section
CORE-11900 #resolve

Modified:
    trunk/reactos/ntoskrnl/mm/ARM3/section.c

Modified: trunk/reactos/ntoskrnl/mm/ARM3/section.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/section.c?rev=72472&r1=72471&r2=72472&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/section.c    [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/section.c    [iso-8859-1] Sat Aug 27 
13:17:10 2016
@@ -1564,6 +1564,9 @@
     if (AllocationAttributes & SEC_RESERVE) ControlArea->u.Flags.Reserve = 1;
     if (AllocationAttributes & SEC_COMMIT) ControlArea->u.Flags.Commit = 1;
 
+    /* We just allocated it */
+    ControlArea->u.Flags.BeingCreated = 1;
+
     /* The subsection follows, write the mask, PTE count and point back to the 
CA */
     Subsection = (PSUBSECTION)(ControlArea + 1);
     Subsection->ControlArea = ControlArea;
@@ -2565,6 +2568,7 @@
         /* Set the size here, and read the control area */
         Section.SizeOfSection.QuadPart = NewSegment->SizeOfSegment;
         ControlArea = NewSegment->ControlArea;
+        ASSERT(ControlArea->u.Flags.BeingCreated == 1);
     }
 
     /* Did we already have a segment? */
@@ -2663,6 +2667,60 @@
     ASSERT(KernelCall == FALSE);
     NewSection->u.Flags.UserReference = TRUE;
 
+    /* Is this a "based" allocation, in which all mappings are identical? */
+    if (AllocationAttributes & SEC_BASED)
+    {
+        /* Lock the VAD tree during the search */
+        KeAcquireGuardedMutex(&MmSectionBasedMutex);
+
+        /* Is it a brand new ControArea ? */
+        if (ControlArea->u.Flags.BeingCreated == 1)
+        {
+            ASSERT(ControlArea->u.Flags.Based == 1);
+            /* Then we must find a global address, top-down */
+            Status = 
MiFindEmptyAddressRangeDownBasedTree((SIZE_T)ControlArea->Segment->SizeOfSegment,
+                                                          
(ULONG_PTR)MmHighSectionBase,
+                                                          _64K,
+                                                          &MmSectionBasedRoot,
+                                                          
(ULONG_PTR*)&ControlArea->Segment->BasedAddress);
+
+            if (!NT_SUCCESS(Status))
+            {
+                /* No way to find a valid range. */
+                KeReleaseGuardedMutex(&MmSectionBasedMutex);
+                ControlArea->u.Flags.Based = 0;
+                NewSection->u.Flags.Based = 0;
+                ObDereferenceObject(NewSection);
+                return Status;
+            }
+
+            /* Compute the ending address and insert it into the VAD tree */
+            NewSection->Address.StartingVpn = 
(ULONG_PTR)ControlArea->Segment->BasedAddress;
+            NewSection->Address.EndingVpn = NewSection->Address.StartingVpn + 
NewSection->SizeOfSection.LowPart - 1;
+            MiInsertBasedSection(NewSection);
+        }
+        else
+        {
+            /* FIXME : Should we deny section creation if SEC_BASED is not set 
? Can we have two different section objects on the same based address ? 
Investigate !*/
+            ASSERT(FALSE);
+        }
+
+        KeReleaseGuardedMutex(&MmSectionBasedMutex);
+    }
+
+    /* The control area is not being created anymore */
+    if (ControlArea->u.Flags.BeingCreated == 1)
+    {
+        /* Acquire the PFN lock while we set control area flags */
+        OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+        /* Take off the being created flag, and then release the lock */
+        ControlArea->u.Flags.BeingCreated = 0;
+        NewSection->u.Flags.BeingCreated = 0;
+
+        KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+    }
+
     /* Migrate the attribute into a flag */
     if (AllocationAttributes & SEC_NO_CHANGE) NewSection->u.Flags.NoChange = 
TRUE;
 
@@ -2670,40 +2728,6 @@
     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 ((ULONGLONG)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);
     }
 
     /* Write down if this was a kernel call */
@@ -3141,6 +3165,14 @@
     KIRQL OldIrql;
 
     SectionObject = (PSECTION)ObjectBody;
+
+    if (SectionObject->u.Flags.Based == 1)
+    {
+        /* Remove the node from the global section address tree */
+        KeAcquireGuardedMutex(&MmSectionBasedMutex);
+        MiRemoveNode(&SectionObject->Address, &MmSectionBasedRoot);
+        KeReleaseGuardedMutex(&MmSectionBasedMutex);
+    }
 
     /* Lock the PFN database */
     OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);


Reply via email to