#include <mono/utils/mono-lazy-init.h>
#include <mono/utils/mono-coop-mutex.h>
#include <mono/utils/mono-coop-semaphore.h>
+#include <mono/utils/mono-threads-coop.h>
#include <errno.h>
The GC has to acquire this lock before starting a STW to make sure
a runtime suspend won't make it wronly see a thread in a safepoint
when it is in fact not.
+
+This has to be a naked locking primitive, and not a coop aware one, as
+it needs to be usable when destroying thread_info_key, the TLS key for
+the current MonoThreadInfo. In this case, mono_thread_info_current_unchecked,
+(which is used inside MONO_ENTER_GC_SAFE), would return NULL, leading
+to an assertion error. We then simply switch state manually in
+mono_thread_info_suspend_lock_with_info.
*/
-static MonoCoopSem global_suspend_semaphore;
+static MonoSemType global_suspend_semaphore;
static size_t thread_info_size;
static MonoThreadInfoCallbacks threads_callbacks;
return info;
}
+static void
+mono_thread_info_suspend_lock_with_info (MonoThreadInfo *info);
+
static void
unregister_thread (void *arg)
{
- MonoThreadInfo *info = (MonoThreadInfo *) arg;
- int small_id = info->small_id;
+ gpointer gc_unsafe_stackdata;
+ MonoThreadInfo *info;
+ int small_id;
+
+ info = (MonoThreadInfo *) arg;
g_assert (info);
+ small_id = info->small_id;
+
+ /* We only enter the GC unsafe region, as when exiting this function, the thread
+ * will be detached, and the current MonoThreadInfo* will be destroyed. */
+ mono_threads_enter_gc_unsafe_region_unbalanced_with_info (info, &gc_unsafe_stackdata);
+
THREADS_DEBUG ("unregistering info %p\n", info);
mono_native_tls_set_value (thread_exited_key, GUINT_TO_POINTER (1));
if (threads_callbacks.thread_detach)
threads_callbacks.thread_detach (info);
- mono_thread_info_suspend_lock ();
+ mono_thread_info_suspend_lock_with_info (info);
/*
Now perform the callback that must be done under locks.
unified_suspend_enabled = g_getenv ("MONO_ENABLE_UNIFIED_SUSPEND") != NULL || mono_threads_is_coop_enabled ();
- mono_coop_sem_init (&global_suspend_semaphore, 1);
+ mono_os_sem_init (&global_suspend_semaphore, 1);
mono_os_sem_init (&suspend_semaphore, 0);
mono_lls_init (&thread_list, NULL, HAZARD_FREE_NO_LOCK);
A GC that has safepoints must take this lock as part of its
STW to make sure no unsafe pending suspend is in progress.
*/
+
+static void
+mono_thread_info_suspend_lock_with_info (MonoThreadInfo *info)
+{
+ g_assert (info);
+
+ MONO_ENTER_GC_SAFE_WITH_INFO(info);
+
+ int res = mono_os_sem_wait (&global_suspend_semaphore, MONO_SEM_FLAGS_NONE);
+ g_assert (res != -1);
+
+ MONO_EXIT_GC_SAFE_WITH_INFO;
+}
+
void
mono_thread_info_suspend_lock (void)
{
- int res = mono_coop_sem_wait (&global_suspend_semaphore, MONO_SEM_FLAGS_NONE);
- g_assert (res != -1);
+ mono_thread_info_suspend_lock_with_info (mono_thread_info_current_unchecked ());
}
void
mono_thread_info_suspend_unlock (void)
{
- mono_coop_sem_post (&global_suspend_semaphore);
+ mono_os_sem_post (&global_suspend_semaphore);
}
/*
if (alerted)
return sleep_interruptable (ms, alerted);
- MONO_PREPARE_BLOCKING;
+ MONO_ENTER_GC_SAFE;
if (ms == INFINITE) {
do {
#endif /* __linux__ */
}
- MONO_FINISH_BLOCKING;
+ MONO_EXIT_GC_SAFE;
return 0;
}
gint
mono_thread_info_usleep (guint64 us)
{
- MONO_PREPARE_BLOCKING;
+ MONO_ENTER_GC_SAFE;
g_usleep (us);
- MONO_FINISH_BLOCKING;
+ MONO_EXIT_GC_SAFE;
return 0;
}
return mono_threads_core_open_thread_handle (handle, tid);
}
-void
-mono_thread_info_set_name (MonoNativeThreadId tid, const char *name)
-{
- mono_threads_core_set_name (tid, name);
-}
-
#define INTERRUPT_STATE ((MonoThreadInfoInterruptToken*) (size_t) -1)
struct _MonoThreadInfoInterruptToken {
else
g_string_append_printf (text, "waiting");
}
+
+gboolean
+mono_thread_info_is_current (MonoThreadInfo *info)
+{
+ return mono_thread_info_get_tid (info) == mono_native_thread_id_get ();
+}