Author: ros-arm-bringup
Date: Sat Jun 27 12:41:45 2009
New Revision: 41636
URL:
http://svn.reactos.org/svn/reactos?rev=41636&view=rev
Log:
- Reimplement kernel stack allocation (MmCreateKernelStack, MmDeleteKernelStack,
MmGrowKernelStack, MmGrowKernelStackEx):
- Use System PTEs.
- Allocate 12KB stacks with a 4KB guard page, and expand them up to 60KB as required.
- Previous implementation always allocated 60KB, without any guard page.
- The result is that on a minimal ReactOS install, simply booting up now requires an
average of 0.5MB less of physical memory than before.
- And once again, optimizations to the system PTE allocation code should significantly
improve performance.
- Should also analyze benefits of using a dead stack slist as done on Windows. (Assembla
Ticket #39).
Added:
trunk/reactos/ntoskrnl/mm/ARM3/procsup.c (with props)
Modified:
trunk/reactos/ntoskrnl/mm/procsup.c
trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild
Added: trunk/reactos/ntoskrnl/mm/ARM3/procsup.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/procsup.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/procsup.c (added)
+++ trunk/reactos/ntoskrnl/mm/ARM3/procsup.c [iso-8859-1] Sat Jun 27 12:41:45 2009
@@ -1,0 +1,285 @@
+/*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: BSD - See COPYING.ARM in the top level directory
+ * FILE: ntoskrnl/mm/ARM3/procsup.c
+ * PURPOSE: ARM Memory Manager Process Related Management
+ * PROGRAMMERS: ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+
+#line 15 "ARM³::PROCSUP"
+#define MODULE_INVOLVED_IN_ARM3
+#include "../ARM3/miarm.h"
+
+ULONG PagesForStacks = 0;
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+VOID
+NTAPI
+MmDeleteKernelStack(IN PVOID StackBase,
+ IN BOOLEAN GuiStack)
+{
+ PMMPTE PointerPte;
+ PFN_NUMBER StackPages;
+ ULONG i;
+
+ //
+ // This should be the guard page, so decrement by one
+ //
+ PointerPte = MiAddressToPte(StackBase);
+ PointerPte--;
+
+ //
+ // Calculate pages used
+ //
+ StackPages = BYTES_TO_PAGES(GuiStack ?
+ KERNEL_LARGE_STACK_SIZE : KERNEL_STACK_SIZE);
+
+ //
+ // Loop them
+ //
+ for (i = 0; i < StackPages; i++)
+ {
+ //
+ // Check if this is a valid PTE
+ //
+ if (PointerPte->u.Hard.Valid == 1)
+ {
+ //
+ // Nuke it
+ //
+ MmReleasePageMemoryConsumer(MC_NPPOOL, PFN_FROM_PTE(PointerPte));
+ PagesForStacks--;
+ }
+
+ //
+ // Next one
+ //
+ PointerPte--;
+ }
+
+ //
+ // We should be at the guard page now
+ //
+ ASSERT(PointerPte->u.Hard.Valid == 0);
+
+ //
+ // Release the PTEs
+ //
+ MiReleaseSystemPtes(PointerPte, StackPages + 1, SystemPteSpace);
+}
+
+PVOID
+NTAPI
+MmCreateKernelStack(IN BOOLEAN GuiStack,
+ IN UCHAR Node)
+{
+ PFN_NUMBER StackPtes, StackPages;
+ PMMPTE PointerPte, StackPte;
+ PVOID BaseAddress;
+ MMPTE TempPte;
+ KIRQL OldIrql;
+ PFN_NUMBER PageFrameIndex;
+ ULONG i;
+
+ //
+ // Calculate pages needed
+ //
+ if (GuiStack)
+ {
+ //
+ // We'll allocate 64KB stack, but only commit 12K
+ //
+ StackPtes = BYTES_TO_PAGES(KERNEL_LARGE_STACK_SIZE);
+ StackPages = BYTES_TO_PAGES(KERNEL_LARGE_STACK_COMMIT);
+
+ }
+ else
+ {
+ //
+ // We'll allocate 12K and that's it
+ //
+ StackPtes = BYTES_TO_PAGES(KERNEL_STACK_SIZE);
+ StackPages = StackPtes;
+ }
+
+ //
+ // Reserve stack pages, plus a guard page
+ //
+ StackPte = MiReserveSystemPtes(StackPtes + 1, SystemPteSpace);
+ if (!StackPte) return NULL;
+
+ //
+ // Get the stack address
+ //
+ BaseAddress = MiPteToAddress(StackPte + StackPtes + 1);
+
+ //
+ // Select the right PTE address where we actually start committing pages
+ //
+ PointerPte = StackPte;
+ if (GuiStack) PointerPte += BYTES_TO_PAGES(KERNEL_LARGE_STACK_SIZE -
+ KERNEL_LARGE_STACK_COMMIT);
+
+ //
+ // Setup the template stack PTE
+ //
+ TempPte = HyperTemplatePte;
+ TempPte.u.Hard.Global = FALSE;
+ TempPte.u.Hard.PageFrameNumber = 0;
+ TempPte.u.Hard.Dirty = TRUE;
+
+ //
+ // Acquire the PFN DB lock
+ //
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ //
+ // Loop each stack page
+ //
+ for (i = 0; i < StackPages; i++)
+ {
+ //
+ // Next PTE
+ //
+ PointerPte++;
+ ASSERT(PointerPte->u.Hard.Valid == 0);
+
+ //
+ // Get a page
+ //
+ PageFrameIndex = MmAllocPage(MC_NPPOOL, 0);
+ TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
+
+ //
+ // Write it
+ //
+ *PointerPte = TempPte;
+ PagesForStacks++;
+ }
+
+ //
+ // Release the PFN lock
+ //
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+
+ //
+ // Return the stack address
+ //
+ return BaseAddress;
+}
+
+NTSTATUS
+NTAPI
+MmGrowKernelStackEx(IN PVOID StackPointer,
+ IN ULONG GrowSize)
+{
+ PKTHREAD Thread = KeGetCurrentThread();
+ PMMPTE LimitPte, NewLimitPte, LastPte;
+ PFN_NUMBER StackPages;
+ KIRQL OldIrql;
+ MMPTE TempPte;
+ PFN_NUMBER PageFrameIndex;
+
+ //
+ // Make sure the stack did not overflow
+ //
+ ASSERT(((ULONG_PTR)Thread->StackBase - (ULONG_PTR)Thread->StackLimit) <=
+ (KERNEL_LARGE_STACK_SIZE + PAGE_SIZE));
+
+ //
+ // Get the current stack limit
+ //
+ LimitPte = MiAddressToPte(Thread->StackLimit);
+ ASSERT(LimitPte->u.Hard.Valid == 1);
+
+ //
+ // Get the new one and make sure this isn't a retarded request
+ //
+ NewLimitPte = MiAddressToPte((PVOID)((ULONG_PTR)StackPointer - GrowSize));
+ if (NewLimitPte == LimitPte) return STATUS_SUCCESS;
+
+ //
+ // Now make sure you're not going past the reserved space
+ //
+ LastPte = MiAddressToPte((PVOID)((ULONG_PTR)Thread->StackBase -
+ KERNEL_LARGE_STACK_SIZE));
+ if (NewLimitPte < LastPte)
+ {
+ //
+ // Sorry!
+ //
+ DPRINT1("Thread wants too much stack\n");
+ return STATUS_STACK_OVERFLOW;
+ }
+
+ //
+ // Calculate the number of new pages
+ //
+ LimitPte--;
+ StackPages = (LimitPte - NewLimitPte + 1);
+
+ //
+ // Setup the template stack PTE
+ //
+ TempPte = HyperTemplatePte;
+ TempPte.u.Hard.Global = FALSE;
+ TempPte.u.Hard.PageFrameNumber = 0;
+ TempPte.u.Hard.Dirty = TRUE;
+
+ //
+ // Acquire the PFN DB lock
+ //
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ //
+ // Loop each stack page
+ //
+ while (LimitPte >= NewLimitPte)
+ {
+ //
+ // Sanity check
+ //
+ ASSERT(LimitPte->u.Hard.Valid == 0);
+
+ //
+ // Get a page
+ //
+ PageFrameIndex = MmAllocPage(MC_NPPOOL, 0);
+ TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
+
+ //
+ // Write it
+ //
+ *LimitPte-- = TempPte;
+ }
+
+ //
+ // Release the PFN lock
+ //
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+
+ //
+ // Set the new limit
+ //
+ Thread->StackLimit = (ULONG_PTR)MiPteToAddress(NewLimitPte);
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+MmGrowKernelStack(IN PVOID StackPointer)
+{
+ //
+ // Call the extended version
+ //
+ return MmGrowKernelStackEx(StackPointer, KERNEL_LARGE_STACK_COMMIT);
+}
+
+/* EOF */
Propchange: trunk/reactos/ntoskrnl/mm/ARM3/procsup.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: trunk/reactos/ntoskrnl/mm/ARM3/procsup.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: trunk/reactos/ntoskrnl/mm/procsup.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/procsup.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/procsup.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/procsup.c [iso-8859-1] Sat Jun 27 12:41:45 2009
@@ -127,38 +127,6 @@
}
VOID
-MiFreeStackPage(PVOID Context,
- MEMORY_AREA* MemoryArea,
- PVOID Address,
- PFN_TYPE Page,
- SWAPENTRY SwapEntry,
- BOOLEAN Dirty)
-{
- ASSERT(SwapEntry == 0);
- if (Page) MmReleasePageMemoryConsumer(MC_NPPOOL, Page);
-}
-
-VOID
-NTAPI
-MmDeleteKernelStack(PVOID StackBase,
- BOOLEAN GuiStack)
-{
- ULONG StackSize = GuiStack ? KERNEL_LARGE_STACK_SIZE : KERNEL_STACK_SIZE;
-
- /* Lock the Address Space */
- MmLockAddressSpace(MmGetKernelAddressSpace());
-
- /* Delete the Stack */
- MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
- (PVOID)((ULONG_PTR)StackBase - StackSize),
- MiFreeStackPage,
- NULL);
-
- /* Unlock the Address Space */
- MmUnlockAddressSpace(MmGetKernelAddressSpace());
-}
-
-VOID
NTAPI
MmDeleteTeb(PEPROCESS Process,
PTEB Teb)
@@ -178,106 +146,6 @@
/* Unlock the Address Space */
MmUnlockAddressSpace(ProcessAddressSpace);
-}
-
-PVOID
-NTAPI
-MmCreateKernelStack(BOOLEAN GuiStack,
- UCHAR Node)
-{
- PMEMORY_AREA StackArea;
- ULONG i;
- PHYSICAL_ADDRESS BoundaryAddressMultiple;
- ULONG StackSize = GuiStack ? KERNEL_LARGE_STACK_SIZE : KERNEL_STACK_SIZE;
- PFN_TYPE Page[KERNEL_LARGE_STACK_SIZE / PAGE_SIZE];
- PVOID KernelStack = NULL;
- NTSTATUS Status;
-
- /* Initialize the Boundary Address */
- BoundaryAddressMultiple.QuadPart = 0;
-
- /* Lock the Kernel Address Space */
- MmLockAddressSpace(MmGetKernelAddressSpace());
-
- /* Create a MAREA for the Kernel Stack */
- Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
- MEMORY_AREA_KERNEL_STACK,
- &KernelStack,
- StackSize,
- PAGE_READWRITE,
- &StackArea,
- FALSE,
- 0,
- BoundaryAddressMultiple);
-
- /* Unlock the Address Space */
- MmUnlockAddressSpace(MmGetKernelAddressSpace());
-
- /* Check for Success */
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to create thread stack\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
-
- /*
- * Mark the Stack in use.
- * Note: Currently we mark all 60KB in use for a GUI Thread.
- * We should only do this inside MmGrowKernelStack. TODO!
- */
- for (i = 0; i < (StackSize / PAGE_SIZE); i++)
- {
- Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page[i]);
- }
-
- /* Create a Virtual Mapping for it */
- Status = MmCreateVirtualMapping(NULL,
- KernelStack,
- PAGE_READWRITE,
- Page,
- StackSize / PAGE_SIZE);
-
- /* Check for success */
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Could not create Virtual Mapping for Kernel Stack\n");
- KeBugCheck(MEMORY_MANAGEMENT);
- }
-
- /* Return the stack base */
- return (PVOID)((ULONG_PTR)KernelStack +
- (GuiStack ? KERNEL_LARGE_STACK_SIZE : KERNEL_STACK_SIZE));
-}
-
-/*
- * @implemented
- */
-NTSTATUS
-NTAPI
-MmGrowKernelStack(PVOID StackPointer)
-{
- PETHREAD Thread = PsGetCurrentThread();
-
- /* Make sure the stack did not overflow */
- ASSERT(((PCHAR)Thread->Tcb.StackBase - (PCHAR)Thread->Tcb.StackLimit) <=
- (KERNEL_LARGE_STACK_SIZE + PAGE_SIZE));
-
- /* Check if we have reserved space for our grow */
- if ((PCHAR)Thread->Tcb.StackBase - (PCHAR)Thread->Tcb.StackLimit +
- KERNEL_STACK_SIZE > KERNEL_LARGE_STACK_SIZE)
- {
- return STATUS_STACK_OVERFLOW;
- }
-
- /*
- * We'll give you three more pages.
- * NOTE: See note in MmCreateKernelStack. These pages are already being reserved.
- * It would be more efficient to only grow them (commit them) here.
- */
- Thread->Tcb.StackLimit -= KERNEL_STACK_SIZE;
-
- /* Return success */
- return STATUS_SUCCESS;
}
NTSTATUS
Modified: trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl-generic.…
==============================================================================
--- trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] Sat Jun 27 12:41:45 2009
@@ -364,6 +364,7 @@
<file>init.c</file>
<file>iosup.c</file>
<file>pool.c</file>
+ <file>procsup.c</file>
<file>syspte.c</file>
</directory>
<file>anonmem.c</file>