ntdll: Move the rest of the thread creation code to the Unix library.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
f4efea2233
commit
ca3ca7b046
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue