void mono_threads_core_exit (int exit_code) { MonoThreadInfo *current = mono_thread_info_current (); #if defined(__native_client__) nacl_shutdown_gc_thread(); #endif wapi_thread_handle_set_exited (current->handle, exit_code); g_assert (mono_threads_get_callbacks ()->thread_exit); mono_threads_get_callbacks ()->thread_exit (NULL); }
HANDLE mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start_routine, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid) { pthread_attr_t attr; int res; pthread_t thread; StartInfo start_info; res = pthread_attr_init (&attr); g_assert (!res); 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; #else stack_size = (SIZEOF_VOID_P / 4) * 1024 * 1024; #endif } #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 memset (&start_info, 0, sizeof (StartInfo)); start_info.start_routine = (gpointer)start_routine; start_info.arg = arg; start_info.flags = creation_flags; MONO_SEM_INIT (&(start_info.registered), 0); /* Actually start the thread */ res = mono_threads_get_callbacks ()->mono_gc_pthread_create (&thread, &attr, inner_start_thread, &start_info); if (res) { MONO_SEM_DESTROY (&(start_info.registered)); return NULL; } /* Wait until the thread register itself in various places */ while (MONO_SEM_WAIT (&(start_info.registered)) != 0) { /*if (EINTR != errno) ABORT("sem_wait failed"); */ } MONO_SEM_DESTROY (&(start_info.registered)); if (out_tid) *out_tid = thread; return start_info.handle; }
int mono_threads_pthread_create (pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) { ThreadStartInfo *start_info; int result; start_info = g_malloc0 (sizeof (ThreadStartInfo)); if (!start_info) return ENOMEM; MONO_SEM_INIT (&(start_info->registered), 0); start_info->arg = arg; start_info->start_routine = start_routine; result = mono_threads_get_callbacks ()->mono_gc_pthread_create (new_thread, attr, inner_start_thread, start_info); if (result == 0) { while (MONO_SEM_WAIT (&(start_info->registered)) != 0) { /*if (EINTR != errno) ABORT("sem_wait failed"); */ } } MONO_SEM_DESTROY (&(start_info->registered)); g_free (start_info); return result; }
static void* inner_start_thread (void *arg) { StartInfo *start_info = arg; void *t_arg = start_info->arg; int res; void *(*start_func)(void*) = start_info->start_routine; guint32 flags = start_info->flags; void *result; HANDLE handle; MonoThreadInfo *info; /* Register the thread with the io-layer */ handle = wapi_create_thread_handle (); if (!handle) { res = MONO_SEM_POST (&(start_info->registered)); g_assert (!res); return NULL; } start_info->handle = handle; info = mono_thread_info_attach (&result); info->runtime_thread = TRUE; info->handle = handle; if (flags & CREATE_SUSPENDED) { info->create_suspended = TRUE; MONO_SEM_INIT (&info->create_suspended_sem, 0); } /* start_info is not valid after this */ res = MONO_SEM_POST (&(start_info->registered)); g_assert (!res); start_info = NULL; if (flags & CREATE_SUSPENDED) { while (MONO_SEM_WAIT (&info->create_suspended_sem) != 0 && errno == EINTR); MONO_SEM_DESTROY (&info->create_suspended_sem); } /* Run the actual main function of the thread */ result = start_func (t_arg); /* mono_thread_info_detach (); */ #if defined(__native_client__) nacl_shutdown_gc_thread(); #endif wapi_thread_handle_set_exited (handle, GPOINTER_TO_UINT (result)); /* This is needed by mono_threads_core_unregister () which is called later */ info->handle = NULL; g_assert (mono_threads_get_callbacks ()->thread_exit); mono_threads_get_callbacks ()->thread_exit (NULL); g_assert_not_reached (); return result; }