ntdll: Move the rest of the thread creation code to the Unix library.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Alexandre Julliard 2020-06-05 14:09:19 +02:00
parent f4efea2233
commit ca3ca7b046
7 changed files with 110 additions and 103 deletions

View File

@ -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;
}

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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 */