From 1056771b9100a9bf6bb9abf79c8379753129ace4 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 23 Feb 2009 14:24:59 +0100 Subject: [PATCH] ntdll: Allocate the stack for all threads, don't rely on pthread to do it for us. --- dlls/ntdll/loader.c | 6 +---- dlls/ntdll/ntdll_misc.h | 2 +- dlls/ntdll/thread.c | 55 ++++++++++++----------------------------- dlls/ntdll/virtual.c | 43 ++++++++++++++++---------------- 4 files changed, 39 insertions(+), 67 deletions(-) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index c7fd2674d47..500e4bb85dc 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -2448,7 +2448,6 @@ void WINAPI LdrInitializeThunk( ULONG unknown1, ULONG unknown2, ULONG unknown3, NTSTATUS status; WINE_MODREF *wm; LPCWSTR load_path; - SIZE_T stack_size; PEB *peb = NtCurrentTeb()->Peb; IMAGE_NT_HEADERS *nt = RtlImageNtHeader( peb->ImageBaseAddress ); @@ -2471,10 +2470,7 @@ void WINAPI LdrInitializeThunk( ULONG unknown1, ULONG unknown2, ULONG unknown3, RemoveEntryList( &wm->ldr.InLoadOrderModuleList ); InsertHeadList( &peb->LdrData->InLoadOrderModuleList, &wm->ldr.InLoadOrderModuleList ); - stack_size = max( nt->OptionalHeader.SizeOfStackReserve, nt->OptionalHeader.SizeOfStackCommit ); - if (stack_size < 1024 * 1024) stack_size = 1024 * 1024; /* Xlib needs a large stack */ - - if ((status = virtual_alloc_thread_stack( NULL, stack_size )) != STATUS_SUCCESS) goto error; + if ((status = virtual_alloc_thread_stack( NtCurrentTeb(), 0, 0 )) != STATUS_SUCCESS) goto error; if ((status = server_init_process_done()) != STATUS_SUCCESS) goto error; actctx_init(); diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 55eadd09c00..5dc0e7e6d2a 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -139,7 +139,7 @@ extern unsigned int DIR_get_drives_info( struct drive_info info[MAX_DOS_DRIVES] extern void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info ); extern NTSTATUS virtual_create_system_view( void *base, SIZE_T size, DWORD vprot ); extern SIZE_T virtual_free_system_view( PVOID *addr_ptr ); -extern NTSTATUS virtual_alloc_thread_stack( void *base, SIZE_T stack_size ); +extern NTSTATUS virtual_alloc_thread_stack( TEB *teb, SIZE_T reserve_size, SIZE_T commit_size ); extern void virtual_clear_thread_stack(void); extern BOOL virtual_handle_stack_fault( void *addr ); extern NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err ); diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 40bf507e91d..87b9d577978 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -53,7 +53,7 @@ PUNHANDLED_EXCEPTION_FILTER unhandled_exception_filter = NULL; /* info passed to a starting thread */ struct startup_info { - struct wine_pthread_thread_info pthread_info; + TEB *teb; PRTL_THREAD_START_ROUTINE entry_point; void *entry_arg; }; @@ -233,7 +233,6 @@ HANDLE thread_init(void) HANDLE exe_file = 0; LARGE_INTEGER now; struct ntdll_thread_data *thread_data; - struct wine_pthread_thread_info thread_info; static struct debug_info debug_info; /* debug info for initial thread */ virtual_init(); @@ -278,7 +277,6 @@ HANDLE thread_init(void) while (1U << sigstack_zero_bits < sigstack_total_size) sigstack_zero_bits++; assert( 1U << sigstack_zero_bits == sigstack_total_size ); /* must be a power of 2 */ assert( sigstack_total_size >= sizeof(TEB) + sizeof(struct startup_info) ); - thread_info.teb_size = sigstack_total_size; addr = NULL; size = sigstack_total_size; @@ -286,19 +284,13 @@ HANDLE thread_init(void) &size, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE ); teb = addr; teb->Peb = peb; - thread_info.teb_size = size; init_teb( teb ); thread_data = (struct ntdll_thread_data *)teb->SystemReserved2; thread_data->debug_info = &debug_info; InsertHeadList( &tls_links, &teb->TlsLinks ); - thread_info.stack_base = NULL; - thread_info.stack_size = 0; - thread_info.teb_base = teb; - thread_info.teb_sel = thread_data->fs; wine_pthread_get_functions( &pthread_functions, sizeof(pthread_functions) ); signal_init_thread( teb ); - pthread_functions.init_thread( &thread_info ); virtual_init_threading(); debug_info.str_pos = debug_info.strings; @@ -467,13 +459,12 @@ static void DECLSPEC_NORETURN call_thread_func( PRTL_THREAD_START_ROUTINE rtl_fu * * Startup routine for a newly created thread. */ -static void start_thread( struct wine_pthread_thread_info *info ) +static void start_thread( struct startup_info *info ) { - TEB *teb = info->teb_base; + TEB *teb = info->teb; struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SystemReserved2; - struct startup_info *startup_info = (struct startup_info *)info; - PRTL_THREAD_START_ROUTINE func = startup_info->entry_point; - void *arg = startup_info->entry_arg; + PRTL_THREAD_START_ROUTINE func = info->entry_point; + void *arg = info->entry_arg; struct debug_info debug_info; debug_info.str_pos = debug_info.strings; @@ -483,8 +474,6 @@ static void start_thread( struct wine_pthread_thread_info *info ) signal_init_thread( teb ); server_init_thread( func ); - pthread_functions.init_thread( info ); - virtual_alloc_thread_stack( info->stack_base, info->stack_size ); pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL ); RtlAcquirePebLock(); @@ -531,7 +520,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR * DWORD tid = 0; int request_pipe[2]; NTSTATUS status; - SIZE_T size, page_size = getpagesize(); + SIZE_T size; if (process != NtCurrentProcess()) { @@ -593,7 +582,10 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR * teb = addr; teb->Peb = NtCurrentTeb()->Peb; info = (struct startup_info *)(teb + 1); - info->pthread_info.teb_size = size; + info->teb = teb; + info->entry_point = start; + info->entry_arg = param; + if ((status = init_teb( teb ))) goto error; teb->ClientId.UniqueProcess = ULongToHandle(GetCurrentProcessId()); @@ -603,9 +595,6 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR * thread_regs = (struct ntdll_thread_regs *)teb->SpareBytes1; thread_data->request_fd = request_pipe[1]; - info->pthread_info.teb_base = teb; - info->pthread_info.teb_sel = thread_data->fs; - /* inherit debug registers from parent thread */ thread_regs->dr0 = ntdll_get_thread_regs()->dr0; thread_regs->dr1 = ntdll_get_thread_regs()->dr1; @@ -614,31 +603,19 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR * thread_regs->dr6 = ntdll_get_thread_regs()->dr6; thread_regs->dr7 = ntdll_get_thread_regs()->dr7; - if (!stack_reserve || !stack_commit) - { - IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress ); - if (!stack_reserve) stack_reserve = nt->OptionalHeader.SizeOfStackReserve; - if (!stack_commit) stack_commit = nt->OptionalHeader.SizeOfStackCommit; - } - if (stack_reserve < stack_commit) stack_reserve = stack_commit; - stack_reserve += page_size; /* for the guard page */ - stack_reserve = (stack_reserve + 0xffff) & ~0xffff; /* round to 64K boundary */ - if (stack_reserve < 1024 * 1024) stack_reserve = 1024 * 1024; /* Xlib needs a large stack */ - - info->pthread_info.stack_base = NULL; - info->pthread_info.stack_size = stack_reserve; - info->pthread_info.entry = start_thread; - info->entry_point = start; - info->entry_arg = param; + if ((status = virtual_alloc_thread_stack( teb, stack_reserve, stack_commit ))) goto error; pthread_attr_init( &attr ); - pthread_attr_setstacksize( &attr, stack_reserve ); + pthread_attr_setstack( &attr, teb->DeallocationStack, + (char *)teb->Tib.StackBase - (char *)teb->DeallocationStack ); pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM ); /* force creating a kernel thread */ interlocked_xchg_add( &nb_threads, 1 ); if (pthread_create( &pthread_id, &attr, (void * (*)(void *))start_thread, info )) { interlocked_xchg_add( &nb_threads, -1 ); pthread_attr_destroy( &attr ); + size = 0; + NtFreeVirtualMemory( NtCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE ); status = STATUS_NO_MEMORY; goto error; } @@ -655,7 +632,7 @@ error: if (thread_data) wine_ldt_free_fs( thread_data->fs ); if (addr) { - SIZE_T size = 0; + size = 0; NtFreeVirtualMemory( NtCurrentProcess(), &addr, &size, MEM_RELEASE ); } if (handle) NtClose( handle ); diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index dce8cf09b24..c029e913a12 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -1396,33 +1396,33 @@ SIZE_T virtual_free_system_view( PVOID *addr_ptr ) /*********************************************************************** * virtual_alloc_thread_stack */ -NTSTATUS virtual_alloc_thread_stack( void *base, SIZE_T size ) +NTSTATUS virtual_alloc_thread_stack( TEB *teb, SIZE_T reserve_size, SIZE_T commit_size ) { FILE_VIEW *view; NTSTATUS status; sigset_t sigset; + SIZE_T size; + + if (!reserve_size || !commit_size) + { + IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress ); + if (!reserve_size) reserve_size = nt->OptionalHeader.SizeOfStackReserve; + if (!commit_size) commit_size = nt->OptionalHeader.SizeOfStackCommit; + } + + size = max( reserve_size, commit_size ); + if (size < 1024 * 1024) size = 1024 * 1024; /* Xlib needs a large stack */ + size = (size + 0xffff) & ~0xffff; /* round to 64K boundary */ server_enter_uninterrupted_section( &csVirtual, &sigset ); - if (base) /* already allocated, create a system view */ - { - size = ROUND_SIZE( base, size ); - base = ROUND_ADDR( base, page_mask ); - if ((status = create_view( &view, base, size, - VPROT_READ | VPROT_WRITE | VPROT_COMMITTED | VPROT_VALLOC | VPROT_SYSTEM )) != STATUS_SUCCESS) - goto done; - } - else - { - size = (size + 0xffff) & ~0xffff; /* round to 64K boundary */ - if ((status = map_view( &view, NULL, size, 0xffff, 0, - VPROT_READ | VPROT_WRITE | VPROT_COMMITTED | VPROT_VALLOC )) != STATUS_SUCCESS) - goto done; + if ((status = map_view( &view, NULL, size, 0xffff, 0, + VPROT_READ | VPROT_WRITE | VPROT_COMMITTED | VPROT_VALLOC )) != STATUS_SUCCESS) + goto done; + #ifdef VALGRIND_STACK_REGISTER - /* no need to de-register the stack as it's the one of the main thread */ - VALGRIND_STACK_REGISTER( view->base, (char *)view->base + view->size ); + VALGRIND_STACK_REGISTER( view->base, (char *)view->base + view->size ); #endif - } /* setup no access guard page */ VIRTUAL_SetProt( view, view->base, page_size, VPROT_COMMITTED ); @@ -1430,10 +1430,9 @@ NTSTATUS virtual_alloc_thread_stack( void *base, SIZE_T size ) VPROT_READ | VPROT_WRITE | VPROT_COMMITTED | VPROT_GUARD ); /* note: limit is lower than base since the stack grows down */ - NtCurrentTeb()->DeallocationStack = view->base; - NtCurrentTeb()->Tib.StackBase = (char *)view->base + view->size; - NtCurrentTeb()->Tib.StackLimit = (char *)view->base + 2 * page_size; - + teb->DeallocationStack = view->base; + teb->Tib.StackBase = (char *)view->base + view->size; + teb->Tib.StackLimit = (char *)view->base + 2 * page_size; done: server_leave_uninterrupted_section( &csVirtual, &sigset ); return status;