ntdll: Move the thread creation code to the Unix library.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
be0eb9c92e
commit
35b063a404
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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 );
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue