From dee934c0ff54851f049ab27b11d84c5a5810662c Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 30 Apr 2020 10:05:56 +0200 Subject: [PATCH] ntdll: Allocate TEBs out of a larger memory block. Signed-off-by: Alexandre Julliard --- dlls/ntdll/ntdll_misc.h | 2 +- dlls/ntdll/thread.c | 19 ++------ dlls/ntdll/virtual.c | 103 ++++++++++++++++++++++++++++++++-------- 3 files changed, 86 insertions(+), 38 deletions(-) diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 3e877593b64..a22b77b4819 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -93,7 +93,6 @@ extern void debug_init(void) DECLSPEC_HIDDEN; extern TEB *thread_init(void) DECLSPEC_HIDDEN; extern void actctx_init(void) DECLSPEC_HIDDEN; extern void virtual_init(void) DECLSPEC_HIDDEN; -extern void virtual_init_threading(void) DECLSPEC_HIDDEN; extern void fill_cpu_info(void) DECLSPEC_HIDDEN; extern void heap_set_debug_flags( HANDLE handle ) DECLSPEC_HIDDEN; extern void init_unix_codepage(void) DECLSPEC_HIDDEN; @@ -200,6 +199,7 @@ extern NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, unsigned sh ULONG protect, pe_image_info_t *image_info ) DECLSPEC_HIDDEN; extern void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info ) DECLSPEC_HIDDEN; extern NTSTATUS virtual_create_builtin_view( void *base ) DECLSPEC_HIDDEN; +extern TEB * virtual_alloc_first_teb(void) DECLSPEC_HIDDEN; extern NTSTATUS virtual_alloc_teb( TEB **teb ) DECLSPEC_HIDDEN; extern void virtual_free_teb( TEB *teb ) DECLSPEC_HIDDEN; extern NTSTATUS virtual_alloc_thread_stack( INITIAL_TEB *stack, SIZE_T reserve_size, diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 604fd20c846..d116c7bd571 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -246,13 +246,10 @@ TEB *thread_init(void) user_shared_data = addr; memcpy( user_shared_data->NtSystemRoot, default_windirW, sizeof(default_windirW) ); - /* allocate and initialize the PEB */ - - addr = NULL; - size = sizeof(*peb); - virtual_alloc_aligned( &addr, 0, &size, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE, 1 ); - peb = addr; + /* allocate and initialize the PEB and initial TEB */ + teb = virtual_alloc_first_teb(); + peb = teb->Peb; peb->FastPebLock = &peb_lock; peb->TlsBitmap = &tls_bitmap; peb->TlsExpansionBitmap = &tls_expansion_bitmap; @@ -282,21 +279,12 @@ TEB *thread_init(void) */ peb->SessionId = 1; - /* allocate and initialize the initial TEB */ - - signal_init_threading(); - virtual_alloc_teb( &teb ); - teb->Peb = peb; - teb->Tib.StackBase = (void *)~0UL; - thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; thread_data->request_fd = -1; thread_data->reply_fd = -1; thread_data->wait_fd[0] = -1; thread_data->wait_fd[1] = -1; - signal_init_thread( teb ); - virtual_init_threading(); debug_init(); init_paths(); set_process_name( __wine_main_argc, __wine_main_argv ); @@ -517,7 +505,6 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, SECURITY_DESCRIPTOR *descr, if ((status = virtual_alloc_teb( &teb ))) goto error; - teb->Peb = NtCurrentTeb()->Peb; teb->ClientId.UniqueProcess = ULongToHandle(GetCurrentProcessId()); teb->ClientId.UniqueThread = ULongToHandle(tid); diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index 7be00a1ac2e..5900616e0ca 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -164,6 +164,11 @@ SIZE_T signal_stack_size = 0; SIZE_T signal_stack_mask = 0; static SIZE_T signal_stack_align; +/* TEB allocation blocks */ +static TEB *teb_block; +static TEB *next_free_teb; +static int teb_block_pos; + #define ROUND_ADDR(addr,mask) \ ((void *)((UINT_PTR)(addr) & ~(UINT_PTR)(mask))) @@ -2011,15 +2016,6 @@ void virtual_init(void) } -/*********************************************************************** - * virtual_init_threading - */ -void virtual_init_threading(void) -{ - use_locks = TRUE; -} - - /*********************************************************************** * virtual_get_system_info */ @@ -2093,29 +2089,90 @@ NTSTATUS virtual_create_builtin_view( void *module ) } +/*********************************************************************** + * virtual_alloc_first_teb + */ +TEB *virtual_alloc_first_teb(void) +{ + TEB *teb; + PEB *peb; + SIZE_T peb_size = page_size; + SIZE_T teb_size = signal_stack_mask + 1; + SIZE_T total = 32 * teb_size; + + NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&teb_block, 0, &total, + MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE ); + teb_block_pos = 30; + teb = (TEB *)((char *)teb_block + 30 * teb_size); + peb = (PEB *)((char *)teb_block + 32 * teb_size - peb_size); + NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&teb, 0, &teb_size, MEM_COMMIT, PAGE_READWRITE ); + NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&peb, 0, &peb_size, MEM_COMMIT, PAGE_READWRITE ); + + teb->Peb = peb; + teb->Tib.Self = &teb->Tib; + teb->Tib.ExceptionList = (void *)~0ul; + teb->Tib.StackBase = (void *)~0ul; + teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer; + teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer); + signal_init_threading(); + signal_alloc_thread( teb ); + signal_init_thread( teb ); + use_locks = TRUE; + return teb; +} + + /*********************************************************************** * virtual_alloc_teb */ NTSTATUS virtual_alloc_teb( TEB **ret_teb ) { - SIZE_T size = signal_stack_mask + 1; - void *addr = NULL; - TEB *teb; - NTSTATUS status; + sigset_t sigset; + TEB *teb = NULL; + NTSTATUS status = STATUS_SUCCESS; + SIZE_T teb_size = signal_stack_mask + 1; - if ((status = virtual_alloc_aligned( &addr, 0, &size, MEM_COMMIT | MEM_TOP_DOWN, - PAGE_READWRITE, signal_stack_align ))) - return status; + server_enter_uninterrupted_section( &csVirtual, &sigset ); + if (next_free_teb) + { + teb = next_free_teb; + next_free_teb = *(TEB **)teb; + memset( teb, 0, sizeof(*teb) ); + } + else + { + if (!teb_block_pos) + { + void *addr = NULL; + SIZE_T total = 32 * teb_size; - *ret_teb = teb = addr; + if ((status = NtAllocateVirtualMemory( NtCurrentProcess(), &addr, 0, &total, + MEM_RESERVE, PAGE_READWRITE ))) + { + server_leave_uninterrupted_section( &csVirtual, &sigset ); + return status; + } + teb_block = addr; + teb_block_pos = 32; + } + teb = (TEB *)((char *)teb_block + --teb_block_pos * teb_size); + NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&teb, 0, &teb_size, + MEM_COMMIT, PAGE_READWRITE ); + } + server_leave_uninterrupted_section( &csVirtual, &sigset ); + + *ret_teb = teb; + teb->Peb = NtCurrentTeb()->Peb; teb->Tib.Self = &teb->Tib; teb->Tib.ExceptionList = (void *)~0UL; teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer; teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer); if ((status = signal_alloc_thread( teb ))) { - size = 0; - NtFreeVirtualMemory( NtCurrentProcess(), &addr, &size, MEM_RELEASE ); + server_enter_uninterrupted_section( &csVirtual, &sigset ); + *(TEB **)teb = next_free_teb; + next_free_teb = teb; + server_leave_uninterrupted_section( &csVirtual, &sigset ); } return status; } @@ -2128,6 +2185,7 @@ void virtual_free_teb( TEB *teb ) { struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; SIZE_T size; + sigset_t sigset; signal_free_thread( teb ); if (teb->DeallocationStack) @@ -2140,8 +2198,11 @@ void virtual_free_teb( TEB *teb ) size = 0; NtFreeVirtualMemory( GetCurrentProcess(), &thread_data->start_stack, &size, MEM_RELEASE ); } - size = 0; - NtFreeVirtualMemory( NtCurrentProcess(), (void **)&teb, &size, MEM_RELEASE ); + + server_enter_uninterrupted_section( &csVirtual, &sigset ); + *(TEB **)teb = next_free_teb; + next_free_teb = teb; + server_leave_uninterrupted_section( &csVirtual, &sigset ); }