private int abort_state_handle;
/* thread_id is only accessed from unmanaged code */
internal Int64 thread_id;
- private IntPtr stack_ptr;
+ private IntPtr debugger_thread; // FIXME switch to bool as soon as CI testing with corlib version bump works
private UIntPtr static_data; /* GC-tracked */
private IntPtr runtime_thread_info;
/* current System.Runtime.Remoting.Contexts.Context instance
MonoError error;
unload_data *data = (unload_data*)arg;
MonoDomain *domain = data->domain;
- MonoThread *thread;
+ MonoInternalThread *internal;
int i;
- /* Have to attach to the runtime so shutdown can wait for this thread */
- /* Force it to be attached to avoid racing during shutdown. */
- thread = mono_thread_attach_full (mono_get_root_domain (), TRUE);
+ internal = mono_thread_internal_current ();
- mono_thread_set_name_internal (thread->internal_thread, mono_string_new (mono_get_root_domain (), "Domain unloader"), TRUE, FALSE, &error);
+ mono_thread_set_name_internal (internal, mono_string_new (mono_domain_get (), "Domain unloader"), TRUE, FALSE, &error);
if (!is_ok (&error)) {
data->failure_reason = g_strdup (mono_error_get_message (&error));
mono_error_cleanup (&error);
mono_atomic_store_release (&data->done, TRUE);
unload_data_unref (data);
- mono_thread_detach (thread);
return 0;
failure:
mono_atomic_store_release (&data->done, TRUE);
unload_data_unref (data);
- mono_thread_detach (thread);
return 1;
}
MonoAppDomainState prev_state;
MonoMethod *method;
unload_data *thread_data;
- MonoNativeThreadId tid;
+ MonoInternalThread *internal;
MonoDomain *caller_domain = mono_domain_get ();
/* printf ("UNLOAD STARTING FOR %s (%p) IN THREAD 0x%x.\n", domain->friendly_name, domain, mono_native_thread_id_get ()); */
/*
* First we create a separate thread for unloading, since
* we might have to abort some threads, including the current one.
+ *
+ * Have to attach to the runtime so shutdown can wait for this thread.
+ *
+ * Force it to be attached to avoid racing during shutdown.
*/
- thread_handle = mono_threads_create_thread (unload_thread_main, thread_data, NULL, &tid);
- if (thread_handle == NULL)
- return;
+ internal = mono_thread_create_internal (mono_get_root_domain (), unload_thread_main, thread_data, MONO_THREAD_CREATE_FLAGS_FORCE_CREATE, &error);
+ mono_error_assert_ok (&error);
+
+ thread_handle = mono_threads_open_thread_handle (internal->handle);
/* Wait for the thread */
while (!thread_data->done && guarded_wait (thread_handle, MONO_INFINITE_WAIT, TRUE) == MONO_THREAD_INFO_WAIT_RET_ALERTED) {
static void
transport_start_receive (void)
{
+ MonoError error;
+ MonoInternalThread *internal;
+
transport_connect ();
if (!listen_fd)
return;
- receiver_thread_handle = mono_threads_create_thread (receiver_thread, NULL, NULL, NULL);
+ internal = mono_thread_create_internal (mono_get_root_domain (), receiver_thread, NULL, MONO_THREAD_CREATE_FLAGS_NONE, &error);
+ mono_error_assert_ok (&error);
+
+ receiver_thread_handle = mono_threads_open_thread_handle (internal->handle);
g_assert (receiver_thread_handle);
}
guint8 buffer [256];
guint8 *p, *p_end;
MonoObject *exc;
+ MonoInternalThread *internal;
- mono_native_thread_set_name (mono_native_thread_id_get (), "Attach receiver");
+ internal = mono_thread_internal_current ();
+ mono_thread_set_name_internal (internal, mono_string_new (mono_domain_get (), "Attach receiver"), TRUE, FALSE, &error);
+ mono_error_assert_ok (&error);
+ /* Ask the runtime to not abort this thread */
+ //internal->flags |= MONO_THREAD_FLAG_DONT_MANAGE;
+ /* Ask the runtime to not wait for this thread */
+ internal->state |= ThreadState_Background;
printf ("attach: Listening on '%s'...\n", server_uri);
printf ("attach: Connected.\n");
- MonoThread *thread = mono_thread_attach (mono_get_root_domain ());
- mono_thread_set_name_internal (thread->internal_thread, mono_string_new (mono_get_root_domain (), "Attach receiver"), TRUE, FALSE, &error);
- mono_error_assert_ok (&error);
- /* Ask the runtime to not abort this thread */
- //mono_thread_current ()->flags |= MONO_THREAD_FLAG_DONT_MANAGE;
- /* Ask the runtime to not wait for this thread */
- thread->internal_thread->state |= ThreadState_Background;
-
while (TRUE) {
char *cmd, *agent_name, *agent_args;
guint8 *body;
mono_gc_init_finalizer_thread (void)
{
MonoError error;
- gc_thread = mono_thread_create_internal (mono_domain_get (), finalizer_thread, NULL, FALSE, 0, &error);
+ gc_thread = mono_thread_create_internal (mono_domain_get (), finalizer_thread, NULL, MONO_THREAD_CREATE_FLAGS_NONE, &error);
mono_error_assert_ok (&error);
}
MonoException *abort_exc;
int abort_state_handle;
guint64 tid; /* This is accessed as a gsize in the code (so it can hold a 64bit pointer on systems that need it), but needs to reserve 64 bits of space on all machines as it corresponds to a field in managed code */
- gpointer stack_ptr;
+ gsize debugger_thread; // FIXME switch to bool as soon as CI testing with corlib version bump works
gpointer *static_data;
void *thread_info; /*This is MonoThreadInfo*, but to simplify dependencies, let's make it a void* here. */
MonoAppContext *current_appcontext;
g_error ("initialize: backend->init () failed");
MonoError error;
- if (!mono_thread_create_internal (mono_get_root_domain (), selector_thread, NULL, TRUE, SMALL_STACK, &error))
+ if (!mono_thread_create_internal (mono_get_root_domain (), selector_thread, NULL, MONO_THREAD_CREATE_FLAGS_THREADPOOL | MONO_THREAD_CREATE_FLAGS_SMALL_STACK, &error))
g_error ("initialize: mono_thread_create_internal () failed due to %s", mono_error_get_message (&error));
}
counter._.starting ++;
});
- thread = mono_thread_create_internal (mono_get_root_domain (), worker_thread, NULL, TRUE, 0, &error);
+ thread = mono_thread_create_internal (mono_get_root_domain (), worker_thread, NULL, MONO_THREAD_CREATE_FLAGS_THREADPOOL, &error);
if (!thread) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] try create worker, failed: could not create thread due to %s", mono_native_thread_id_get (), mono_error_get_message (&error));
mono_error_cleanup (&error);
return;
if (InterlockedCompareExchange (&worker.monitor_status, MONITOR_STATUS_REQUESTED, MONITOR_STATUS_NOT_RUNNING) == MONITOR_STATUS_NOT_RUNNING) {
// printf ("monitor_thread: creating\n");
- if (!mono_thread_create_internal (mono_get_root_domain (), monitor_thread, NULL, TRUE, SMALL_STACK, &error)) {
+ if (!mono_thread_create_internal (mono_get_root_domain (), monitor_thread, NULL, MONO_THREAD_CREATE_FLAGS_THREADPOOL | MONO_THREAD_CREATE_FLAGS_SMALL_STACK, &error)) {
// printf ("monitor_thread: creating failed\n");
worker.monitor_status = MONITOR_STATUS_NOT_RUNNING;
mono_error_cleanup (&error);
#include <mono/metadata/exception.h>
#include <mono/metadata/object-internals.h>
-#define SMALL_STACK (sizeof (gpointer) * 32 * 1024)
-
typedef struct _MonoNativeOverlapped MonoNativeOverlapped;
void
/* INFO has type MonoThreadInfo* */
typedef void (*MonoThreadNotifyPendingExcFunc) (gpointer info);
-MonoInternalThread* mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gboolean threadpool_thread, guint32 stack_size, MonoError *error);
+typedef enum {
+ MONO_THREAD_CREATE_FLAGS_NONE = 0x0,
+ MONO_THREAD_CREATE_FLAGS_THREADPOOL = 0x1,
+ MONO_THREAD_CREATE_FLAGS_DEBUGGER = 0x2,
+ MONO_THREAD_CREATE_FLAGS_FORCE_CREATE = 0x4,
+ MONO_THREAD_CREATE_FLAGS_SMALL_STACK = 0x8,
+} MonoThreadCreateFlags;
+
+MonoInternalThread*
+mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, MonoThreadCreateFlags flags, MonoError *error);
void mono_threads_install_cleanup (MonoThreadCleanupFunc func);
mono_alloc_static_data (gpointer **static_data_ptr, guint32 offset, gboolean threadlocal);
static gboolean
-mono_thread_attach_internal (MonoThread *thread, gboolean force_attach, gboolean force_domain, gsize *stack_ptr)
+mono_thread_attach_internal (MonoThread *thread, gboolean force_attach, gboolean force_domain)
{
MonoThreadInfo *info;
MonoInternalThread *internal;
internal->tid = MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ());
internal->thread_info = info;
internal->small_id = info->small_id;
- internal->stack_ptr = stack_ptr;
THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Setting current_object_key to %p", __func__, mono_native_thread_id_get (), internal));
MonoObject *start_delegate_arg;
MonoThreadStart start_func;
gpointer start_func_arg;
+ gboolean force_attach;
gboolean failed;
MonoCoopSem registered;
} StartInfo;
THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Start wrapper", __func__, mono_native_thread_id_get ()));
- if (!mono_thread_attach_internal (thread, FALSE, FALSE, stack_ptr)) {
+ if (!mono_thread_attach_internal (thread, start_info->force_attach, FALSE)) {
start_info->failed = TRUE;
mono_coop_sem_post (&start_info->registered);
return(0);
}
-static gsize WINAPI start_wrapper(void *data)
+static gsize WINAPI
+start_wrapper (gpointer data)
{
- volatile gsize dummy;
+ StartInfo *start_info;
+ MonoThreadInfo *info;
+ gsize res;
+
+ start_info = (StartInfo*) data;
+ g_assert (start_info);
+
+ info = mono_thread_info_attach (&res);
+ info->runtime_thread = TRUE;
+
+ /* Run the actual main function of the thread */
+ res = start_wrapper_internal (start_info, &res);
- return start_wrapper_internal ((StartInfo*) data, (gsize*) &dummy);
+ mono_thread_info_exit (res);
+
+ g_assert_not_reached ();
}
/*
*/
static gboolean
create_thread (MonoThread *thread, MonoInternalThread *internal, MonoObject *start_delegate, MonoThreadStart start_func, gpointer start_func_arg,
- gboolean threadpool_thread, guint32 stack_size, MonoError *error)
+ MonoThreadCreateFlags flags, MonoError *error)
{
StartInfo *start_info = NULL;
- MonoThreadHandle *thread_handle;
MonoNativeThreadId tid;
gboolean ret;
gsize stack_set_size;
if (start_func)
g_assert (!start_delegate);
+ if (flags & MONO_THREAD_CREATE_FLAGS_THREADPOOL) {
+ g_assert (!(flags & MONO_THREAD_CREATE_FLAGS_DEBUGGER));
+ g_assert (!(flags & MONO_THREAD_CREATE_FLAGS_FORCE_CREATE));
+ }
+ if (flags & MONO_THREAD_CREATE_FLAGS_DEBUGGER) {
+ g_assert (!(flags & MONO_THREAD_CREATE_FLAGS_THREADPOOL));
+ g_assert (!(flags & MONO_THREAD_CREATE_FLAGS_FORCE_CREATE));
+ }
+
/*
* Join joinable threads to prevent running out of threads since the finalizer
* thread might be blocked/backlogged.
error_init (error);
mono_threads_lock ();
- if (shutting_down) {
+ if (shutting_down && !(flags & MONO_THREAD_CREATE_FLAGS_FORCE_CREATE)) {
mono_threads_unlock ();
return FALSE;
}
mono_g_hash_table_insert (threads_starting_up, thread, thread);
mono_threads_unlock ();
- internal->threadpool_thread = threadpool_thread;
- if (threadpool_thread)
+ internal->threadpool_thread = flags & MONO_THREAD_CREATE_FLAGS_THREADPOOL;
+ if (internal->threadpool_thread)
mono_thread_set_state (internal, ThreadState_Background);
+ internal->debugger_thread = flags & MONO_THREAD_CREATE_FLAGS_DEBUGGER;
+
start_info = g_new0 (StartInfo, 1);
start_info->ref = 2;
start_info->thread = thread;
start_info->start_delegate_arg = thread->start_obj;
start_info->start_func = start_func;
start_info->start_func_arg = start_func_arg;
+ start_info->force_attach = flags & MONO_THREAD_CREATE_FLAGS_FORCE_CREATE;
start_info->failed = FALSE;
mono_coop_sem_init (&start_info->registered, 0);
- if (stack_size == 0)
+ if (flags != MONO_THREAD_CREATE_FLAGS_SMALL_STACK)
stack_set_size = default_stacksize_for_thread (internal);
else
stack_set_size = 0;
- thread_handle = mono_threads_create_thread (start_wrapper, start_info, &stack_set_size, &tid);
-
- if (thread_handle == NULL) {
+ if (!mono_thread_platform_create_thread (start_wrapper, start_info, &stack_set_size, &tid)) {
/* The thread couldn't be created, so set an exception */
mono_threads_lock ();
mono_g_hash_table_remove (threads_starting_up, thread);
mono_coop_sem_wait (&start_info->registered, MONO_SEM_FLAGS_NONE);
- mono_threads_close_thread_handle (thread_handle);
-
THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Done launching thread %p (%"G_GSIZE_FORMAT")", __func__, mono_native_thread_id_get (), internal, (gsize)internal->tid));
ret = !start_info->failed;
* ARG should not be a GC reference.
*/
MonoInternalThread*
-mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gboolean threadpool_thread, guint32 stack_size, MonoError *error)
+mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, MonoThreadCreateFlags flags, MonoError *error)
{
MonoThread *thread;
MonoInternalThread *internal;
LOCK_THREAD (internal);
- res = create_thread (thread, internal, NULL, (MonoThreadStart) func, arg, threadpool_thread, stack_size, error);
- return_val_if_nok (error, NULL);
+ res = create_thread (thread, internal, NULL, (MonoThreadStart) func, arg, flags, error);
UNLOCK_THREAD (internal);
+ return_val_if_nok (error, NULL);
return internal;
}
gboolean
mono_thread_create_checked (MonoDomain *domain, gpointer func, gpointer arg, MonoError *error)
{
- return (NULL != mono_thread_create_internal (domain, func, arg, FALSE, 0, error));
+ return (NULL != mono_thread_create_internal (domain, func, arg, MONO_THREAD_CREATE_FLAGS_NONE, error));
}
MonoThread *
{
MonoInternalThread *internal;
MonoThread *thread;
+ MonoThreadInfo *info;
MonoNativeThreadId tid;
gsize stack_ptr;
return mono_thread_current ();
}
- if (!mono_gc_register_thread (&domain)) {
- g_error ("Thread %"G_GSIZE_FORMAT" calling into managed code is not registered with the GC. On UNIX, this can be fixed by #include-ing <gc.h> before <pthread.h> in the file containing the thread creation code.", mono_native_thread_id_get ());
- }
+ info = mono_thread_info_attach (&stack_ptr);
+ g_assert (info);
tid=mono_native_thread_id_get ();
thread = create_thread_object (domain, internal);
- if (!mono_thread_attach_internal (thread, force_attach, TRUE, &stack_ptr)) {
+ if (!mono_thread_attach_internal (thread, force_attach, TRUE)) {
/* Mono is shutting down, so just wait for the end */
for (;;)
mono_thread_info_sleep (10000, NULL);
return this_obj;
}
- res = create_thread (this_obj, internal, start, NULL, NULL, FALSE, 0, &error);
+ res = create_thread (this_obj, internal, start, NULL, NULL, MONO_THREAD_CREATE_FLAGS_NONE, &error);
if (!res) {
mono_error_cleanup (&error);
UNLOCK_THREAD (internal);
static mono_thread_start_return_t WINAPI
compile_thread_main (gpointer user_data)
{
- MonoDomain *domain = ((MonoDomain **)user_data) [0];
- MonoAotCompile *acfg = ((MonoAotCompile **)user_data) [1];
- GPtrArray *methods = ((GPtrArray **)user_data) [2];
+ MonoAotCompile *acfg = ((MonoAotCompile **)user_data) [0];
+ GPtrArray *methods = ((GPtrArray **)user_data) [1];
int i;
MonoError error;
- MonoThread *thread = mono_thread_attach (domain);
- mono_thread_set_name_internal (thread->internal_thread, mono_string_new (mono_get_root_domain (), "AOT compiler"), TRUE, FALSE, &error);
+ MonoInternalThread *internal = mono_thread_internal_current ();
+ mono_thread_set_name_internal (internal, mono_string_new (mono_domain_get (), "AOT compiler"), TRUE, FALSE, &error);
mono_error_assert_ok (&error);
for (i = 0; i < methods->len; ++i)
methods [i] = (MonoMethod *)g_ptr_array_index (acfg->methods, i);
i = 0;
while (i < methods_len) {
+ MonoError error;
+ MonoInternalThread *thread;
+
frag = g_ptr_array_new ();
for (j = 0; j < len; ++j) {
if (i < methods_len) {
}
user_data = g_new0 (gpointer, 3);
- user_data [0] = mono_domain_get ();
- user_data [1] = acfg;
- user_data [2] = frag;
+ user_data [0] = acfg;
+ user_data [1] = frag;
- thread_handle = mono_threads_create_thread (compile_thread_main, (gpointer) user_data, NULL, NULL);
+ thread = mono_thread_create_internal (mono_domain_get (), compile_thread_main, (gpointer) user_data, MONO_THREAD_CREATE_FLAGS_NONE, &error);
+ mono_error_assert_ok (&error);
+
+ thread_handle = mono_threads_open_thread_handle (thread->handle);
g_ptr_array_add (threads, thread_handle);
}
g_free (methods);
static inline gboolean
is_debugger_thread (void)
{
- return mono_native_thread_id_equals (mono_native_thread_id_get (), debugger_thread_id);
+ MonoInternalThread *internal;
+
+ internal = mono_thread_internal_current ();
+ if (!internal)
+ return FALSE;
+
+ return internal->debugger_thread;
}
static int
static void
start_debugger_thread (void)
{
- debugger_thread_handle = mono_threads_create_thread (debugger_thread, NULL, NULL, NULL);
+ MonoError error;
+ MonoInternalThread *thread;
+
+ thread = mono_thread_create_internal (mono_get_root_domain (), debugger_thread, NULL, MONO_THREAD_CREATE_FLAGS_DEBUGGER, &error);
+ mono_error_assert_ok (&error);
+
+ debugger_thread_handle = mono_threads_open_thread_handle (thread->handle);
g_assert (debugger_thread_handle);
}
DebuggerTlsData *tls = (DebuggerTlsData *)value;
MonoNativeThreadId tid = MONO_UINT_TO_NATIVE_THREAD_ID (thread->tid);
- if (mono_native_thread_id_equals (mono_native_thread_id_get (), tid) || tls->terminated)
+ if (mono_thread_internal_is_current (thread) || tls->terminated)
return;
DEBUG_PRINTF (1, "[%p] Interrupting %p...\n", (gpointer) (gsize) mono_native_thread_id_get (), (gpointer)tid);
{
DebuggerTlsData *tls = (DebuggerTlsData *)value;
- if (!tls->suspended && !tls->terminated)
+ if (!tls->suspended && !tls->terminated && !mono_thread_internal_is_current (tls->thread))
*(int*)user_data = *(int*)user_data + 1;
}
static void
emit_thread_start (gpointer key, gpointer value, gpointer user_data)
{
- if (!mono_native_thread_id_equals (MONO_UINT_TO_NATIVE_THREAD_ID (GPOINTER_TO_UINT (key)), debugger_thread_id))
- process_profiler_event (EVENT_KIND_THREAD_START, value);
+ g_assert (!mono_native_thread_id_equals (MONO_UINT_TO_NATIVE_THREAD_ID (GPOINTER_TO_UINT (key)), debugger_thread_id));
+ process_profiler_event (EVENT_KIND_THREAD_START, value);
}
/*
MonoInternalThread *old_thread;
DebuggerTlsData *tls;
- if (mono_native_thread_id_equals (MONO_UINT_TO_NATIVE_THREAD_ID (tid), debugger_thread_id))
+ if (is_debugger_thread ())
return;
g_assert (mono_native_thread_id_equals (MONO_UINT_TO_NATIVE_THREAD_ID (tid), MONO_UINT_TO_NATIVE_THREAD_ID (thread->tid)));
if (thread) {
DEBUG_PRINTF (1, "[%p] Thread terminated, obj=%p, tls=%p.\n", (gpointer)tid, thread, tls);
- if (mono_native_thread_id_equals (mono_native_thread_id_get (), MONO_UINT_TO_NATIVE_THREAD_ID (tid))
- && !mono_native_tls_get_value (debugger_tls_id)
+ if (mono_thread_internal_is_current (thread) && !mono_native_tls_get_value (debugger_tls_id)
) {
/*
* This can happen on darwin since we deregister threads using pthread dtors.
debugger_thread_id = mono_native_thread_id_get ();
- MonoThread *thread = mono_thread_attach (mono_get_root_domain ());
- mono_thread_set_name_internal (thread->internal_thread, mono_string_new (mono_get_root_domain (), "Debugger agent"), TRUE, FALSE, &error);
+ MonoInternalThread *internal = mono_thread_internal_current ();
+ mono_thread_set_name_internal (internal, mono_string_new (mono_domain_get (), "Debugger agent"), TRUE, FALSE, &error);
mono_error_assert_ok (&error);
- thread->internal_thread->state |= ThreadState_Background;
- thread->internal_thread->flags |= MONO_THREAD_FLAG_DONT_MANAGE;
+ internal->state |= ThreadState_Background;
+ internal->flags |= MONO_THREAD_FLAG_DONT_MANAGE;
if (agent_config.defer) {
if (!wait_for_attach ()) {
#include <pthread.h>
#include <os/kernel/OS.h>
-void
-mono_threads_platform_reset_priority(pthread_attr_t *attr)
-{
- /* FIXME: Implement this on Haiku */
-}
-
void
mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize)
{
#include <sys/resource.h>
-#ifdef MONO_THREADS_PLATFORM_HAS_ATTR_SETSCHED
-void
-mono_threads_platform_reset_priority (pthread_attr_t *attr)
-{
- struct sched_param param;
- gint res;
- gint policy;
-
- memset (¶m, 0, sizeof (param));
-
- res = pthread_attr_getschedpolicy (attr, &policy);
- if (res != 0)
- g_error ("%s: pthread_attr_getschedpolicy failed, error: \"%s\" (%d)", __func__, g_strerror (res), res);
-
-#ifdef _POSIX_PRIORITY_SCHEDULING
- gint max, min;
-
- /* Necessary to get valid priority range */
-
- min = sched_get_priority_min (policy);
- max = sched_get_priority_max (policy);
-
- if (max > 0 && min >= 0 && max > min)
- param.sched_priority = (max - min) / 2 + min;
- else
-#endif
- {
- switch (policy) {
- case SCHED_FIFO:
- case SCHED_RR:
- param.sched_priority = 50;
- break;
-#ifdef SCHED_BATCH
- case SCHED_BATCH:
-#endif
- case SCHED_OTHER:
- param.sched_priority = 0;
- break;
- default:
- g_warning ("%s: unknown policy %d", __func__, policy);
- return;
- }
- }
-
- res = pthread_attr_setschedparam (attr, ¶m);
- if (res != 0)
- g_error ("%s: pthread_attr_setschedparam failed, error: \"%s\" (%d)", __func__, g_strerror (res), res);
-}
-#endif
-
-int
-mono_threads_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize* const stack_size, MonoNativeThreadId *out_tid)
+gboolean
+mono_thread_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize* const stack_size, MonoNativeThreadId *tid)
{
pthread_attr_t attr;
pthread_t thread;
gint res;
gsize set_stack_size;
- gsize min_stack_size;
res = pthread_attr_init (&attr);
- g_assert (!res);
+ if (res != 0)
+ g_error ("%s: pthread_attr_init failed, error: \"%s\" (%d)", __func__, g_strerror (res), res);
if (stack_size)
set_stack_size = *stack_size;
#endif
res = pthread_attr_setstacksize (&attr, set_stack_size);
- g_assert (!res);
+ if (res != 0)
+ g_error ("%s: pthread_attr_setstacksize failed, error: \"%s\" (%d)", __func__, g_strerror (res), res);
#endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */
- mono_threads_platform_reset_priority (&attr);
-
- if (stack_size) {
- res = pthread_attr_getstacksize (&attr, &min_stack_size);
+ /* Actually start the thread */
+ res = mono_gc_pthread_create (&thread, &attr, (gpointer (*)(gpointer)) thread_fn, thread_data);
+ if (res) {
+ res = pthread_attr_destroy (&attr);
if (res != 0)
- g_error ("%s: pthread_attr_getstacksize failed, error: \"%s\" (%d)", g_strerror (res), res);
+ g_error ("%s: pthread_attr_destroy failed, error: \"%s\" (%d)", __func__, g_strerror (res), res);
- *stack_size = min_stack_size;
+ return FALSE;
}
- /* Actually start the thread */
- res = mono_gc_pthread_create (&thread, &attr, (gpointer (*)(gpointer)) thread_fn, thread_data);
- if (res)
- return -1;
+ if (tid)
+ *tid = thread;
+
+ if (stack_size) {
+ res = pthread_attr_getstacksize (&attr, stack_size);
+ if (res != 0)
+ g_error ("%s: pthread_attr_getstacksize failed, error: \"%s\" (%d)", __func__, g_strerror (res), res);
+ }
- if (out_tid)
- *out_tid = thread;
+ res = pthread_attr_destroy (&attr);
+ if (res != 0)
+ g_error ("%s: pthread_attr_destroy failed, error: \"%s\" (%d)", __func__, g_strerror (res), res);
- return 0;
+ return TRUE;
}
void
#if defined (HOST_WIN32)
-int
-mono_threads_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize* const stack_size, MonoNativeThreadId *out_tid)
+gboolean
+mono_thread_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize* const stack_size, MonoNativeThreadId *tid)
{
HANDLE result;
DWORD thread_id;
result = CreateThread (NULL, stack_size ? *stack_size : 0, (LPTHREAD_START_ROUTINE) thread_fn, thread_data, 0, &thread_id);
if (!result)
- return -1;
+ return FALSE;
/* A new handle is open when attaching
* the thread, so we don't need this one */
CloseHandle (result);
- if (out_tid)
- *out_tid = thread_id;
+ if (tid)
+ *tid = thread_id;
if (stack_size) {
// TOOD: Use VirtualQuery to get correct value
*stack_size = 2 * 1024 * 1024;
}
- return 0;
+ return TRUE;
}
return FALSE;
}
-typedef struct {
- MonoRefCount ref;
- MonoThreadStart start_routine;
- gpointer start_routine_arg;
- MonoCoopSem registered;
- MonoThreadHandle *handle;
-} CreateThreadData;
-
-static void
-create_thread_data_destroy (gpointer data)
-{
- CreateThreadData *thread_data;
-
- thread_data = (CreateThreadData*) data;
-
- mono_coop_sem_destroy (&thread_data->registered);
- g_free (thread_data);
-}
-
-static gsize WINAPI
-inner_start_thread (gpointer data)
-{
- CreateThreadData *thread_data;
- MonoThreadInfo *info;
- MonoThreadStart start_routine;
- gpointer start_routine_arg;
- gsize start_routine_res;
- gsize dummy;
-
- thread_data = (CreateThreadData*) data;
- g_assert (thread_data);
-
- start_routine = thread_data->start_routine;
- start_routine_arg = thread_data->start_routine_arg;
-
- info = mono_thread_info_attach (&dummy);
- info->runtime_thread = TRUE;
-
- thread_data->handle = mono_threads_open_thread_handle (info->handle);
-
- mono_coop_sem_post (&thread_data->registered);
-
- mono_refcount_dec (thread_data);
-
- /* thread_data is not valid anymore */
- thread_data = NULL;
-
- /* Run the actual main function of the thread */
- start_routine_res = start_routine (start_routine_arg);
-
- mono_thread_info_exit (start_routine_res);
-
- g_assert_not_reached ();
-}
-
-/*
- * mono_threads_create_thread:
- *
- * Create a new thread executing START with argument ARG. Store its id into OUT_TID.
- * Returns: a windows or io-layer handle for the thread.
- */
-MonoThreadHandle*
-mono_threads_create_thread (MonoThreadStart start, gpointer arg, gsize * const stack_size, MonoNativeThreadId *out_tid)
-{
- CreateThreadData *thread_data;
- gint res;
- MonoThreadHandle *ret;
-
- thread_data = g_new0 (CreateThreadData, 1);
- mono_refcount_init (thread_data, create_thread_data_destroy);
- thread_data->start_routine = start;
- thread_data->start_routine_arg = arg;
- mono_coop_sem_init (&thread_data->registered, 0);
-
- res = mono_threads_platform_create_thread (inner_start_thread, (gpointer) mono_refcount_inc (thread_data), stack_size, out_tid);
- if (res != 0) {
- /* ref is not going to be decremented in inner_start_thread */
- mono_refcount_dec (thread_data);
- ret = NULL;
- goto done;
- }
-
- res = mono_coop_sem_wait (&thread_data->registered, MONO_SEM_FLAGS_NONE);
- g_assert (res == 0);
-
- ret = thread_data->handle;
- g_assert (ret);
-
-done:
- mono_refcount_dec (thread_data);
-
- return ret;
-}
-
/*
* mono_thread_info_get_stack_bounds:
*
gboolean
mono_thread_info_is_live (THREAD_INFO_TYPE *info);
-MonoThreadHandle*
-mono_threads_create_thread (MonoThreadStart start, gpointer arg, gsize * const stack_size, MonoNativeThreadId *out_tid);
-
int
mono_threads_get_max_stack_size (void);
gint mono_threads_suspend_get_restart_signal (void);
gint mono_threads_suspend_get_abort_signal (void);
-#if defined(USE_POSIX_BACKEND)
-void mono_threads_platform_reset_priority (pthread_attr_t *attr);
-#endif /* defined(USE_POSIX_BACKEND) */
-int mono_threads_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize* const stack_size, MonoNativeThreadId *out_tid);
+gboolean
+mono_thread_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data,
+ gsize* const stack_size, MonoNativeThreadId *tid);
+
void mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize);
void mono_threads_platform_init (void);
gboolean mono_threads_platform_in_critical_region (MonoNativeThreadId tid);