Don't use more than a single page for a TEB

svn path=/trunk/; revision=11143
This commit is contained in:
Gé van Geldorp 2004-10-01 20:26:05 +00:00
parent f6fb22a9ef
commit 228cddee4a
6 changed files with 123 additions and 53 deletions

View file

@ -359,6 +359,10 @@ MEMORY_AREA* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace,
PVOID MmFindGap(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG Granularity, BOOL TopDown); PVOID MmFindGap(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG Granularity, BOOL TopDown);
void MmReleaseMemoryAreaIfDecommitted(PEPROCESS Process,
PMADDRESS_SPACE AddressSpace,
PVOID BaseAddress);
/* npool.c *******************************************************************/ /* npool.c *******************************************************************/
VOID MiDebugDumpNonPagedPool(BOOLEAN NewOnly); VOID MiDebugDumpNonPagedPool(BOOLEAN NewOnly);

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 * FILE: ntoskrnl/ke/kthread.c
* PURPOSE: Process manager definitions * PURPOSE: Process manager definitions
@ -428,6 +428,10 @@ struct _EPROCESS
struct _EJOB* Job; struct _EJOB* Job;
UINT JobStatus; UINT JobStatus;
FAST_MUTEX TebLock;
PVOID TebBlock;
PVOID TebLastAllocated;
}; };
#define PROCESS_STATE_TERMINATED (1) #define PROCESS_STATE_TERMINATED (1)

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 * PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/anonmem.c * FILE: ntoskrnl/mm/anonmem.c
@ -752,7 +752,7 @@ MmFreeVirtualMemory(PEPROCESS Process,
} }
/* /*
* @unimplemented * @implemented
*/ */
NTSTATUS STDCALL NTSTATUS STDCALL
NtFreeVirtualMemory(IN HANDLE ProcessHandle, NtFreeVirtualMemory(IN HANDLE ProcessHandle,

View file

@ -201,9 +201,6 @@ static VOID MmInsertMemoryArea(PMADDRESS_SPACE AddressSpace,
InsertTailList(ListHead,inserted_entry); 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) static PVOID MmFindGapBottomUp(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG Granularity)
{ {
PLIST_ENTRY ListHead; PLIST_ENTRY ListHead;
@ -230,7 +227,7 @@ static PVOID MmFindGapBottomUp(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG
#ifdef DBG #ifdef DBG
Address = (PVOID) ((char *) Address + PAGE_SIZE); /* For a guard page preceding the area */ Address = (PVOID) ((char *) Address + PAGE_SIZE); /* For a guard page preceding the area */
#endif #endif
Address = (PVOID) ROUND_UP_POW2(Address, Granularity); Address = (PVOID) MM_ROUND_UP(Address, Granularity);
if (Address < next->BaseAddress) if (Address < next->BaseAddress)
{ {
Gap = (char*)next->BaseAddress - ((char*)current->BaseAddress + PAGE_ROUND_UP(current->Length)); 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) if (current_entry == ListHead)
{ {
Address = (PVOID) ROUND_UP_POW2(AddressSpace->LowestAddress, Granularity); Address = (PVOID) MM_ROUND_UP(AddressSpace->LowestAddress, Granularity);
} }
else else
{ {
@ -253,7 +250,7 @@ static PVOID MmFindGapBottomUp(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG
#ifdef DBG #ifdef DBG
Address = (PVOID) ((char *) Address + PAGE_SIZE); /* For a guard page preceding the area */ Address = (PVOID) ((char *) Address + PAGE_SIZE); /* For a guard page preceding the area */
#endif #endif
Address = (PVOID) ROUND_UP_POW2(Address, Granularity); Address = (PVOID) MM_ROUND_UP(Address, Granularity);
} }
/* Check if enough space for the block */ /* Check if enough space for the block */
if (AddressSpace->LowestAddress < KERNEL_BASE) if (AddressSpace->LowestAddress < KERNEL_BASE)
@ -313,7 +310,7 @@ static PVOID MmFindGapTopDown(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG
#ifdef DBG #ifdef DBG
BottomAddress = (PVOID) ((char *) BottomAddress + PAGE_SIZE); /* For a guard page preceding the area */ BottomAddress = (PVOID) ((char *) BottomAddress + PAGE_SIZE); /* For a guard page preceding the area */
#endif #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)); DPRINT("Base %p Length %lx\n", current->BaseAddress, PAGE_ROUND_UP(current->Length));
if (BottomAddress < TopAddress && BottomAddress < HighestAddress) if (BottomAddress < TopAddress && BottomAddress < HighestAddress)
@ -323,7 +320,7 @@ static PVOID MmFindGapTopDown(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG
if (Gap >= Length) if (Gap >= Length)
{ {
DPRINT("Found gap at %p\n", (char*) TopAddress - 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; TopAddress = (char*)current->BaseAddress - 1;
@ -332,11 +329,11 @@ static PVOID MmFindGapTopDown(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG
if (current_entry == ListHead) 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 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 */ /* Check if enough space for the block */
@ -596,8 +593,9 @@ NTSTATUS MmCreateMemoryArea(PEPROCESS Process,
} }
else else
{ {
tmpLength = Length + ((ULONG_PTR) *BaseAddress - ROUND_DOWN_POW2(*BaseAddress, Granularity)); tmpLength = Length + ((ULONG_PTR) *BaseAddress
(*BaseAddress) = (PVOID) ROUND_DOWN_POW2(*BaseAddress, Granularity); - (ULONG_PTR) MM_ROUND_DOWN(*BaseAddress, Granularity));
*BaseAddress = MM_ROUND_DOWN(*BaseAddress, Granularity);
if (AddressSpace->LowestAddress == KERNEL_BASE && if (AddressSpace->LowestAddress == KERNEL_BASE &&
(*BaseAddress) < (PVOID)KERNEL_BASE) (*BaseAddress) < (PVOID)KERNEL_BASE)
@ -643,3 +641,36 @@ NTSTATUS MmCreateMemoryArea(PEPROCESS Process,
DPRINT("MmCreateMemoryArea() succeeded\n"); DPRINT("MmCreateMemoryArea() succeeded\n");
return STATUS_SUCCESS; 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 */

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -504,51 +504,76 @@ PsCreateTeb(HANDLE ProcessHandle,
PETHREAD Thread, PETHREAD Thread,
PUSER_STACK UserStack) PUSER_STACK UserStack)
{ {
MEMORY_BASIC_INFORMATION Info; PEPROCESS Process;
NTSTATUS Status; NTSTATUS Status;
ULONG ByteCount; ULONG ByteCount;
ULONG RegionSize; ULONG RegionSize;
ULONG TebSize; ULONG TebSize;
PVOID TebBase; PVOID TebBase;
TEB Teb; TEB Teb;
ULONG ResultLength;
TebBase = (PVOID)0x7FFDE000;
TebSize = PAGE_SIZE; TebSize = PAGE_SIZE;
while (TRUE) if (NULL == Thread->ThreadsProcess)
{ {
Status = ZwQueryVirtualMemory(ProcessHandle, /* We'll be allocating a 64k block here and only use 4k of it, but this
TebBase, path should almost never be taken. Actually, I never saw it was taken,
MemoryBasicInformation, so maybe we should just assert(NULL != Thread->ThreadsProcess) and
&Info, move on */
sizeof(Info), TebBase = NULL;
&ResultLength); Status = ZwAllocateVirtualMemory(ProcessHandle,
if (!NT_SUCCESS(Status)) &TebBase,
{ 0,
CPRINT("ZwQueryVirtualMemory (Status %x)\n", Status); &TebSize,
KEBUGCHECK(0); MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN,
} PAGE_READWRITE);
/* FIXME: Race between this and the above check */ if (! NT_SUCCESS(Status))
if (Info.State == MEM_FREE) {
{ DPRINT1("Failed to allocate virtual memory for TEB\n");
/* The TEB must reside in user space */ return Status;
Status = ZwAllocateVirtualMemory(ProcessHandle, }
&TebBase, }
0, else
&TebSize, {
MEM_RESERVE | MEM_COMMIT, Process = Thread->ThreadsProcess;
PAGE_READWRITE); ExAcquireFastMutex(&Process->TebLock);
if (NT_SUCCESS(Status)) if (NULL == Process->TebBlock ||
{ Process->TebBlock == Process->TebLastAllocated)
break; {
} Process->TebBlock = NULL;
} RegionSize = MM_VIRTMEM_GRANULARITY;
Status = ZwAllocateVirtualMemory(ProcessHandle,
TebBase = (char*)TebBase - TebSize; &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); DPRINT ("TebBase %p TebSize %lu\n", TebBase, TebSize);
assert(NULL != TebBase && PAGE_SIZE <= TebSize);
RtlZeroMemory(&Teb, sizeof(TEB)); RtlZeroMemory(&Teb, sizeof(TEB));
/* set all pointers to and from the TEB */ /* set all pointers to and from the TEB */

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -417,6 +417,7 @@ PsCreatePeb(HANDLE ProcessHandle,
PEPROCESS Process, PEPROCESS Process,
PVOID ImageBase) PVOID ImageBase)
{ {
ULONG AllocSize;
ULONG PebSize; ULONG PebSize;
PPEB Peb; PPEB Peb;
LARGE_INTEGER SectionOffset; LARGE_INTEGER SectionOffset;
@ -425,12 +426,12 @@ PsCreatePeb(HANDLE ProcessHandle,
NTSTATUS Status; NTSTATUS Status;
/* Allocate the Process Environment Block (PEB) */ /* Allocate the Process Environment Block (PEB) */
Peb = (PPEB)PEB_BASE; Process->TebBlock = (PVOID) MM_ROUND_DOWN(PEB_BASE, MM_VIRTMEM_GRANULARITY);
PebSize = PAGE_SIZE; AllocSize = MM_VIRTMEM_GRANULARITY;
Status = NtAllocateVirtualMemory(ProcessHandle, Status = NtAllocateVirtualMemory(ProcessHandle,
(PVOID*)&Peb, &Process->TebBlock,
0, 0,
&PebSize, &AllocSize,
MEM_RESERVE, MEM_RESERVE,
PAGE_READWRITE); PAGE_READWRITE);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -438,6 +439,8 @@ PsCreatePeb(HANDLE ProcessHandle,
DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status); DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
return(Status); return(Status);
} }
assert((ULONG_PTR) Process->TebBlock <= PEB_BASE &&
PEB_BASE + PAGE_SIZE <= (ULONG_PTR) Process->TebBlock + AllocSize);
Peb = (PPEB)PEB_BASE; Peb = (PPEB)PEB_BASE;
PebSize = PAGE_SIZE; PebSize = PAGE_SIZE;
Status = NtAllocateVirtualMemory(ProcessHandle, Status = NtAllocateVirtualMemory(ProcessHandle,
@ -452,6 +455,8 @@ PsCreatePeb(HANDLE ProcessHandle,
return(Status); return(Status);
} }
DPRINT("Peb %p PebSize %lu\n", Peb, PebSize); DPRINT("Peb %p PebSize %lu\n", Peb, PebSize);
assert((PPEB) PEB_BASE == Peb && PAGE_SIZE <= PebSize);
Process->TebLastAllocated = (PVOID) Peb;
ViewSize = 0; ViewSize = 0;
#if defined(__GNUC__) #if defined(__GNUC__)
@ -730,6 +735,7 @@ NtCreateProcess(OUT PHANDLE ProcessHandle,
InitializeListHead(&Process->ThreadListHead); InitializeListHead(&Process->ThreadListHead);
KeReleaseSpinLock(&PsProcessListLock, oldIrql); KeReleaseSpinLock(&PsProcessListLock, oldIrql);
ExInitializeFastMutex(&Process->TebLock);
Process->Pcb.State = PROCESS_STATE_ACTIVE; Process->Pcb.State = PROCESS_STATE_ACTIVE;
/* /*