/* * This is a very specific function whose only purpose is to * break a given thread from socket syscalls. * * This only exists because linux won't fail a call to connect * if the underlying is closed. * * TODO We should cleanup and unify this with the other syscall abort * facility. */ void mono_thread_info_abort_socket_syscall_for_close (MonoNativeThreadId tid) { MonoThreadHazardPointers *hp; MonoThreadInfo *info; if (tid == mono_native_thread_id_get () || !mono_threads_core_needs_abort_syscall ()) return; hp = mono_hazard_pointer_get (); info = mono_thread_info_lookup (tid); if (!info) return; if (mono_thread_info_run_state (info) == STATE_DETACHED) { mono_hazard_pointer_clear (hp, 1); return; } mono_thread_info_suspend_lock (); mono_threads_begin_global_suspend (); mono_threads_core_abort_syscall (info); mono_threads_wait_pending_operations (); mono_hazard_pointer_clear (hp, 1); mono_threads_end_global_suspend (); mono_thread_info_suspend_unlock (); }
void mono_thread_info_safe_suspend_and_run (MonoNativeThreadId id, gboolean interrupt_kernel, MonoSuspendThreadCallback callback, gpointer user_data) { int result; MonoThreadInfo *info = NULL; MonoThreadHazardPointers *hp = mono_hazard_pointer_get (); THREADS_SUSPEND_DEBUG ("SUSPENDING tid %p\n", (void*)id); /*FIXME: unify this with self-suspend*/ g_assert (id != mono_native_thread_id_get ()); mono_thread_info_suspend_lock (); mono_threads_begin_global_suspend (); info = suspend_sync_nolock (id, interrupt_kernel); if (!info) goto done; switch (result = callback (info, user_data)) { case MonoResumeThread: mono_hazard_pointer_set (hp, 1, info); mono_thread_info_core_resume (info); mono_threads_wait_pending_operations (); break; case KeepSuspended: break; default: g_error ("Invalid suspend_and_run callback return value %d", result); } done: mono_hazard_pointer_clear (hp, 1); mono_threads_end_global_suspend (); mono_thread_info_suspend_unlock (); }
static void sgen_unified_suspend_restart_world (void) { THREADS_STW_DEBUG ("[GC-STW-END] *** BEGIN RESUME ***\n"); FOREACH_THREAD (info) { int reason = 0; if (sgen_is_thread_in_current_stw (info, &reason)) { g_assert (mono_thread_info_begin_resume (info)); THREADS_STW_DEBUG ("[GC-STW-RESUME-WORLD] RESUME thread %p\n", mono_thread_info_get_tid (info)); binary_protocol_thread_restart ((gpointer) mono_thread_info_get_tid (info)); } else { THREADS_STW_DEBUG ("[GC-STW-RESUME-WORLD] IGNORE thread %p, reason %d\n", mono_thread_info_get_tid (info), reason); } } FOREACH_THREAD_END mono_threads_wait_pending_operations (); mono_threads_end_global_suspend (); }
/* WARNING: If we are trying to suspend a target that is on a critical region and running a syscall we risk looping forever if @interrupt_kernel is FALSE. So, be VERY carefull in calling this with @interrupt_kernel == FALSE. Info is not put on a hazard pointer as a suspended thread cannot exit and be freed. This function MUST be matched with mono_thread_info_finish_suspend or mono_thread_info_finish_suspend_and_resume */ MonoThreadInfo* mono_thread_info_safe_suspend_sync (MonoNativeThreadId id, gboolean interrupt_kernel) { MonoThreadInfo *info = NULL; THREADS_SUSPEND_DEBUG ("SUSPENDING tid %p\n", (void*)id); /*FIXME: unify this with self-suspend*/ g_assert (id != mono_native_thread_id_get ()); mono_thread_info_suspend_lock (); mono_threads_begin_global_suspend (); info = suspend_sync_nolock (id, interrupt_kernel); /* XXX this clears HP 1, so we restated it again */ // mono_atomic_store_release (&mono_thread_info_current ()->inside_critical_region, TRUE); mono_threads_end_global_suspend (); mono_thread_info_suspend_unlock (); return info; }