Commit 35b063a4 authored by Alexandre Julliard's avatar Alexandre Julliard

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

parent be0eb9c9
......@@ -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;
......@@ -404,24 +392,6 @@ static void WINAPI call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *
/***********************************************************************
* 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.@)
*/
NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle_ptr, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr,
......@@ -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);
RtlGetActiveActivationContext( &actctx );
/* create default activation context frame for new thread */
RtlGetActiveActivationContext(&actctx);
if (actctx)
{
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;
}
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 ))
status = unix_funcs->create_thread( stack_reserve, stack_commit, actctx, tid, request_pipe[1],
start, param, call_thread_entry_point );
if (status)
{
InterlockedDecrement( &nb_threads );
pthread_attr_destroy( &attr );
status = STATUS_NO_MEMORY;
goto error;
if (actctx) RtlReleaseActivationContext( actctx );
NtClose( handle );
close( request_pipe[1] );
return status;
}
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 );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment