int
mono_gc_pthread_create (pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
{
- return pthread_create (new_thread, attr, start_routine, arg);
+ int res;
+
+ mono_threads_join_lock ();
+ res = pthread_create (new_thread, attr, start_routine, arg);
+ mono_threads_join_unlock ();
+
+ return res;
}
#endif
if (thread != pthread_self ()) {
MONO_ENTER_GC_SAFE;
/* This shouldn't block */
+ mono_threads_join_lock ();
mono_native_thread_join (thread);
+ mono_threads_join_unlock ();
MONO_EXIT_GC_SAFE;
}
} else {
static MonoSemType suspend_semaphore;
static size_t pending_suspends;
+static mono_mutex_t join_mutex;
+
#define mono_thread_info_run_state(info) (((MonoThreadInfo*)info)->thread_state & THREAD_STATE_MASK)
/*warn at 50 ms*/
mono_os_sem_init (&global_suspend_semaphore, 1);
mono_os_sem_init (&suspend_semaphore, 0);
+ mono_os_mutex_init (&join_mutex);
mono_lls_init (&thread_list, NULL);
mono_thread_smr_init ();
{
return mono_threads_platform_yield ();
}
+
static mono_lazy_init_t sleep_init = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
static MonoCoopMutex sleep_mutex;
static MonoCoopCond sleep_cond;
else
g_error ("%s: unknown res value %d", __func__, res);
}
+
+/*
+ * mono_threads_join_mutex:
+ *
+ * This mutex is used to avoid races between pthread_create () and pthread_join () on osx, see
+ * https://bugzilla.xamarin.com/show_bug.cgi?id=50529
+ * The code inside the lock should not block.
+ */
+void
+mono_threads_join_lock (void)
+{
+#ifdef TARGET_OSX
+ mono_os_mutex_lock (&join_mutex);
+#endif
+}
+
+void
+mono_threads_join_unlock (void)
+{
+#ifdef TARGET_OSX
+ mono_os_mutex_unlock (&join_mutex);
+#endif
+}
MonoThreadInfoWaitRet
mono_thread_info_wait_multiple_handle (MonoThreadHandle **thread_handles, gsize nhandles, MonoOSEvent *background_change_event, gboolean waitall, guint32 timeout, gboolean alertable);
+void mono_threads_join_lock (void);
+void mono_threads_join_unlock (void);
+
#endif /* __MONO_THREADS_H__ */