X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fthreads.c;h=56a1ea2646be71194ebe78c192d034ce8c60dd2f;hb=4df4b7a47a07d924d7bfcfc53f43bd2319b54266;hp=f65f890749eeb81b928f36e060ee002b0673536d;hpb=9abcad0826874c241f34d60eff9f26561b112fce;p=mono.git diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c index f65f890749e..56a1ea2646b 100644 --- a/mono/metadata/threads.c +++ b/mono/metadata/threads.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #ifndef HOST_WIN32 #include @@ -410,7 +411,11 @@ static void thread_cleanup (MonoInternalThread *thread) if (mono_thread_cleanup_fn) mono_thread_cleanup_fn (thread); - MONO_GC_UNREGISTER_ROOT (thread->thread_pinning_ref); + if (mono_gc_is_moving ()) { + MONO_GC_UNREGISTER_ROOT (thread->thread_pinning_ref); + thread->thread_pinning_ref = NULL; + } + } static gpointer @@ -695,13 +700,22 @@ register_thread_start_argument (MonoThread *thread, struct StartInfo *start_info mono_g_hash_table_insert (thread_start_args, thread, start_info->start_arg); } -MonoInternalThread* mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gboolean threadpool_thread, guint32 stack_size) +/* + * mono_thread_create_internal: + * + * If NO_DETACH is TRUE, then the thread is not detached using pthread_detach (). This is needed to fix the race condition where waiting for a thred to exit only waits for its exit event to be + * signalled, which can cause shutdown crashes if the thread shutdown code accesses data already freed by the runtime shutdown. + * Currently, this is only used for the finalizer thread. + */ +MonoInternalThread* +mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gboolean threadpool_thread, gboolean no_detach, guint32 stack_size) { MonoThread *thread; MonoInternalThread *internal; HANDLE thread_handle; struct StartInfo *start_info; gsize tid; + guint32 create_flags; thread = create_thread_object (domain); internal = create_internal_thread_object (); @@ -733,8 +747,13 @@ MonoInternalThread* mono_thread_create_internal (MonoDomain *domain, gpointer fu /* Create suspended, so we can do some housekeeping before the thread * starts */ + create_flags = CREATE_SUSPENDED; +#ifndef HOST_WIN32 + if (no_detach) + create_flags |= CREATE_NO_DETACH; +#endif thread_handle = mono_create_thread (NULL, stack_size, (LPTHREAD_START_ROUTINE)start_wrapper, start_info, - CREATE_SUSPENDED, &tid); + create_flags, &tid); THREAD_DEBUG (g_message ("%s: Started thread ID %"G_GSIZE_FORMAT" (handle %p)", __func__, tid, thread_handle)); if (thread_handle == NULL) { /* The thread couldn't be created, so throw an exception */ @@ -749,9 +768,11 @@ MonoInternalThread* mono_thread_create_internal (MonoDomain *domain, gpointer fu internal->handle=thread_handle; internal->tid=tid; internal->apartment_state=ThreadApartmentState_Unknown; - internal->thread_pinning_ref = internal; internal->managed_id = get_next_managed_thread_id (); - MONO_GC_REGISTER_ROOT_PINNING (internal->thread_pinning_ref); + if (mono_gc_is_moving ()) { + internal->thread_pinning_ref = internal; + MONO_GC_REGISTER_ROOT_PINNING (internal->thread_pinning_ref); + } internal->synch_cs = g_new0 (CRITICAL_SECTION, 1); InitializeCriticalSection (internal->synch_cs); @@ -773,7 +794,7 @@ MonoInternalThread* mono_thread_create_internal (MonoDomain *domain, gpointer fu void mono_thread_create (MonoDomain *domain, gpointer func, gpointer arg) { - mono_thread_create_internal (domain, func, arg, FALSE, 0); + mono_thread_create_internal (domain, func, arg, FALSE, FALSE, 0); } /* @@ -880,9 +901,11 @@ mono_thread_attach (MonoDomain *domain) thread->android_tid = (gpointer) gettid (); #endif thread->apartment_state=ThreadApartmentState_Unknown; - thread->thread_pinning_ref = thread; thread->managed_id = get_next_managed_thread_id (); - MONO_GC_REGISTER_ROOT_PINNING (thread->thread_pinning_ref); + if (mono_gc_is_moving ()) { + thread->thread_pinning_ref = thread; + MONO_GC_REGISTER_ROOT_PINNING (thread->thread_pinning_ref); + } thread->stack_ptr = &tid; @@ -1049,8 +1072,10 @@ HANDLE ves_icall_System_Threading_Thread_Thread_internal(MonoThread *this, internal->handle=thread; internal->tid=tid; - internal->thread_pinning_ref = internal; - MONO_GC_REGISTER_ROOT_PINNING (internal->thread_pinning_ref); + if (mono_gc_is_moving ()) { + internal->thread_pinning_ref = internal; + MONO_GC_REGISTER_ROOT_PINNING (internal->thread_pinning_ref); + } /* Don't call handle_store() here, delay it to Start. @@ -2072,13 +2097,14 @@ mono_thread_get_abort_signal (void) { #ifdef HOST_WIN32 return -1; -#else -#ifndef SIGRTMIN +#elif defined(PLATFORM_ANDROID) + return SIGUNUSED; +#elif !defined (SIGRTMIN) #ifdef SIGUSR1 return SIGUSR1; #else return -1; -#endif +#endif /* SIGUSR1 */ #else static int abort_signum = -1; int i; @@ -2095,7 +2121,6 @@ mono_thread_get_abort_signal (void) } /* fallback to the old way */ return SIGRTMIN; -#endif #endif /* HOST_WIN32 */ } @@ -2442,6 +2467,12 @@ ves_icall_System_Threading_Thread_VolatileReadFloat (void *ptr) return *((volatile float *) (ptr)); } +MonoObject* +ves_icall_System_Threading_Volatile_Read_T (void *ptr) +{ + return (MonoObject*)*((volatile MonoObject**)ptr); +} + void ves_icall_System_Threading_Thread_VolatileWrite1 (void *ptr, gint8 value) { @@ -2490,6 +2521,13 @@ ves_icall_System_Threading_Thread_VolatileWriteFloat (void *ptr, float value) *((volatile float *) ptr) = value; } +void +ves_icall_System_Threading_Volatile_Write_T (void *ptr, MonoObject *value) +{ + *((volatile MonoObject **) ptr) = value; + mono_gc_wbarrier_generic_nostore (ptr); +} + void mono_thread_init (MonoThreadStartCB start_cb, MonoThreadAttachCB attach_cb) { @@ -2869,6 +2907,10 @@ void mono_thread_manage (void) THREAD_DEBUG (g_message ("%s: I have %d threads after waiting.", __func__, wait->num)); } while(wait->num>0); +#ifndef MONO_CROSS_COMPILE + mono_runtime_shutdown (); +#endif + mono_threads_set_shutting_down (); /* No new threads will be created after this point */ @@ -4465,6 +4507,8 @@ static MonoJitInfo* mono_thread_info_get_last_managed (MonoThreadInfo *info) { MonoJitInfo *ji = NULL; + if (!info) + return NULL; mono_get_eh_callbacks ()->mono_walk_stack_with_state (last_managed, &info->suspend_state, MONO_UNWIND_SIGNAL_SAFE, &ji); return ji; } @@ -4571,10 +4615,20 @@ suspend_thread_internal (MonoInternalThread *thread, gboolean interrupt) transition_to_suspended (thread); mono_thread_info_self_suspend (); } else { - MonoThreadInfo *info = mono_thread_info_safe_suspend_sync ((MonoNativeThreadId)(gsize)thread->tid, interrupt); - MonoJitInfo *ji = mono_thread_info_get_last_managed (info); - gboolean protected_wrapper = ji && mono_threads_is_critical_method (ji->method); - gboolean running_managed = mono_jit_info_match (ji, MONO_CONTEXT_GET_IP (&info->suspend_state.ctx)); + MonoThreadInfo *info; + MonoJitInfo *ji; + gboolean protected_wrapper; + gboolean running_managed; + + /*A null info usually means the thread is already dead. */ + if (!(info = mono_thread_info_safe_suspend_sync ((MonoNativeThreadId)(gsize)thread->tid, interrupt))) { + LeaveCriticalSection (thread->synch_cs); + return; + } + + ji = mono_thread_info_get_last_managed (info); + protected_wrapper = ji && mono_threads_is_critical_method (ji->method); + running_managed = mono_jit_info_match (ji, MONO_CONTEXT_GET_IP (&info->suspend_state.ctx)); if (running_managed && !protected_wrapper) { transition_to_suspended (thread);