gpointer mono_threads_enter_gc_unsafe_region_with_info (THREAD_INFO_TYPE *info, gpointer *stackdata) { gpointer cookie; if (!mono_threads_is_coop_enabled ()) return NULL; cookie = mono_threads_enter_gc_unsafe_region_unbalanced_with_info (info, stackdata); #ifdef ENABLE_CHECKED_BUILD_GC if (mono_check_mode_enabled (MONO_CHECK_MODE_GC)) coop_tls_push (cookie); #endif return cookie; }
gpointer mono_threads_enter_gc_unsafe_region_unbalanced (gpointer *stackdata) { return mono_threads_enter_gc_unsafe_region_unbalanced_with_info (mono_thread_info_current_unchecked (), stackdata); }
static void unregister_thread (void *arg) { gpointer gc_unsafe_stackdata; MonoThreadInfo *info; int small_id; info = (MonoThreadInfo *) arg; g_assert (info); g_assert (mono_thread_info_is_current (info)); g_assert (mono_thread_info_is_live (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)); mono_threads_platform_unregister (info); /* * TLS destruction order is not reliable so small_id might be cleaned up * before us. */ #ifndef HAVE_KW_THREAD mono_native_tls_set_value (small_id_key, GUINT_TO_POINTER (info->small_id + 1)); #endif /* First perform the callback that requires no locks. This callback has the potential of taking other locks, so we do it before. After it completes, the thread remains functional. */ if (threads_callbacks.thread_detach) threads_callbacks.thread_detach (info); mono_thread_info_suspend_lock_with_info (info); /* Now perform the callback that must be done under locks. This will render the thread useless and non-suspendable, so it must be done while holding the suspend lock to give no other thread chance to suspend it. */ if (threads_callbacks.thread_unregister) threads_callbacks.thread_unregister (info); mono_threads_unregister_current_thread (info); mono_threads_transition_detach (info); mono_thread_info_suspend_unlock (); g_byte_array_free (info->stackdata, /*free_segment=*/TRUE); /*now it's safe to free the thread info.*/ mono_thread_hazardous_try_free (info, free_thread_info); /* Pump the HP queue */ mono_thread_hazardous_try_free_some (); mono_thread_small_id_free (small_id); }