From: Ludovic Henry Date: Thu, 1 Sep 2016 19:22:51 +0000 (+0200) Subject: [mono-threads] Factor common platform create thread code (#3484) X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;ds=sidebyside;h=012e17697981de381089fd4e051c0a56d04f4076;p=mono.git [mono-threads] Factor common platform create thread code (#3484) --- diff --git a/mono/utils/mono-threads-posix.c b/mono/utils/mono-threads-posix.c index 4d1afeba132..1a6b06fe045 100644 --- a/mono/utils/mono-threads-posix.c +++ b/mono/utils/mono-threads-posix.c @@ -107,71 +107,18 @@ mono_threads_platform_register (MonoThreadInfo *info) info->handle = thread_handle_create (); } -typedef struct { - void *(*start_routine)(void*); - void *arg; - int flags; - gint32 priority; - MonoCoopSem registered; - HANDLE handle; -} StartInfo; - -static void* -inner_start_thread (void *arg) -{ - StartInfo *start_info = (StartInfo *) arg; - void *t_arg = start_info->arg; - int res; - void *(*start_func)(void*) = start_info->start_routine; - guint32 flags = start_info->flags; - void *result; - MonoThreadInfo *info; - - info = mono_thread_info_attach (&result); - info->runtime_thread = TRUE; - - start_info->handle = info->handle; - - mono_threads_platform_set_priority (info, start_info->priority); - - if (flags & CREATE_SUSPENDED) { - info->create_suspended = TRUE; - mono_coop_sem_init (&info->create_suspended_sem, 0); - } - - /* start_info is not valid after this */ - mono_coop_sem_post (&(start_info->registered)); - start_info = NULL; - - if (flags & CREATE_SUSPENDED) { - res = mono_coop_sem_wait (&info->create_suspended_sem, MONO_SEM_FLAGS_NONE); - g_assert (res != -1); - - mono_coop_sem_destroy (&info->create_suspended_sem); - } - - /* Run the actual main function of the thread */ - result = start_func (t_arg); - - mono_threads_platform_exit (GPOINTER_TO_UINT (result)); - g_assert_not_reached (); -} - -HANDLE -mono_threads_platform_create_thread (MonoThreadStart start_routine, gpointer arg, MonoThreadParm *tp, MonoNativeThreadId *out_tid) +int +mono_threads_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize stack_size, MonoNativeThreadId *out_tid) { pthread_attr_t attr; - int res; pthread_t thread; - StartInfo start_info; - guint32 stack_size; - int policy; - struct sched_param sp; + gint res; res = pthread_attr_init (&attr); g_assert (!res); - if (tp->stack_size == 0) { +#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE + if (stack_size == 0) { #if HAVE_VALGRIND_MEMCHECK_H if (RUNNING_ON_VALGRIND) stack_size = 1 << 20; @@ -180,52 +127,26 @@ mono_threads_platform_create_thread (MonoThreadStart start_routine, gpointer arg #else stack_size = (SIZEOF_VOID_P / 4) * 1024 * 1024; #endif - } else - stack_size = tp->stack_size; + } #ifdef PTHREAD_STACK_MIN if (stack_size < PTHREAD_STACK_MIN) stack_size = PTHREAD_STACK_MIN; #endif -#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE res = pthread_attr_setstacksize (&attr, stack_size); g_assert (!res); -#endif - - /* - * For policies that respect priorities set the prirority for the new thread - */ - pthread_getschedparam(pthread_self(), &policy, &sp); - if ((policy == SCHED_FIFO) || (policy == SCHED_RR)) { - sp.sched_priority = win32_priority_to_posix_priority (tp->priority, policy); - res = pthread_attr_setschedparam (&attr, &sp); - } - - memset (&start_info, 0, sizeof (StartInfo)); - start_info.start_routine = (void *(*)(void *)) start_routine; - start_info.arg = arg; - start_info.flags = tp->creation_flags; - start_info.priority = tp->priority; - mono_coop_sem_init (&(start_info.registered), 0); +#endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */ /* Actually start the thread */ - res = mono_gc_pthread_create (&thread, &attr, inner_start_thread, &start_info); - if (res) { - mono_coop_sem_destroy (&(start_info.registered)); - return NULL; - } - - /* Wait until the thread register itself in various places */ - res = mono_coop_sem_wait (&start_info.registered, MONO_SEM_FLAGS_NONE); - g_assert (res != -1); - - mono_coop_sem_destroy (&(start_info.registered)); + res = mono_gc_pthread_create (&thread, &attr, (gpointer (*)(gpointer)) thread_fn, thread_data); + if (res) + return -1; if (out_tid) *out_tid = thread; - return start_info.handle; + return 0; } gboolean diff --git a/mono/utils/mono-threads-windows.c b/mono/utils/mono-threads-windows.c index ca6159b07f5..bb8d300a58b 100644 --- a/mono/utils/mono-threads-windows.c +++ b/mono/utils/mono-threads-windows.c @@ -148,84 +148,24 @@ mono_threads_platform_register (MonoThreadInfo *info) info->handle = thread_handle; } -typedef struct { - LPTHREAD_START_ROUTINE start_routine; - void *arg; - gint32 priority; - MonoCoopSem registered; - gboolean suspend; - HANDLE handle; -} ThreadStartInfo; - -static DWORD WINAPI -inner_start_thread (LPVOID arg) +int +mono_threads_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize stack_size, MonoNativeThreadId *out_tid) { - ThreadStartInfo *start_info = arg; - void *t_arg = start_info->arg; - LPTHREAD_START_ROUTINE start_func = start_info->start_routine; - DWORD result; - gboolean suspend = start_info->suspend; - MonoThreadInfo *info; - int res; - - info = mono_thread_info_attach (&result); - info->runtime_thread = TRUE; - - start_info->handle = info->handle; - - mono_threads_platform_set_priority(info, start_info->priority); - - if (suspend) { - info->create_suspended = TRUE; - mono_coop_sem_init (&info->create_suspended_sem, 0); - } - - mono_coop_sem_post (&(start_info->registered)); - - if (suspend) { - res = mono_coop_sem_wait (&info->create_suspended_sem, MONO_SEM_FLAGS_NONE); - g_assert (res != -1); - - mono_coop_sem_destroy (&info->create_suspended_sem); - } - - result = start_func (t_arg); + HANDLE result; + DWORD thread_id; - mono_thread_info_detach (); + result = CreateThread (NULL, stack_size, (LPTHREAD_START_ROUTINE) thread_fn, thread_data, 0, &thread_id); + if (!result) + return -1; - return result; -} + /* A new handle is open when attaching + * the thread, so we don't need this one */ + CloseHandle (result); -HANDLE -mono_threads_platform_create_thread (MonoThreadStart start_routine, gpointer arg, MonoThreadParm *tp, MonoNativeThreadId *out_tid) -{ - ThreadStartInfo start_info; - HANDLE result; - DWORD thread_id; - guint32 creation_flags = tp->creation_flags; - int res; - - memset (&start_info, 0, sizeof (start_info)); - mono_coop_sem_init (&(start_info.registered), 0); - start_info.arg = arg; - start_info.start_routine = start_routine; - start_info.suspend = creation_flags & CREATE_SUSPENDED; - start_info.priority = tp->priority; - creation_flags &= ~CREATE_SUSPENDED; - - result = CreateThread (NULL, tp->stack_size, inner_start_thread, &start_info, creation_flags, &thread_id); - if (result) { - res = mono_coop_sem_wait (&(start_info.registered), MONO_SEM_FLAGS_NONE); - g_assert (res != -1); - - /* A new handle has been opened when attaching - * the thread, so we don't need this one */ - CloseHandle (result); - } if (out_tid) *out_tid = thread_id; - mono_coop_sem_destroy (&(start_info.registered)); - return start_info.handle; + + return 0; } diff --git a/mono/utils/mono-threads.c b/mono/utils/mono-threads.c index 53a14e38440..0611e739d37 100644 --- a/mono/utils/mono-threads.c +++ b/mono/utils/mono-threads.c @@ -1138,6 +1138,75 @@ mono_thread_info_is_async_context (void) return FALSE; } +typedef struct { + gint32 ref; + MonoThreadStart start_routine; + gpointer start_routine_arg; + gboolean create_suspended; + gint32 priority; + MonoCoopSem registered; + MonoThreadInfo *info; +} CreateThreadData; + +static gsize WINAPI +inner_start_thread (gpointer data) +{ + CreateThreadData *thread_data; + MonoThreadInfo *info; + MonoThreadStart start_routine; + gpointer start_routine_arg; + guint32 start_routine_res; + gboolean create_suspended; + gint32 priority; + gsize dummy; + gint res; + + thread_data = (CreateThreadData*) data; + g_assert (thread_data); + + start_routine = thread_data->start_routine; + start_routine_arg = thread_data->start_routine_arg; + + create_suspended = thread_data->create_suspended; + priority = thread_data->priority; + + info = mono_thread_info_attach (&dummy); + info->runtime_thread = TRUE; + + mono_threads_platform_set_priority (info, priority); + + if (create_suspended) { + info->create_suspended = TRUE; + mono_coop_sem_init (&info->create_suspended_sem, 0); + } + + thread_data->info = info; + + mono_coop_sem_post (&thread_data->registered); + + if (InterlockedDecrement (&thread_data->ref) == 0) { + mono_coop_sem_destroy (&thread_data->registered); + g_free (thread_data); + } + + /* thread_data is not valid anymore */ + thread_data = NULL; + + if (create_suspended) { + res = mono_coop_sem_wait (&info->create_suspended_sem, MONO_SEM_FLAGS_NONE); + g_assert (res == 0); + + mono_coop_sem_destroy (&info->create_suspended_sem); + } + + /* Run the actual main function of the thread */ + start_routine_res = start_routine (start_routine_arg); + + mono_threads_platform_exit (start_routine_res); + + g_assert_not_reached (); +} + /* * mono_threads_create_thread: * @@ -1147,7 +1216,43 @@ mono_thread_info_is_async_context (void) HANDLE mono_threads_create_thread (MonoThreadStart start, gpointer arg, MonoThreadParm *tp, MonoNativeThreadId *out_tid) { - return mono_threads_platform_create_thread (start, arg, tp, out_tid); + CreateThreadData *thread_data; + MonoThreadInfo *info; + gint res; + gpointer ret; + + thread_data = g_new0 (CreateThreadData, 1); + thread_data->ref = 2; + thread_data->start_routine = start; + thread_data->start_routine_arg = arg; + thread_data->create_suspended = tp->creation_flags & CREATE_SUSPENDED; + thread_data->priority = tp->priority; + mono_coop_sem_init (&thread_data->registered, 0); + + res = mono_threads_platform_create_thread (inner_start_thread, (gpointer) thread_data, tp->stack_size, out_tid); + if (res != 0) { + /* ref is not going to be decremented in inner_start_thread */ + InterlockedDecrement (&thread_data->ref); + ret = NULL; + goto done; + } + + res = mono_coop_sem_wait (&thread_data->registered, MONO_SEM_FLAGS_NONE); + g_assert (res == 0); + + info = thread_data->info; + g_assert (info); + + ret = info->handle; + g_assert (ret); + +done: + if (InterlockedDecrement (&thread_data->ref) == 0) { + mono_coop_sem_destroy (&thread_data->registered); + g_free (thread_data); + } + + return ret; } /* diff --git a/mono/utils/mono-threads.h b/mono/utils/mono-threads.h index 778deb5b51c..93e4aa4ce0f 100644 --- a/mono/utils/mono-threads.h +++ b/mono/utils/mono-threads.h @@ -538,7 +538,7 @@ gboolean mono_threads_suspend_needs_abort_syscall (void); void mono_threads_platform_register (THREAD_INFO_TYPE *info); void mono_threads_platform_unregister (THREAD_INFO_TYPE *info); -HANDLE mono_threads_platform_create_thread (MonoThreadStart start, gpointer arg, MonoThreadParm *, MonoNativeThreadId *out_tid); +int mono_threads_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize stack_size, MonoNativeThreadId *out_tid); void mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize); gboolean mono_threads_platform_yield (void); void mono_threads_platform_exit (int exit_code);