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;
#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
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;
}
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:
*
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;
}
/*
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);