From 228cddee4af9bdc048208752f3c6a209766aa771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Fri, 1 Oct 2004 20:26:05 +0000 Subject: [PATCH] Don't use more than a single page for a TEB svn path=/trunk/; revision=11143 --- reactos/ntoskrnl/include/internal/mm.h | 4 ++ reactos/ntoskrnl/include/internal/ps.h | 6 +- reactos/ntoskrnl/mm/anonmem.c | 4 +- reactos/ntoskrnl/mm/marea.c | 55 ++++++++++++---- reactos/ntoskrnl/ps/create.c | 91 ++++++++++++++++---------- reactos/ntoskrnl/ps/process.c | 16 +++-- 6 files changed, 123 insertions(+), 53 deletions(-) diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index 7bef406740c..d691844e946 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -359,6 +359,10 @@ MEMORY_AREA* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace, PVOID MmFindGap(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG Granularity, BOOL TopDown); +void MmReleaseMemoryAreaIfDecommitted(PEPROCESS Process, + PMADDRESS_SPACE AddressSpace, + PVOID BaseAddress); + /* npool.c *******************************************************************/ VOID MiDebugDumpNonPagedPool(BOOLEAN NewOnly); diff --git a/reactos/ntoskrnl/include/internal/ps.h b/reactos/ntoskrnl/include/internal/ps.h index 19232c38efd..9f19e77c475 100644 --- a/reactos/ntoskrnl/include/internal/ps.h +++ b/reactos/ntoskrnl/include/internal/ps.h @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: ps.h,v 1.69 2004/09/28 15:02:29 weiden Exp $ +/* $Id: ps.h,v 1.70 2004/10/01 20:26:04 gvg Exp $ * * FILE: ntoskrnl/ke/kthread.c * PURPOSE: Process manager definitions @@ -428,6 +428,10 @@ struct _EPROCESS struct _EJOB* Job; UINT JobStatus; + + FAST_MUTEX TebLock; + PVOID TebBlock; + PVOID TebLastAllocated; }; #define PROCESS_STATE_TERMINATED (1) diff --git a/reactos/ntoskrnl/mm/anonmem.c b/reactos/ntoskrnl/mm/anonmem.c index 29d008263c6..8b54dec2036 100644 --- a/reactos/ntoskrnl/mm/anonmem.c +++ b/reactos/ntoskrnl/mm/anonmem.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: anonmem.c,v 1.32 2004/09/28 19:49:20 gvg Exp $ +/* $Id: anonmem.c,v 1.33 2004/10/01 20:26:04 gvg Exp $ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/anonmem.c @@ -752,7 +752,7 @@ MmFreeVirtualMemory(PEPROCESS Process, } /* - * @unimplemented + * @implemented */ NTSTATUS STDCALL NtFreeVirtualMemory(IN HANDLE ProcessHandle, diff --git a/reactos/ntoskrnl/mm/marea.c b/reactos/ntoskrnl/mm/marea.c index 1c7cf164cc7..51822cf4d2b 100644 --- a/reactos/ntoskrnl/mm/marea.c +++ b/reactos/ntoskrnl/mm/marea.c @@ -201,9 +201,6 @@ static VOID MmInsertMemoryArea(PMADDRESS_SPACE AddressSpace, InsertTailList(ListHead,inserted_entry); } -#define ROUND_DOWN_POW2(Addr, Boundary) ((ULONG_PTR) (Addr) & ~ ((Boundary) - 1)) -#define ROUND_UP_POW2(Addr, Boundary) ROUND_DOWN_POW2((ULONG_PTR) (Addr) + (Boundary) - 1, Boundary) - static PVOID MmFindGapBottomUp(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG Granularity) { PLIST_ENTRY ListHead; @@ -230,7 +227,7 @@ static PVOID MmFindGapBottomUp(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG #ifdef DBG Address = (PVOID) ((char *) Address + PAGE_SIZE); /* For a guard page preceding the area */ #endif - Address = (PVOID) ROUND_UP_POW2(Address, Granularity); + Address = (PVOID) MM_ROUND_UP(Address, Granularity); if (Address < next->BaseAddress) { Gap = (char*)next->BaseAddress - ((char*)current->BaseAddress + PAGE_ROUND_UP(current->Length)); @@ -244,7 +241,7 @@ static PVOID MmFindGapBottomUp(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG if (current_entry == ListHead) { - Address = (PVOID) ROUND_UP_POW2(AddressSpace->LowestAddress, Granularity); + Address = (PVOID) MM_ROUND_UP(AddressSpace->LowestAddress, Granularity); } else { @@ -253,7 +250,7 @@ static PVOID MmFindGapBottomUp(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG #ifdef DBG Address = (PVOID) ((char *) Address + PAGE_SIZE); /* For a guard page preceding the area */ #endif - Address = (PVOID) ROUND_UP_POW2(Address, Granularity); + Address = (PVOID) MM_ROUND_UP(Address, Granularity); } /* Check if enough space for the block */ if (AddressSpace->LowestAddress < KERNEL_BASE) @@ -313,7 +310,7 @@ static PVOID MmFindGapTopDown(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG #ifdef DBG BottomAddress = (PVOID) ((char *) BottomAddress + PAGE_SIZE); /* For a guard page preceding the area */ #endif - BottomAddress = (PVOID) ROUND_UP_POW2(BottomAddress, Granularity); + BottomAddress = (PVOID) MM_ROUND_UP(BottomAddress, Granularity); DPRINT("Base %p Length %lx\n", current->BaseAddress, PAGE_ROUND_UP(current->Length)); if (BottomAddress < TopAddress && BottomAddress < HighestAddress) @@ -323,7 +320,7 @@ static PVOID MmFindGapTopDown(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG if (Gap >= Length) { DPRINT("Found gap at %p\n", (char*) TopAddress - Length); - return (PVOID) ROUND_DOWN_POW2((char*) TopAddress - Length + 1, Granularity); + return (PVOID) MM_ROUND_DOWN((char*) TopAddress - Length + 1, Granularity); } } TopAddress = (char*)current->BaseAddress - 1; @@ -332,11 +329,11 @@ static PVOID MmFindGapTopDown(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG if (current_entry == ListHead) { - Address = (PVOID) ROUND_DOWN_POW2((char*) HighestAddress - Length + 1, Granularity); + Address = (PVOID) MM_ROUND_DOWN((char*) HighestAddress - Length + 1, Granularity); } else { - Address = (PVOID) ROUND_DOWN_POW2((char*)TopAddress - Length + 1, Granularity); + Address = (PVOID) MM_ROUND_DOWN((char*)TopAddress - Length + 1, Granularity); } /* Check if enough space for the block */ @@ -596,8 +593,9 @@ NTSTATUS MmCreateMemoryArea(PEPROCESS Process, } else { - tmpLength = Length + ((ULONG_PTR) *BaseAddress - ROUND_DOWN_POW2(*BaseAddress, Granularity)); - (*BaseAddress) = (PVOID) ROUND_DOWN_POW2(*BaseAddress, Granularity); + tmpLength = Length + ((ULONG_PTR) *BaseAddress + - (ULONG_PTR) MM_ROUND_DOWN(*BaseAddress, Granularity)); + *BaseAddress = MM_ROUND_DOWN(*BaseAddress, Granularity); if (AddressSpace->LowestAddress == KERNEL_BASE && (*BaseAddress) < (PVOID)KERNEL_BASE) @@ -643,3 +641,36 @@ NTSTATUS MmCreateMemoryArea(PEPROCESS Process, DPRINT("MmCreateMemoryArea() succeeded\n"); return STATUS_SUCCESS; } + + +void +MmReleaseMemoryAreaIfDecommitted(PEPROCESS Process, + PMADDRESS_SPACE AddressSpace, + PVOID BaseAddress) +{ + PMEMORY_AREA MemoryArea; + PLIST_ENTRY Entry; + PMM_REGION Region; + BOOLEAN Reserved; + + MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, BaseAddress); + if (NULL != MemoryArea) + { + Entry = MemoryArea->Data.VirtualMemoryData.RegionListHead.Flink; + Reserved = TRUE; + while (Reserved && Entry != &MemoryArea->Data.VirtualMemoryData.RegionListHead) + { + Region = CONTAINING_RECORD(Entry, MM_REGION, RegionListEntry); + Reserved = (MEM_RESERVE == Region->Type); + Entry = Entry->Flink; + } + + if (Reserved) + { + DPRINT("Release TebBlock at %p\n", TebBlock); + MmFreeVirtualMemory(Process, MemoryArea); + } + } +} + +/* EOF */ diff --git a/reactos/ntoskrnl/ps/create.c b/reactos/ntoskrnl/ps/create.c index 61ef649dc2a..16915138b1b 100644 --- a/reactos/ntoskrnl/ps/create.c +++ b/reactos/ntoskrnl/ps/create.c @@ -1,4 +1,4 @@ -/* $Id: create.c,v 1.81 2004/09/28 15:02:29 weiden Exp $ +/* $Id: create.c,v 1.82 2004/10/01 20:26:05 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -504,51 +504,76 @@ PsCreateTeb(HANDLE ProcessHandle, PETHREAD Thread, PUSER_STACK UserStack) { - MEMORY_BASIC_INFORMATION Info; + PEPROCESS Process; NTSTATUS Status; ULONG ByteCount; ULONG RegionSize; ULONG TebSize; PVOID TebBase; TEB Teb; - ULONG ResultLength; - TebBase = (PVOID)0x7FFDE000; TebSize = PAGE_SIZE; - while (TRUE) + if (NULL == Thread->ThreadsProcess) { - Status = ZwQueryVirtualMemory(ProcessHandle, - TebBase, - MemoryBasicInformation, - &Info, - sizeof(Info), - &ResultLength); - if (!NT_SUCCESS(Status)) - { - CPRINT("ZwQueryVirtualMemory (Status %x)\n", Status); - KEBUGCHECK(0); - } - /* FIXME: Race between this and the above check */ - if (Info.State == MEM_FREE) - { - /* The TEB must reside in user space */ - Status = ZwAllocateVirtualMemory(ProcessHandle, - &TebBase, - 0, - &TebSize, - MEM_RESERVE | MEM_COMMIT, - PAGE_READWRITE); - if (NT_SUCCESS(Status)) - { - break; - } - } - - TebBase = (char*)TebBase - TebSize; + /* We'll be allocating a 64k block here and only use 4k of it, but this + path should almost never be taken. Actually, I never saw it was taken, + so maybe we should just assert(NULL != Thread->ThreadsProcess) and + move on */ + TebBase = NULL; + Status = ZwAllocateVirtualMemory(ProcessHandle, + &TebBase, + 0, + &TebSize, + MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, + PAGE_READWRITE); + if (! NT_SUCCESS(Status)) + { + DPRINT1("Failed to allocate virtual memory for TEB\n"); + return Status; + } + } + else + { + Process = Thread->ThreadsProcess; + ExAcquireFastMutex(&Process->TebLock); + if (NULL == Process->TebBlock || + Process->TebBlock == Process->TebLastAllocated) + { + Process->TebBlock = NULL; + RegionSize = MM_VIRTMEM_GRANULARITY; + Status = ZwAllocateVirtualMemory(ProcessHandle, + &Process->TebBlock, + 0, + &RegionSize, + MEM_RESERVE | MEM_TOP_DOWN, + PAGE_READWRITE); + if (! NT_SUCCESS(Status)) + { + ExReleaseFastMutex(&Process->TebLock); + DPRINT1("Failed to reserve virtual memory for TEB\n"); + return Status; + } + Process->TebLastAllocated = (PVOID) ((char *) Process->TebBlock + RegionSize); + } + TebBase = (PVOID) ((char *) Process->TebLastAllocated - PAGE_SIZE); + Status = ZwAllocateVirtualMemory(ProcessHandle, + &TebBase, + 0, + &TebSize, + MEM_COMMIT, + PAGE_READWRITE); + if (! NT_SUCCESS(Status)) + { + DPRINT1("Failed to commit virtual memory for TEB\n"); + return Status; + } + Process->TebLastAllocated = TebBase; + ExReleaseFastMutex(&Process->TebLock); } DPRINT ("TebBase %p TebSize %lu\n", TebBase, TebSize); + assert(NULL != TebBase && PAGE_SIZE <= TebSize); RtlZeroMemory(&Teb, sizeof(TEB)); /* set all pointers to and from the TEB */ diff --git a/reactos/ntoskrnl/ps/process.c b/reactos/ntoskrnl/ps/process.c index 4775cfffa82..6bbd29cad54 100644 --- a/reactos/ntoskrnl/ps/process.c +++ b/reactos/ntoskrnl/ps/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.143 2004/09/28 19:49:21 gvg Exp $ +/* $Id: process.c,v 1.144 2004/10/01 20:26:05 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -417,6 +417,7 @@ PsCreatePeb(HANDLE ProcessHandle, PEPROCESS Process, PVOID ImageBase) { + ULONG AllocSize; ULONG PebSize; PPEB Peb; LARGE_INTEGER SectionOffset; @@ -425,12 +426,12 @@ PsCreatePeb(HANDLE ProcessHandle, NTSTATUS Status; /* Allocate the Process Environment Block (PEB) */ - Peb = (PPEB)PEB_BASE; - PebSize = PAGE_SIZE; + Process->TebBlock = (PVOID) MM_ROUND_DOWN(PEB_BASE, MM_VIRTMEM_GRANULARITY); + AllocSize = MM_VIRTMEM_GRANULARITY; Status = NtAllocateVirtualMemory(ProcessHandle, - (PVOID*)&Peb, + &Process->TebBlock, 0, - &PebSize, + &AllocSize, MEM_RESERVE, PAGE_READWRITE); if (!NT_SUCCESS(Status)) @@ -438,6 +439,8 @@ PsCreatePeb(HANDLE ProcessHandle, DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status); return(Status); } + assert((ULONG_PTR) Process->TebBlock <= PEB_BASE && + PEB_BASE + PAGE_SIZE <= (ULONG_PTR) Process->TebBlock + AllocSize); Peb = (PPEB)PEB_BASE; PebSize = PAGE_SIZE; Status = NtAllocateVirtualMemory(ProcessHandle, @@ -452,6 +455,8 @@ PsCreatePeb(HANDLE ProcessHandle, return(Status); } DPRINT("Peb %p PebSize %lu\n", Peb, PebSize); + assert((PPEB) PEB_BASE == Peb && PAGE_SIZE <= PebSize); + Process->TebLastAllocated = (PVOID) Peb; ViewSize = 0; #if defined(__GNUC__) @@ -730,6 +735,7 @@ NtCreateProcess(OUT PHANDLE ProcessHandle, InitializeListHead(&Process->ThreadListHead); KeReleaseSpinLock(&PsProcessListLock, oldIrql); + ExInitializeFastMutex(&Process->TebLock); Process->Pcb.State = PROCESS_STATE_ACTIVE; /*