From 35b063a404457fdf956d1913738a3c8a66266cb4 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 3 Jun 2020 21:09:13 +0200 Subject: [PATCH] ntdll: Move the thread creation code to the Unix library. Signed-off-by: Alexandre Julliard --- dlls/ntdll/ntdll_misc.h | 8 --- dlls/ntdll/thread.c | 106 +++------------------------------ dlls/ntdll/unix/loader.c | 3 +- dlls/ntdll/unix/thread.c | 94 ++++++++++++++++++++++++++++- dlls/ntdll/unix/unix_private.h | 7 ++- dlls/ntdll/unix/virtual.c | 2 +- dlls/ntdll/unixlib.h | 7 ++- 7 files changed, 110 insertions(+), 117 deletions(-) diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 116e072a4a6..ff791a60764 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -205,14 +205,6 @@ enum loadorder extern enum loadorder get_load_order( const WCHAR *app_name, const UNICODE_STRING *nt_name ) DECLSPEC_HIDDEN; -struct debug_info -{ - unsigned int str_pos; /* current position in strings buffer */ - unsigned int out_pos; /* current position in output buffer */ - char strings[1024]; /* buffer for temporary strings */ - char output[1024]; /* current output line */ -}; - /* thread private data, stored in NtCurrentTeb()->GdiTebBatch */ struct ntdll_thread_data { diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 51777ae6a9a..d7386f2ab14 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -49,22 +49,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(thread); WINE_DECLARE_DEBUG_CHANNEL(relay); -#ifndef PTHREAD_STACK_MIN -#define PTHREAD_STACK_MIN 16384 -#endif - struct _KUSER_SHARED_DATA *user_shared_data = NULL; void (WINAPI *kernel32_start_process)(LPTHREAD_START_ROUTINE,void*) = NULL; -/* info passed to a starting thread */ -struct startup_info -{ - TEB *teb; - PRTL_THREAD_START_ROUTINE entry_point; - void *entry_arg; -}; - static PEB *peb; static PEB_LDR_DATA ldr; static RTL_BITMAP tls_bitmap; @@ -403,24 +391,6 @@ static void WINAPI call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void * #endif /* __i386__ */ -/*********************************************************************** - * start_thread - * - * Startup routine for a newly created thread. - */ -static void start_thread( struct startup_info *info ) -{ - TEB *teb = info->teb; - struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; - struct debug_info debug_info; - - debug_info.str_pos = debug_info.out_pos = 0; - thread_data->debug_info = &debug_info; - thread_data->pthread_id = pthread_self(); - unix_funcs->start_thread( info->entry_point, info->entry_arg, call_thread_entry_point, teb ); -} - - /*********************************************************************** * NtCreateThreadEx (NTDLL.@) */ @@ -447,20 +417,12 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, SECURITY_DESCRIPTOR *descr, PRTL_THREAD_START_ROUTINE start, void *param, HANDLE *handle_ptr, CLIENT_ID *id ) { - sigset_t sigset; - pthread_t pthread_id; - pthread_attr_t attr; - struct ntdll_thread_data *thread_data; - struct startup_info *info; HANDLE handle = 0, actctx = 0; - TEB *teb = NULL; DWORD tid = 0; int request_pipe[2]; NTSTATUS status; - SIZE_T extra_stack = PTHREAD_STACK_MIN; data_size_t len = 0; struct object_attributes *objattr = NULL; - INITIAL_TEB stack; if (process != NtCurrentProcess()) { @@ -524,73 +486,21 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, SECURITY_DESCRIPTOR *descr, return status; } - pthread_sigmask( SIG_BLOCK, &server_block_set, &sigset ); + RtlGetActiveActivationContext( &actctx ); - if ((status = unix_funcs->virtual_alloc_teb( &teb ))) goto error; - - teb->ClientId.UniqueProcess = ULongToHandle(GetCurrentProcessId()); - teb->ClientId.UniqueThread = ULongToHandle(tid); - - /* create default activation context frame for new thread */ - RtlGetActiveActivationContext(&actctx); - if (actctx) + status = unix_funcs->create_thread( stack_reserve, stack_commit, actctx, tid, request_pipe[1], + start, param, call_thread_entry_point ); + if (status) { - RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame; - - frame = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*frame)); - frame->Previous = NULL; - frame->ActivationContext = actctx; - frame->Flags = 0; - teb->ActivationContextStack.ActiveFrame = frame; + if (actctx) RtlReleaseActivationContext( actctx ); + NtClose( handle ); + close( request_pipe[1] ); + return status; } - - info = (struct startup_info *)(teb + 1); - info->teb = teb; - info->entry_point = start; - info->entry_arg = param; - - if ((status = unix_funcs->virtual_alloc_thread_stack( &stack, stack_reserve, stack_commit, &extra_stack ))) - goto error; - - teb->Tib.StackBase = stack.StackBase; - teb->Tib.StackLimit = stack.StackLimit; - teb->DeallocationStack = stack.DeallocationStack; - - thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; - thread_data->request_fd = request_pipe[1]; - thread_data->reply_fd = -1; - thread_data->wait_fd[0] = -1; - thread_data->wait_fd[1] = -1; - thread_data->start_stack = (char *)teb->Tib.StackBase; - - pthread_attr_init( &attr ); - pthread_attr_setstack( &attr, teb->DeallocationStack, - (char *)teb->Tib.StackBase + extra_stack - (char *)teb->DeallocationStack ); - pthread_attr_setguardsize( &attr, 0 ); - pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM ); /* force creating a kernel thread */ - InterlockedIncrement( &nb_threads ); - if (pthread_create( &pthread_id, &attr, (void * (*)(void *))start_thread, info )) - { - InterlockedDecrement( &nb_threads ); - pthread_attr_destroy( &attr ); - status = STATUS_NO_MEMORY; - goto error; - } - pthread_attr_destroy( &attr ); - pthread_sigmask( SIG_SETMASK, &sigset, NULL ); - if (id) id->UniqueThread = ULongToHandle(tid); if (handle_ptr) *handle_ptr = handle; else NtClose( handle ); - return STATUS_SUCCESS; - -error: - if (teb) unix_funcs->virtual_free_teb( teb ); - if (handle) NtClose( handle ); - pthread_sigmask( SIG_SETMASK, &sigset, NULL ); - close( request_pipe[1] ); - return status; } diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 8692dd931c3..30e1fa61b45 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -1017,7 +1017,6 @@ static struct unix_funcs unix_funcs = virtual_get_system_info, virtual_create_builtin_view, virtual_alloc_first_teb, - virtual_alloc_teb, virtual_free_teb, virtual_alloc_thread_stack, virtual_handle_fault, @@ -1035,7 +1034,7 @@ static struct unix_funcs unix_funcs = virtual_release_address_space, virtual_set_large_address_space, init_threading, - start_thread, + create_thread, start_process, abort_thread, exit_thread, diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 7e18caeaebf..eaed27f4b28 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -92,16 +92,104 @@ void CDECL init_threading( int *nb_threads_ptr, struct ldt_copy **ldt_copy ) } +/* info passed to a starting thread */ +struct startup_info +{ + PRTL_THREAD_START_ROUTINE entry; + void *arg; + void *relay; + HANDLE actctx; +}; + /*********************************************************************** * start_thread + * + * Startup routine for a newly created thread. */ -void CDECL start_thread( PRTL_THREAD_START_ROUTINE entry, void *arg, void *relay, TEB *teb ) +static void start_thread( TEB *teb ) { + struct startup_info *info = (struct startup_info *)(teb + 1); + struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; + struct debug_info debug_info; BOOL suspend; + ULONG_PTR cookie; + debug_info.str_pos = debug_info.out_pos = 0; + thread_data->debug_info = &debug_info; + thread_data->pthread_id = pthread_self(); signal_init_thread( teb ); - server_init_thread( entry, &suspend, NULL, NULL, NULL ); - signal_start_thread( entry, arg, suspend, relay, teb ); + server_init_thread( info->entry, &suspend, NULL, NULL, NULL ); + if (info->actctx) + { + RtlActivateActivationContext( 0, info->actctx, &cookie ); + RtlReleaseActivationContext( info->actctx ); + } + signal_start_thread( info->entry, info->arg, suspend, info->relay, teb ); +} + + +/*********************************************************************** + * create_thread + */ +NTSTATUS CDECL create_thread( SIZE_T stack_reserve, SIZE_T stack_commit, HANDLE actctx, DWORD tid, + int request_fd, PRTL_THREAD_START_ROUTINE start, void *param, void *relay ) +{ + sigset_t sigset; + pthread_t pthread_id; + pthread_attr_t attr; + struct ntdll_thread_data *thread_data; + struct startup_info *info; + SIZE_T extra_stack = PTHREAD_STACK_MIN; + TEB *teb; + INITIAL_TEB stack; + NTSTATUS status; + + pthread_sigmask( SIG_BLOCK, &server_block_set, &sigset ); + + if ((status = virtual_alloc_teb( &teb ))) goto done; + + if ((status = virtual_alloc_thread_stack( &stack, stack_reserve, stack_commit, &extra_stack ))) + { + virtual_free_teb( teb ); + goto done; + } + + teb->ClientId.UniqueProcess = ULongToHandle( GetCurrentProcessId() ); + teb->ClientId.UniqueThread = ULongToHandle( tid ); + + info = (struct startup_info *)(teb + 1); + info->entry = start; + info->arg = param; + info->relay = relay; + info->actctx = actctx; + + teb->Tib.StackBase = stack.StackBase; + teb->Tib.StackLimit = stack.StackLimit; + teb->DeallocationStack = stack.DeallocationStack; + + thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; + thread_data->request_fd = request_fd; + thread_data->reply_fd = -1; + thread_data->wait_fd[0] = -1; + thread_data->wait_fd[1] = -1; + thread_data->start_stack = (char *)teb->Tib.StackBase; + + pthread_attr_init( &attr ); + pthread_attr_setstack( &attr, teb->DeallocationStack, + (char *)teb->Tib.StackBase + extra_stack - (char *)teb->DeallocationStack ); + pthread_attr_setguardsize( &attr, 0 ); + pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM ); /* force creating a kernel thread */ + InterlockedIncrement( nb_threads ); + if (pthread_create( &pthread_id, &attr, (void * (*)(void *))start_thread, teb )) + { + InterlockedDecrement( nb_threads ); + virtual_free_teb( teb ); + status = STATUS_NO_MEMORY; + } + pthread_attr_destroy( &attr ); +done: + pthread_sigmask( SIG_SETMASK, &sigset, NULL ); + return status; } diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index dd94cde1cf1..eeadf33f1cb 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -63,7 +63,6 @@ extern NTSTATUS CDECL virtual_map_section( HANDLE handle, PVOID *addr_ptr, unsig extern void CDECL virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info ) DECLSPEC_HIDDEN; extern NTSTATUS CDECL virtual_create_builtin_view( void *module ) DECLSPEC_HIDDEN; extern TEB * CDECL virtual_alloc_first_teb(void) DECLSPEC_HIDDEN; -extern NTSTATUS CDECL virtual_alloc_teb( TEB **ret_teb ) DECLSPEC_HIDDEN; extern void CDECL virtual_free_teb( TEB *teb ) DECLSPEC_HIDDEN; extern NTSTATUS CDECL virtual_alloc_thread_stack( INITIAL_TEB *stack, SIZE_T reserve_size, SIZE_T commit_size, SIZE_T *pthread_size ) DECLSPEC_HIDDEN; extern NTSTATUS CDECL virtual_handle_fault( LPCVOID addr, DWORD err, BOOL on_signal_stack ) DECLSPEC_HIDDEN; @@ -106,7 +105,9 @@ extern void CDECL server_init_process_done(void) DECLSPEC_HIDDEN; extern size_t CDECL server_init_thread( void *entry_point, BOOL *suspend, unsigned int *cpus, BOOL *wow64, timeout_t *start_time ) DECLSPEC_HIDDEN; extern void CDECL init_threading( int *nb_threads, struct ldt_copy **ldt_copy ) DECLSPEC_HIDDEN; -extern void CDECL DECLSPEC_NORETURN start_thread( PRTL_THREAD_START_ROUTINE entry, void *arg, void *relay, TEB *teb ) DECLSPEC_HIDDEN; +extern NTSTATUS CDECL create_thread( SIZE_T stack_reserve, SIZE_T stack_commit, HANDLE actctx, DWORD tid, + int request_fd, PRTL_THREAD_START_ROUTINE start, + void *param, void *relay ) DECLSPEC_HIDDEN; extern void CDECL DECLSPEC_NORETURN start_process( PRTL_THREAD_START_ROUTINE entry, BOOL suspend, void *relay ) DECLSPEC_HIDDEN; extern void CDECL DECLSPEC_NORETURN abort_thread( int status ) DECLSPEC_HIDDEN; extern void CDECL DECLSPEC_NORETURN exit_thread( int status ) DECLSPEC_HIDDEN; @@ -132,6 +133,8 @@ extern void wait_suspend( CONTEXT *context ) DECLSPEC_HIDDEN; extern NTSTATUS set_thread_context( HANDLE handle, const context_t *context, BOOL *self ) DECLSPEC_HIDDEN; extern NTSTATUS get_thread_context( HANDLE handle, context_t *context, unsigned int flags, BOOL *self ) DECLSPEC_HIDDEN; +extern NTSTATUS virtual_alloc_teb( TEB **ret_teb ) DECLSPEC_HIDDEN; + extern void signal_init_threading(void) DECLSPEC_HIDDEN; extern NTSTATUS signal_alloc_thread( TEB *teb ) DECLSPEC_HIDDEN; extern void signal_free_thread( TEB *teb ) DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 9e229c5f4d2..b32a004dae9 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -2572,7 +2572,7 @@ TEB * CDECL virtual_alloc_first_teb(void) /*********************************************************************** * virtual_alloc_teb */ -NTSTATUS CDECL virtual_alloc_teb( TEB **ret_teb ) +NTSTATUS virtual_alloc_teb( TEB **ret_teb ) { sigset_t sigset; TEB *teb = NULL; diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h index 69581c23914..a72cd72dc7e 100644 --- a/dlls/ntdll/unixlib.h +++ b/dlls/ntdll/unixlib.h @@ -28,7 +28,7 @@ struct ldt_copy; struct msghdr; /* increment this when you change the function table */ -#define NTDLL_UNIXLIB_VERSION 17 +#define NTDLL_UNIXLIB_VERSION 18 struct unix_funcs { @@ -92,7 +92,6 @@ struct unix_funcs void (CDECL *virtual_get_system_info)( SYSTEM_BASIC_INFORMATION *info ); NTSTATUS (CDECL *virtual_create_builtin_view)( void *module ); TEB * (CDECL *virtual_alloc_first_teb)(void); - NTSTATUS (CDECL *virtual_alloc_teb)( TEB **ret_teb ); void (CDECL *virtual_free_teb)( TEB *teb ); NTSTATUS (CDECL *virtual_alloc_thread_stack)( INITIAL_TEB *stack, SIZE_T reserve_size, SIZE_T commit_size, SIZE_T *pthread_size ); NTSTATUS (CDECL *virtual_handle_fault)( LPCVOID addr, DWORD err, BOOL on_signal_stack ); @@ -112,7 +111,9 @@ struct unix_funcs /* thread/process functions */ void (CDECL *init_threading)( int *nb_threads, struct ldt_copy **ldt_copy ); - void (CDECL *start_thread)( PRTL_THREAD_START_ROUTINE entry, void *arg, void *relay, TEB *teb ); + NTSTATUS (CDECL *create_thread)( SIZE_T stack_reserve, SIZE_T stack_commit, HANDLE actctx, + DWORD tid, int request_fd, PRTL_THREAD_START_ROUTINE start, + void *param, void *relay ); void (CDECL *start_process)( PRTL_THREAD_START_ROUTINE entry, BOOL suspend, void *relay ); void (CDECL *abort_thread)( int status ); void (CDECL *exit_thread)( int status );