X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=mono%2Fmetadata%2Fthreads.c;h=3eb6b3b623c8994cf3b2442b79a4270c2eebcc0b;hb=f98d0799d89401853f59e4427764932d633b8935;hp=8eb4fe5f24e474e619a68bb2e17a00cb1f52f043;hpb=6649f23b27e947abd19aeb8b12d3a204313ca9ec;p=mono.git diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c index 8eb4fe5f24e..3eb6b3b623c 100644 --- a/mono/metadata/threads.c +++ b/mono/metadata/threads.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -152,7 +153,7 @@ static MonoGHashTable *threads_starting_up = NULL; /* Contains tids */ /* Protected by the threads lock */ static GHashTable *joinable_threads; -static int joinable_thread_count; +static gint32 joinable_thread_count; #define SET_CURRENT_OBJECT(x) mono_tls_set_thread (x) #define GET_CURRENT_OBJECT() (MonoInternalThread*) mono_tls_get_thread () @@ -1801,7 +1802,7 @@ mono_join_uninterrupted (MonoThreadHandle* thread_to_join, gint32 ms, MonoError } gboolean -ves_icall_System_Threading_Thread_Join_internal(MonoThread *this_obj, int ms) +ves_icall_System_Threading_Thread_Join_internal (MonoThread *this_obj, int ms) { MonoInternalThread *thread = this_obj->internal_thread; MonoThreadHandle *handle = thread->handle; @@ -1821,30 +1822,42 @@ ves_icall_System_Threading_Thread_Join_internal(MonoThread *this_obj, int ms) return FALSE; } + MonoNativeThreadId tid = thread_get_tid (thread); + UNLOCK_THREAD (thread); - if(ms== -1) { - ms=MONO_INFINITE_WAIT; - } + if (ms == -1) + ms = MONO_INFINITE_WAIT; THREAD_DEBUG (g_message ("%s: joining thread handle %p, %d ms", __func__, handle, ms)); - + mono_thread_set_state (cur_thread, ThreadState_WaitSleepJoin); - ret=mono_join_uninterrupted (handle, ms, &error); + ret = mono_join_uninterrupted (handle, ms, &error); mono_thread_clr_state (cur_thread, ThreadState_WaitSleepJoin); mono_error_set_pending_exception (&error); - if(ret==MONO_THREAD_INFO_WAIT_RET_SUCCESS_0) { + if (ret == MONO_THREAD_INFO_WAIT_RET_SUCCESS_0) { THREAD_DEBUG (g_message ("%s: join successful", __func__)); - return(TRUE); +#ifdef HOST_WIN32 + /* TODO: Do this on Unix platforms as well. See PR #5454 for context. */ + /* Wait for the thread to really exit */ + MONO_ENTER_GC_SAFE; + /* This shouldn't block */ + mono_threads_join_lock (); + mono_native_thread_join (tid); + mono_threads_join_unlock (); + MONO_EXIT_GC_SAFE; +#endif + + return TRUE; } THREAD_DEBUG (g_message ("%s: join failed", __func__)); - return(FALSE); + return FALSE; } #define MANAGED_WAIT_FAILED 0x7fffffff @@ -3036,6 +3049,8 @@ mono_thread_callbacks_init (void) void mono_thread_cleanup (void) { + mono_threads_join_threads (); + #if !defined(RUN_IN_SUBTHREAD) && !defined(HOST_WIN32) /* The main thread must abandon any held mutexes (particularly * important for named mutexes as they are shared across @@ -5000,7 +5015,7 @@ mono_threads_add_joinable_thread (gpointer tid) if (!joinable_threads) joinable_threads = g_hash_table_new (NULL, NULL); g_hash_table_insert (joinable_threads, tid, tid); - joinable_thread_count ++; + UnlockedIncrement (&joinable_thread_count); joinable_threads_unlock (); mono_gc_finalize_notify (); @@ -5024,7 +5039,7 @@ mono_threads_join_threads (void) gboolean found; /* Fastpath */ - if (!joinable_thread_count) + if (!UnlockedRead (&joinable_thread_count)) return; while (TRUE) { @@ -5035,7 +5050,7 @@ mono_threads_join_threads (void) g_hash_table_iter_next (&iter, &key, (void**)&tid); thread = (pthread_t)tid; g_hash_table_remove (joinable_threads, key); - joinable_thread_count --; + UnlockedDecrement (&joinable_thread_count); found = TRUE; } joinable_threads_unlock (); @@ -5073,7 +5088,7 @@ mono_thread_join (gpointer tid) joinable_threads = g_hash_table_new (NULL, NULL); if (g_hash_table_lookup (joinable_threads, tid)) { g_hash_table_remove (joinable_threads, tid); - joinable_thread_count --; + UnlockedDecrement (&joinable_thread_count); found = TRUE; } joinable_threads_unlock ();