#include <mono/utils/mono-membar.h>
#include <mono/utils/mono-time.h>
#include <mono/utils/mono-threads.h>
+#include <mono/utils/mono-threads-coop.h>
#include <mono/utils/hazard-pointer.h>
#include <mono/utils/mono-tls.h>
#include <mono/utils/atomic.h>
}
static MonoThread*
-create_thread_object (MonoDomain *domain, MonoError *error)
+create_thread_object (MonoDomain *domain)
{
+ MonoError error;
MonoVTable *vt = mono_class_vtable (domain, mono_defaults.thread_class);
- MonoThread *t = (MonoThread*)mono_object_new_mature (vt, error);
+ MonoThread *t = (MonoThread*)mono_object_new_mature (vt, &error);
+ /* only possible failure mode is OOM, from which we don't expect to recover. */
+ mono_error_assert_ok (&error);
return t;
}
static MonoThread*
-new_thread_with_internal (MonoDomain *domain, MonoInternalThread *internal, MonoError *error)
+new_thread_with_internal (MonoDomain *domain, MonoInternalThread *internal)
{
MonoThread *thread;
- thread = create_thread_object (domain, error);
- if (!mono_error_ok (error))
- return NULL;
+ thread = create_thread_object (domain);
MONO_OBJECT_SETREF (thread, internal_thread, internal);
}
static MonoInternalThread*
-create_internal_thread (MonoError *error)
+create_internal_thread (void)
{
+ MonoError error;
MonoInternalThread *thread;
MonoVTable *vt;
vt = mono_class_vtable (mono_get_root_domain (), mono_defaults.internal_thread_class);
- thread = (MonoInternalThread*) mono_object_new_mature (vt, error);
- if (!mono_error_ok (error))
- return NULL;
+ thread = (MonoInternalThread*) mono_object_new_mature (vt, &error);
+ /* only possible failure mode is OOM, from which we don't exect to recover */
+ mono_error_assert_ok (&error);
thread->synch_cs = g_new0 (MonoCoopMutex, 1);
mono_coop_mutex_init_recursive (thread->synch_cs);
}
static gboolean
-init_root_domain_thread (MonoInternalThread *thread, MonoThread *candidate, MonoError *error)
+init_root_domain_thread (MonoInternalThread *thread, MonoThread *candidate)
{
MonoDomain *domain = mono_get_root_domain ();
- mono_error_init (error);
if (!candidate || candidate->obj.vtable->domain != domain) {
- candidate = new_thread_with_internal (domain, thread, error);
- return_val_if_nok (error, FALSE);
+ candidate = new_thread_with_internal (domain, thread);
}
set_current_thread_for_domain (domain, thread, candidate);
g_assert (!thread->root_domain_thread);
/* We have to do this here because mono_thread_new_init()
requires that root_domain_thread is set up. */
thread_adjust_static_data (internal);
- init_root_domain_thread (internal, start_info->obj, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ init_root_domain_thread (internal, start_info->obj);
/* This MUST be called before any managed code can be
* executed, as it calls the callback function that (for the
mono_error_init (error);
- thread = create_thread_object (domain, error);
- return_val_if_nok (error, NULL);
+ thread = create_thread_object (domain);
- internal = create_internal_thread (error);
- return_val_if_nok (error, NULL);
+ internal = create_internal_thread ();
MONO_OBJECT_SETREF (thread, internal_thread, internal);
MonoThread *
mono_thread_attach (MonoDomain *domain)
{
- MonoError error;
- MonoThread *thread = mono_thread_attach_full (domain, FALSE, &error);
- mono_error_raise_exception (&error);
+ MonoThread *thread = mono_thread_attach_full (domain, FALSE);
return thread;
}
MonoThread *
-mono_thread_attach_full (MonoDomain *domain, gboolean force_attach, MonoError *error)
+mono_thread_attach_full (MonoDomain *domain, gboolean force_attach)
{
MonoThreadInfo *info;
MonoInternalThread *thread;
HANDLE thread_handle;
MonoNativeThreadId tid;
- mono_error_init (error);
-
if ((thread = mono_thread_internal_current ())) {
if (domain != mono_domain_get ())
mono_domain_set (domain, TRUE);
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 ());
}
- thread = create_internal_thread (error);
- if (!mono_error_ok (error))
- return NULL;
+ thread = create_internal_thread ();
thread_handle = mono_thread_info_open_handle ();
g_assert (thread_handle);
thread->thread_info = info;
thread->small_id = info->small_id;
- current_thread = new_thread_with_internal (domain, thread, error);
- if (!mono_error_ok (error))
- return NULL;
+ current_thread = new_thread_with_internal (domain, thread);
if (!handle_store (current_thread, force_attach)) {
/* Mono is shutting down, so just wait for the end */
thread_adjust_static_data (thread);
- init_root_domain_thread (thread, current_thread, error);
- return_val_if_nok (error, NULL);
+ init_root_domain_thread (thread, current_thread);
if (domain != mono_get_root_domain ())
set_current_thread_for_domain (domain, thread, current_thread);
void
ves_icall_System_Threading_Thread_ConstructInternalThread (MonoThread *this_obj)
{
- MonoError error;
MonoInternalThread *internal;
- internal = create_internal_thread (&error);
- if (mono_error_set_pending_exception (&error))
- return;
+ internal = create_internal_thread ();
internal->state = ThreadState_Unstarted;
UNLOCK_THREAD (this_obj);
if (this_obj->name && this_obj->tid) {
- char *tname = mono_string_to_utf8 (name);
+ char *tname = mono_string_to_utf8_checked (name, error);
+ return_if_nok (error);
mono_profiler_thread_name (this_obj->tid, tname);
mono_native_thread_set_name (thread_get_tid (this_obj), tname);
mono_free (tname);
MonoThread *
mono_thread_current (void)
{
- MonoError error;
MonoDomain *domain = mono_domain_get ();
MonoInternalThread *internal = mono_thread_internal_current ();
MonoThread **current_thread_ptr;
if (!*current_thread_ptr) {
g_assert (domain != mono_get_root_domain ());
- *current_thread_ptr = new_thread_with_internal (domain, internal, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ *current_thread_ptr = new_thread_with_internal (domain, internal);
}
return *current_thread_ptr;
}
static MonoThread *
mono_thread_current_for_thread (MonoInternalThread *internal)
{
- MonoError error;
MonoDomain *domain = mono_domain_get ();
MonoThread **current_thread_ptr;
if (!*current_thread_ptr) {
g_assert (domain != mono_get_root_domain ());
- *current_thread_ptr = new_thread_with_internal (domain, internal, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ *current_thread_ptr = new_thread_with_internal (domain, internal);
}
return *current_thread_ptr;
}
This function is part of the embeding API and has no way to return the exception
to be thrown. So what we do is keep the old behavior and raise the exception.
*/
- mono_error_raise_exception (&error);
+ mono_error_raise_exception (&error); /* OK to throw, see note */
} else {
async_abort_internal (internal, TRUE);
}
}
/* Obtain the thread dump of all threads */
-static void
-mono_threads_get_thread_dump (MonoArray **out_threads, MonoArray **out_stack_frames)
+static gboolean
+mono_threads_get_thread_dump (MonoArray **out_threads, MonoArray **out_stack_frames, MonoError *error)
{
- MonoError error;
ThreadDumpUserData ud;
MonoInternalThread *thread_array [128];
MonoDebugSourceLocation *location;
int tindex, nthreads;
- mono_error_init (&error);
+ mono_error_init (error);
*out_threads = NULL;
*out_stack_frames = NULL;
ud.frames = g_new0 (MonoStackFrameInfo, 256);
ud.max_frames = 256;
- *out_threads = mono_array_new_checked (domain, mono_defaults.thread_class, nthreads, &error);
- if (!is_ok (&error))
+ *out_threads = mono_array_new_checked (domain, mono_defaults.thread_class, nthreads, error);
+ if (!is_ok (error))
goto leave;
- *out_stack_frames = mono_array_new_checked (domain, mono_defaults.array_class, nthreads, &error);
- if (!is_ok (&error))
+ *out_stack_frames = mono_array_new_checked (domain, mono_defaults.array_class, nthreads, error);
+ if (!is_ok (error))
goto leave;
for (tindex = 0; tindex < nthreads; ++tindex) {
mono_array_setref_fast (*out_threads, tindex, mono_thread_current_for_thread (thread));
- thread_frames = mono_array_new_checked (domain, mono_defaults.stack_frame_class, ud.nframes, &error);
- if (!is_ok (&error))
+ thread_frames = mono_array_new_checked (domain, mono_defaults.stack_frame_class, ud.nframes, error);
+ if (!is_ok (error))
goto leave;
mono_array_setref_fast (*out_stack_frames, tindex, thread_frames);
for (i = 0; i < ud.nframes; ++i) {
MonoStackFrameInfo *frame = &ud.frames [i];
MonoMethod *method = NULL;
- MonoStackFrame *sf = (MonoStackFrame *)mono_object_new_checked (domain, mono_defaults.stack_frame_class, &error);
- if (!mono_error_ok (&error))
+ MonoStackFrame *sf = (MonoStackFrame *)mono_object_new_checked (domain, mono_defaults.stack_frame_class, error);
+ if (!is_ok (error))
goto leave;
sf->native_offset = frame->native_offset;
if (method) {
sf->method_address = (gsize) frame->ji->code_start;
- MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, NULL, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, NULL, error);
+ if (!is_ok (error))
+ goto leave;
MONO_OBJECT_SETREF (sf, method, rm);
location = mono_debug_lookup_source_location (method, frame->native_offset, domain);
leave:
g_free (ud.frames);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ return is_ok (error);
}
/**
mono_threads_unlock ();
}
-static void
-mono_special_static_data_free_slot (guint32 offset, guint32 size)
-{
- /* Only ever called for ThreadLocal instances */
- g_assert (ACCESS_SPECIAL_STATIC_OFFSET (offset, type) == SPECIAL_STATIC_OFFSET_TYPE_THREAD);
-
- mono_threads_lock ();
- do_free_special_slot (offset, size);
- mono_threads_unlock ();
-}
-
#ifdef HOST_WIN32
static void CALLBACK dummy_apc (ULONG_PTR param)
{
}
joinable_threads_unlock ();
if (found) {
- if (thread != pthread_self ())
+ if (thread != pthread_self ()) {
+ MONO_ENTER_GC_SAFE;
/* This shouldn't block */
pthread_join (thread, NULL);
+ MONO_EXIT_GC_SAFE;
+ }
} else {
break;
}
if (!found)
return;
thread = (pthread_t)tid;
+ MONO_ENTER_GC_SAFE;
pthread_join (thread, NULL);
+ MONO_EXIT_GC_SAFE;
#endif
}
void
ves_icall_System_Threading_Thread_GetStackTraces (MonoArray **out_threads, MonoArray **out_stack_traces)
{
- mono_threads_get_thread_dump (out_threads, out_stack_traces);
+ MonoError error;
+ mono_threads_get_thread_dump (out_threads, out_stack_traces, &error);
+ mono_error_set_pending_exception (&error);
}
/*
gpointer
mono_threads_attach_coop (MonoDomain *domain, gpointer *dummy)
{
- MonoError error;
MonoDomain *orig;
gboolean fresh_thread;
}
if (!mono_thread_internal_current ()) {
- mono_thread_attach_full (domain, FALSE, &error);
- mono_error_assert_ok (&error);
+ mono_thread_attach_full (domain, FALSE);
// #678164
mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
*dummy = NULL;
/* mono_thread_attach put the thread in RUNNING mode from STARTING, but we need to
* return the right cookie. */
- return mono_threads_enter_gc_unsafe_region_cookie (mono_thread_info_current ());
+ return mono_threads_enter_gc_unsafe_region_cookie ();
} else {
*dummy = orig;
/* thread state (BLOCKING|RUNNING) -> RUNNING */