From ca3ca7b046ae94a152b1367ca982774345887e55 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 5 Jun 2020 14:09:19 +0200 Subject: [PATCH] ntdll: Move the rest of the thread creation code to the Unix library. Signed-off-by: Alexandre Julliard --- dlls/ntdll/thread.c | 94 +++++----------------------------- dlls/ntdll/unix/loader.c | 1 - dlls/ntdll/unix/server.c | 2 +- dlls/ntdll/unix/sync.c | 4 +- dlls/ntdll/unix/thread.c | 91 ++++++++++++++++++++++++++++---- dlls/ntdll/unix/unix_private.h | 11 ++-- dlls/ntdll/unixlib.h | 10 ++-- 7 files changed, 110 insertions(+), 103 deletions(-) diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 8918b39a9c5..91a6a90d267 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -348,90 +348,24 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, SECURITY_DESCRIPTOR *descr, PRTL_THREAD_START_ROUTINE start, void *param, HANDLE *handle_ptr, CLIENT_ID *id ) { - HANDLE handle = 0, actctx = 0; - DWORD tid = 0; - int request_pipe[2]; + ULONG flags = suspended ? THREAD_CREATE_FLAGS_CREATE_SUSPENDED : 0; + HANDLE handle; NTSTATUS status; - data_size_t len = 0; - struct object_attributes *objattr = NULL; + CLIENT_ID client_id; + OBJECT_ATTRIBUTES attr; - if (process != NtCurrentProcess()) + InitializeObjectAttributes( &attr, NULL, 0, NULL, descr ); + + status = unix_funcs->create_thread( &handle, THREAD_ALL_ACCESS, &attr, process, + start, param, call_thread_entry_point, flags, + stack_commit, stack_reserve, &client_id ); + if (!status) { - apc_call_t call; - apc_result_t result; - - memset( &call, 0, sizeof(call) ); - - call.create_thread.type = APC_CREATE_THREAD; - call.create_thread.func = wine_server_client_ptr( start ); - call.create_thread.arg = wine_server_client_ptr( param ); - call.create_thread.reserve = stack_reserve; - call.create_thread.commit = stack_commit; - call.create_thread.suspend = suspended; - status = unix_funcs->server_queue_process_apc( process, &call, &result ); - if (status != STATUS_SUCCESS) return status; - - if (result.create_thread.status == STATUS_SUCCESS) - { - if (id) id->UniqueThread = ULongToHandle(result.create_thread.tid); - if (handle_ptr) *handle_ptr = wine_server_ptr_handle( result.create_thread.handle ); - else NtClose( wine_server_ptr_handle( result.create_thread.handle )); - } - return result.create_thread.status; + if (id) *id = client_id; + if (handle_ptr) *handle_ptr = handle; + else NtClose( handle ); } - - if (descr) - { - OBJECT_ATTRIBUTES thread_attr; - InitializeObjectAttributes( &thread_attr, NULL, 0, NULL, descr ); - if ((status = alloc_object_attributes( &thread_attr, &objattr, &len ))) return status; - } - - if (unix_funcs->server_pipe( request_pipe ) == -1) - { - RtlFreeHeap( GetProcessHeap(), 0, objattr ); - return STATUS_TOO_MANY_OPENED_FILES; - } - wine_server_send_fd( request_pipe[0] ); - - SERVER_START_REQ( new_thread ) - { - req->process = wine_server_obj_handle( process ); - req->access = THREAD_ALL_ACCESS; - req->suspend = suspended; - req->request_fd = request_pipe[0]; - wine_server_add_data( req, objattr, len ); - if (!(status = wine_server_call( req ))) - { - handle = wine_server_ptr_handle( reply->handle ); - tid = reply->tid; - } - close( request_pipe[0] ); - } - SERVER_END_REQ; - - RtlFreeHeap( GetProcessHeap(), 0, objattr ); - if (status) - { - close( request_pipe[1] ); - return status; - } - - RtlGetActiveActivationContext( &actctx ); - - status = unix_funcs->create_thread( stack_reserve, stack_commit, actctx, tid, request_pipe[1], - start, param, call_thread_entry_point ); - if (status) - { - if (actctx) RtlReleaseActivationContext( actctx ); - NtClose( handle ); - close( request_pipe[1] ); - return status; - } - if (id) id->UniqueThread = ULongToHandle(tid); - if (handle_ptr) *handle_ptr = handle; - else NtClose( handle ); - return STATUS_SUCCESS; + return status; } diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 767cae92b48..6ca8be9e6cf 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -1078,7 +1078,6 @@ static struct unix_funcs unix_funcs = server_fd_to_handle, server_handle_to_fd, server_release_fd, - server_pipe, server_init_process_done, __wine_dbg_get_channel_flags, __wine_dbg_strdup, diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index 9cc01ead7f4..4b38a730392 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -1100,7 +1100,7 @@ void CDECL server_release_fd( HANDLE handle, int unix_fd ) * * Create a pipe for communicating with the server. */ -int CDECL server_pipe( int fd[2] ) +int server_pipe( int fd[2] ) { int ret; #ifdef HAVE_PIPE2 diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index c67eb706979..724f8bee38a 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -72,8 +72,8 @@ HANDLE keyed_event = 0; /* create a struct security_descriptor and contained information in one contiguous piece of memory */ -static NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret, - data_size_t *ret_len ) +NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret, + data_size_t *ret_len ) { unsigned int len = sizeof(**ret); PSID owner = NULL, group = NULL; diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index d3e07cae80e..602e0930abe 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -157,19 +157,84 @@ static void start_thread( TEB *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 ) +NTSTATUS CDECL create_thread( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, + HANDLE process, PRTL_THREAD_START_ROUTINE start, void *param, void *relay, + ULONG flags, SIZE_T stack_commit, SIZE_T stack_reserve, + CLIENT_ID *id ) { sigset_t sigset; pthread_t pthread_id; - pthread_attr_t attr; + pthread_attr_t pthread_attr; + data_size_t len; + struct object_attributes *objattr; struct ntdll_thread_data *thread_data; struct startup_info *info; + DWORD tid = 0; + int request_pipe[2]; SIZE_T extra_stack = PTHREAD_STACK_MIN; + HANDLE actctx; TEB *teb; INITIAL_TEB stack; NTSTATUS status; + if (process != NtCurrentProcess()) + { + apc_call_t call; + apc_result_t result; + + memset( &call, 0, sizeof(call) ); + + call.create_thread.type = APC_CREATE_THREAD; + call.create_thread.func = wine_server_client_ptr( start ); + call.create_thread.arg = wine_server_client_ptr( param ); + call.create_thread.reserve = stack_reserve; + call.create_thread.commit = stack_commit; + call.create_thread.suspend = flags & THREAD_CREATE_FLAGS_CREATE_SUSPENDED; + status = server_queue_process_apc( process, &call, &result ); + if (status != STATUS_SUCCESS) return status; + + if (result.create_thread.status == STATUS_SUCCESS) + { + if (id) id->UniqueThread = ULongToHandle( result.create_thread.tid ); + *handle = wine_server_ptr_handle( result.create_thread.handle ); + } + return result.create_thread.status; + } + + if ((status = alloc_object_attributes( attr, &objattr, &len ))) return status; + + if (server_pipe( request_pipe ) == -1) + { + RtlFreeHeap( GetProcessHeap(), 0, objattr ); + return STATUS_TOO_MANY_OPENED_FILES; + } + server_send_fd( request_pipe[0] ); + + SERVER_START_REQ( new_thread ) + { + req->process = wine_server_obj_handle( process ); + req->access = access; + req->suspend = flags & THREAD_CREATE_FLAGS_CREATE_SUSPENDED; + req->request_fd = request_pipe[0]; + wine_server_add_data( req, objattr, len ); + if (!(status = wine_server_call( req ))) + { + *handle = wine_server_ptr_handle( reply->handle ); + tid = reply->tid; + } + close( request_pipe[0] ); + } + SERVER_END_REQ; + + RtlFreeHeap( GetProcessHeap(), 0, objattr ); + if (status) + { + close( request_pipe[1] ); + return status; + } + + RtlGetActiveActivationContext( &actctx ); + pthread_sigmask( SIG_BLOCK, &server_block_set, &sigset ); if ((status = virtual_alloc_teb( &teb ))) goto done; @@ -182,6 +247,7 @@ NTSTATUS CDECL create_thread( SIZE_T stack_reserve, SIZE_T stack_commit, HANDLE teb->ClientId.UniqueProcess = ULongToHandle( GetCurrentProcessId() ); teb->ClientId.UniqueThread = ULongToHandle( tid ); + if (id) *id = teb->ClientId; info = (struct startup_info *)(teb + 1); info->entry = start; @@ -194,27 +260,32 @@ NTSTATUS CDECL create_thread( SIZE_T stack_reserve, SIZE_T stack_commit, HANDLE teb->DeallocationStack = stack.DeallocationStack; thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; - thread_data->request_fd = request_fd; + 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, + pthread_attr_init( &pthread_attr ); + pthread_attr_setstack( &pthread_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 */ + pthread_attr_setguardsize( &pthread_attr, 0 ); + pthread_attr_setscope( &pthread_attr, PTHREAD_SCOPE_SYSTEM ); /* force creating a kernel thread */ InterlockedIncrement( nb_threads ); - if (pthread_create( &pthread_id, &attr, (void * (*)(void *))start_thread, teb )) + if (pthread_create( &pthread_id, &pthread_attr, (void * (*)(void *))start_thread, teb )) { InterlockedDecrement( nb_threads ); virtual_free_teb( teb ); status = STATUS_NO_MEMORY; } - pthread_attr_destroy( &attr ); + pthread_attr_destroy( &pthread_attr ); + done: pthread_sigmask( SIG_SETMASK, &sigset, NULL ); + if (!status) return STATUS_SUCCESS; + NtClose( *handle ); + RtlReleaseActivationContext( actctx ); + close( request_pipe[1] ); return status; } diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 6fdaa17f087..3e848f87661 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -93,14 +93,14 @@ extern NTSTATUS CDECL server_fd_to_handle( int fd, unsigned int access, unsigned extern NTSTATUS CDECL server_handle_to_fd( HANDLE handle, unsigned int access, int *unix_fd, unsigned int *options ) DECLSPEC_HIDDEN; extern void CDECL server_release_fd( HANDLE handle, int unix_fd ) DECLSPEC_HIDDEN; -extern int CDECL server_pipe( int fd[2] ) DECLSPEC_HIDDEN; extern void CDECL server_init_process_done(void) DECLSPEC_HIDDEN; extern TEB * CDECL init_threading( int *nb_threads_ptr, struct ldt_copy **ldt_copy, SIZE_T *size, BOOL *suspend, unsigned int *cpus, BOOL *wow64, timeout_t *start_time ) 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 NTSTATUS CDECL create_thread( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, + HANDLE process, PRTL_THREAD_START_ROUTINE start, void *param, void *relay, + ULONG flags, SIZE_T stack_commit, SIZE_T stack_reserve, + CLIENT_ID *id ) 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; @@ -124,12 +124,15 @@ extern void server_leave_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset extern void start_server( BOOL debug ) DECLSPEC_HIDDEN; extern void server_init_process(void) DECLSPEC_HIDDEN; extern size_t server_init_thread( void *entry_point, BOOL *suspend ) DECLSPEC_HIDDEN; +extern int server_pipe( int fd[2] ) DECLSPEC_HIDDEN; extern NTSTATUS context_to_server( context_t *to, const CONTEXT *from ) DECLSPEC_HIDDEN; extern NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) DECLSPEC_HIDDEN; 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 alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret, + data_size_t *ret_len ) DECLSPEC_HIDDEN; extern void virtual_init(void) DECLSPEC_HIDDEN; extern TEB *virtual_alloc_first_teb(void) DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h index 4e5cec6637e..5ce1ff9b717 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 27 +#define NTDLL_UNIXLIB_VERSION 28 struct unix_funcs { @@ -166,9 +166,10 @@ struct unix_funcs /* thread/process functions */ TEB * (CDECL *init_threading)( int *nb_threads_ptr, struct ldt_copy **ldt_copy, SIZE_T *size, BOOL *suspend, unsigned int *cpus, BOOL *wow64, timeout_t *start_time ); - 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 ); + NTSTATUS (CDECL *create_thread)( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr, + HANDLE process, PRTL_THREAD_START_ROUTINE start, void *param, void *relay, + ULONG flags, SIZE_T stack_commit, SIZE_T stack_reserve, + CLIENT_ID *id ); 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 ); @@ -191,7 +192,6 @@ struct unix_funcs NTSTATUS (CDECL *server_handle_to_fd)( HANDLE handle, unsigned int access, int *unix_fd, unsigned int *options ); void (CDECL *server_release_fd)( HANDLE handle, int unix_fd ); - int (CDECL *server_pipe)( int fd[2] ); void (CDECL *server_init_process_done)(void); /* debugging functions */