X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fthreads.c;h=6867741e3ce39026918ea56b45a7c028cbe2e9a8;hb=d540bdce6d8f9bfedb6cc8a3071bb9b4e4dd2c51;hp=ebfe4b5be9264ed9ece3e270fd09f2702d5ecc95;hpb=58cc5d1bd13ca28888e1f4f357b7cb9df43edb58;p=mono.git diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c index ebfe4b5be92..6867741e3ce 100644 --- a/mono/metadata/threads.c +++ b/mono/metadata/threads.c @@ -192,9 +192,6 @@ static MonoThreadAttachCB mono_thread_attach_cb = NULL; /* function called at thread cleanup */ static MonoThreadCleanupFunc mono_thread_cleanup_fn = NULL; -/* function called to notify the runtime about a pending exception on the current thread */ -static MonoThreadNotifyPendingExcFunc mono_thread_notify_pending_exc_fn = NULL; - /* The default stack size for each thread */ static guint32 default_stacksize = 0; #define default_stacksize_for_thread(thread) ((thread)->stack_size? (thread)->stack_size: default_stacksize) @@ -205,9 +202,10 @@ static void mono_free_static_data (gpointer* static_data); static void mono_init_static_data_info (StaticDataInfo *static_data); static guint32 mono_alloc_static_data_slot (StaticDataInfo *static_data, guint32 size, guint32 align); static gboolean mono_thread_resume (MonoInternalThread* thread); -static void abort_thread_internal (MonoInternalThread *thread, gboolean can_raise_exception, gboolean install_async_abort); -static void suspend_thread_internal (MonoInternalThread *thread, gboolean interrupt); -static void self_suspend_internal (MonoInternalThread *thread); +static void async_abort_internal (MonoInternalThread *thread, gboolean install_async_abort); +static void self_abort_internal (void); +static void async_suspend_internal (MonoInternalThread *thread, gboolean interrupt); +static void self_suspend_internal (void); static MonoException* mono_thread_execute_interruption (void); static void ref_stack_destroy (gpointer rs); @@ -1323,16 +1321,21 @@ mono_thread_get_managed_id (MonoThread *thread) MonoString* ves_icall_System_Threading_Thread_GetName_internal (MonoInternalThread *this_obj) { + MonoError error; MonoString* str; + mono_error_init (&error); + LOCK_THREAD (this_obj); if (!this_obj->name) str = NULL; else - str = mono_string_new_utf16 (mono_domain_get (), this_obj->name, this_obj->name_len); + str = mono_string_new_utf16_checked (mono_domain_get (), this_obj->name, this_obj->name_len, &error); UNLOCK_THREAD (this_obj); + + mono_error_raise_exception (&error); return str; } @@ -2143,9 +2146,9 @@ void ves_icall_System_Threading_Thread_Interrupt_internal (MonoThread *this_obj) throw_ = current != thread && (thread->state & ThreadState_WaitSleepJoin); UNLOCK_THREAD (thread); - + if (throw_) { - abort_thread_internal (thread, TRUE, FALSE); + async_abort_internal (thread, FALSE); } } @@ -2207,7 +2210,10 @@ ves_icall_System_Threading_Thread_Abort (MonoInternalThread *thread, MonoObject UNLOCK_THREAD (thread); - abort_thread_internal (thread, TRUE, TRUE); + if (thread == mono_thread_internal_current ()) + self_abort_internal (); + else + async_abort_internal (thread, TRUE); } void @@ -2307,7 +2313,15 @@ mono_thread_suspend (MonoInternalThread *thread) } thread->state |= ThreadState_SuspendRequested; - suspend_thread_internal (thread, FALSE); + + if (thread == mono_thread_internal_current ()) { + /* calls UNLOCK_THREAD (thread) */ + self_suspend_internal (); + } else { + /* calls UNLOCK_THREAD (thread) */ + async_suspend_internal (thread, FALSE); + } + return TRUE; } @@ -2415,7 +2429,10 @@ void mono_thread_internal_stop (MonoInternalThread *thread) UNLOCK_THREAD (thread); - abort_thread_internal (thread, TRUE, TRUE); + if (thread == mono_thread_internal_current ()) + self_abort_internal (); + else + async_abort_internal (thread, TRUE); } void mono_thread_stop (MonoThread *thread) @@ -2840,11 +2857,6 @@ mono_thread_set_manage_callback (MonoThread *thread, MonoThreadManageCallback fu thread->internal_thread->manage_callback = func; } -void mono_threads_install_notify_pending_exc (MonoThreadNotifyPendingExcFunc func) -{ - mono_thread_notify_pending_exc_fn = func; -} - G_GNUC_UNUSED static void print_tids (gpointer key, gpointer value, gpointer user) { @@ -3288,8 +3300,9 @@ void mono_thread_suspend_all_other_threads (void) thread->state &= ~ThreadState_AbortRequested; thread->state |= ThreadState_SuspendRequested; - /* Signal the thread to suspend */ - suspend_thread_internal (thread, TRUE); + + /* Signal the thread to suspend + calls UNLOCK_THREAD (thread) */ + async_suspend_internal (thread, TRUE); } if (eventidx <= 0) { /* @@ -4339,7 +4352,8 @@ mono_thread_execute_interruption (void) return thread->abort_exc; } else if ((thread->state & ThreadState_SuspendRequested) != 0) { - self_suspend_internal (thread); + /* calls UNLOCK_THREAD (thread) */ + self_suspend_internal (); return NULL; } else if ((thread->state & ThreadState_StopRequested) != 0) { @@ -4403,11 +4417,6 @@ mono_thread_request_interruption (gboolean running_managed) request count. When exiting the unmanaged method the count will be checked and the thread will be interrupted. */ - if (mono_thread_notify_pending_exc_fn && !running_managed) - /* The JIT will notify the thread about the interruption */ - /* This shouldn't take any locks */ - mono_thread_notify_pending_exc_fn (NULL); - /* this will awake the thread if it is in WaitForSingleObject or similar */ /* Our implementation of this function ignores the func argument */ @@ -4684,7 +4693,7 @@ typedef struct { } AbortThreadData; static SuspendThreadResult -abort_thread_critical (MonoThreadInfo *info, gpointer ud) +async_abort_critical (MonoThreadInfo *info, gpointer ud) { AbortThreadData *data = (AbortThreadData *)ud; MonoInternalThread *thread = data->thread; @@ -4712,10 +4721,6 @@ abort_thread_critical (MonoThreadInfo *info, gpointer ud) mono_thread_info_setup_async_call (info, self_interrupt_thread, NULL); return MonoResumeThread; } else { - if (mono_thread_notify_pending_exc_fn) - /* The JIT will notify the thread about the interruption */ - mono_thread_notify_pending_exc_fn (info); - /* * This will cause waits to be broken. * It will also prevent the thread from entering a wait, so if the thread returns @@ -4730,41 +4735,45 @@ abort_thread_critical (MonoThreadInfo *info, gpointer ud) } static void -abort_thread_internal (MonoInternalThread *thread, gboolean can_raise_exception, gboolean install_async_abort) +async_abort_internal (MonoInternalThread *thread, gboolean install_async_abort) { - AbortThreadData data = { 0 }; - data.thread = thread; - data.install_async_abort = install_async_abort; + AbortThreadData data; - /* - FIXME this is insanely broken, it doesn't cause interruption to happen - synchronously since passing FALSE to mono_thread_request_interruption makes sure it returns NULL - */ - if (thread == mono_thread_internal_current ()) { - /* Do it synchronously */ - MonoException *exc = mono_thread_request_interruption (can_raise_exception); - if (exc) - mono_raise_exception (exc); - - mono_thread_info_self_interrupt (); + g_assert (thread != mono_thread_internal_current ()); - return; - } + data.thread = thread; + data.install_async_abort = install_async_abort; + data.interrupt_token = NULL; - mono_thread_info_safe_suspend_and_run (thread_get_tid (thread), TRUE, abort_thread_critical, &data); + mono_thread_info_safe_suspend_and_run (thread_get_tid (thread), TRUE, async_abort_critical, &data); if (data.interrupt_token) mono_thread_info_finish_interrupt (data.interrupt_token); /*FIXME we need to wait for interruption to complete -- figure out how much into interruption we should wait for here*/ } -typedef struct{ +static void +self_abort_internal (void) +{ + MonoException *exc; + + /* FIXME this is insanely broken, it doesn't cause interruption to happen synchronously + * since passing FALSE to mono_thread_request_interruption makes sure it returns NULL */ + + exc = mono_thread_request_interruption (TRUE); + if (exc) + mono_raise_exception (exc); + + mono_thread_info_self_interrupt (); +} + +typedef struct { MonoInternalThread *thread; gboolean interrupt; MonoThreadInfoInterruptToken *interrupt_token; } SuspendThreadData; static SuspendThreadResult -suspend_thread_critical (MonoThreadInfo *info, gpointer ud) +async_suspend_critical (MonoThreadInfo *info, gpointer ud) { SuspendThreadData *data = (SuspendThreadData *)ud; MonoInternalThread *thread = data->thread; @@ -4785,48 +4794,47 @@ suspend_thread_critical (MonoThreadInfo *info, gpointer ud) InterlockedIncrement (&thread_interruption_requested); if (data->interrupt) data->interrupt_token = mono_thread_info_prepare_interrupt ((MonoThreadInfo *)thread->thread_info); - - if (mono_thread_notify_pending_exc_fn && !running_managed) - /* The JIT will notify the thread about the interruption */ - mono_thread_notify_pending_exc_fn (info); + return MonoResumeThread; } } - + +/* LOCKING: called with @thread synch_cs held, and releases it */ static void -suspend_thread_internal (MonoInternalThread *thread, gboolean interrupt) +async_suspend_internal (MonoInternalThread *thread, gboolean interrupt) { - if (thread == mono_thread_internal_current ()) { - mono_thread_info_begin_self_suspend (); - //XXX replace this with better named functions - thread->state &= ~ThreadState_SuspendRequested; - thread->state |= ThreadState_Suspended; - UNLOCK_THREAD (thread); - mono_thread_info_end_self_suspend (); - } else { - SuspendThreadData data = { 0 }; - data.thread = thread; - data.interrupt = interrupt; + SuspendThreadData data; - mono_thread_info_safe_suspend_and_run (thread_get_tid (thread), interrupt, suspend_thread_critical, &data); - if (data.interrupt_token) - mono_thread_info_finish_interrupt (data.interrupt_token); - UNLOCK_THREAD (thread); - } + g_assert (thread != mono_thread_internal_current ()); + + data.thread = thread; + data.interrupt = interrupt; + data.interrupt_token = NULL; + + mono_thread_info_safe_suspend_and_run (thread_get_tid (thread), interrupt, async_suspend_critical, &data); + if (data.interrupt_token) + mono_thread_info_finish_interrupt (data.interrupt_token); + + UNLOCK_THREAD (thread); } -/*This is called with @thread synch_cs held and it must release it*/ +/* LOCKING: called with @thread synch_cs held, and releases it */ static void -self_suspend_internal (MonoInternalThread *thread) +self_suspend_internal (void) { + MonoInternalThread *thread; + + thread = mono_thread_internal_current (); + mono_thread_info_begin_self_suspend (); thread->state &= ~ThreadState_SuspendRequested; thread->state |= ThreadState_Suspended; + UNLOCK_THREAD (thread); + mono_thread_info_end_self_suspend (); } - /* * mono_thread_is_foreign: * @thread: the thread to query @@ -4834,7 +4842,7 @@ self_suspend_internal (MonoInternalThread *thread) * This function allows one to determine if a thread was created by the mono runtime and has * a well defined lifecycle or it's a foreigh one, created by the native environment. * - * Returns: true if @thread was not created by the runtime. + * Returns: TRUE if @thread was not created by the runtime. */ mono_bool mono_thread_is_foreign (MonoThread *thread)