void mono_threads_posix_init_signals (MonoThreadPosixInitSignals signals) { sigset_t signal_set; g_assert ((signals == MONO_THREADS_POSIX_INIT_SIGNALS_SUSPEND_RESTART) ^ (signals == MONO_THREADS_POSIX_INIT_SIGNALS_ABORT)); sigemptyset (&signal_set); switch (signals) { case MONO_THREADS_POSIX_INIT_SIGNALS_SUSPEND_RESTART: { if (mono_thread_info_unified_management_enabled ()) { suspend_signal_num = DEFAULT_SUSPEND_SIGNAL; restart_signal_num = DEFAULT_RESTART_SIGNAL; } else { suspend_signal_num = suspend_signal_get (); restart_signal_num = restart_signal_get (); } sigfillset (&suspend_signal_mask); sigdelset (&suspend_signal_mask, restart_signal_num); if (!mono_thread_info_unified_management_enabled ()) sigdelset (&suspend_signal_mask, mono_gc_get_suspend_signal ()); sigemptyset (&suspend_ack_signal_mask); sigaddset (&suspend_ack_signal_mask, restart_signal_num); signal_add_handler (suspend_signal_num, suspend_signal_handler, SA_RESTART); signal_add_handler (restart_signal_num, restart_signal_handler, SA_RESTART); sigaddset (&signal_set, suspend_signal_num); sigaddset (&signal_set, restart_signal_num); break; } case MONO_THREADS_POSIX_INIT_SIGNALS_ABORT: { abort_signal_num = abort_signal_get (); signal_add_handler (abort_signal_num, abort_signal_handler, 0); sigaddset (&signal_set, abort_signal_num); break; } default: g_assert_not_reached (); } /* ensure all the new signals are unblocked */ sigprocmask (SIG_UNBLOCK, &signal_set, NULL); }
void mono_threads_init_platform (void) { sigset_t signal_set; abort_signal_num = mono_threads_get_abort_signal (); if (mono_thread_info_unified_management_enabled ()) { suspend_signal_num = DEFAULT_SUSPEND_SIGNAL; restart_signal_num = DEFAULT_RESTART_SIGNAL; } else { suspend_signal_num = mono_thread_get_alt_suspend_signal (); restart_signal_num = mono_thread_get_alt_resume_signal (); } sigfillset (&suspend_signal_mask); sigdelset (&suspend_signal_mask, restart_signal_num); sigemptyset (&suspend_ack_signal_mask); sigaddset (&suspend_ack_signal_mask, restart_signal_num); mono_posix_add_signal_handler (suspend_signal_num, suspend_signal_handler, SA_RESTART); mono_posix_add_signal_handler (restart_signal_num, restart_signal_handler, SA_RESTART); mono_posix_add_signal_handler (abort_signal_num, abort_signal_handler, 0); /* ensure all the new signals are unblocked */ sigemptyset (&signal_set); sigaddset (&signal_set, suspend_signal_num); sigaddset (&signal_set, restart_signal_num); sigaddset (&signal_set, abort_signal_num); sigprocmask (SIG_UNBLOCK, &signal_set, NULL); }
void sgen_os_init (void) { struct sigaction sinfo; if (mono_thread_info_unified_management_enabled ()) return; suspend_ack_semaphore_ptr = &suspend_ack_semaphore; SGEN_SEMAPHORE_INIT (&suspend_ack_semaphore, 0); sigfillset (&sinfo.sa_mask); sinfo.sa_flags = SA_RESTART | SA_SIGINFO; sinfo.sa_sigaction = suspend_handler; if (sigaction (suspend_signal_num, &sinfo, NULL) != 0) { g_error ("failed sigaction"); } sinfo.sa_handler = (void (*)(int))restart_handler; if (sigaction (restart_signal_num, &sinfo, NULL) != 0) { g_error ("failed sigaction"); } sigfillset (&suspend_signal_mask); sigdelset (&suspend_signal_mask, restart_signal_num); sigemptyset (&suspend_ack_signal_mask); sigaddset (&suspend_ack_signal_mask, restart_signal_num); }
/* LOCKING: assumes the GC lock is held */ void sgen_client_restart_world (int generation, gint64 *stw_time) { TV_DECLARE (end_sw); TV_DECLARE (start_handshake); unsigned long usec; /* notify the profiler of the leftovers */ /* FIXME this is the wrong spot at we can STW for non collection reasons. */ if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_GC_MOVES)) mono_sgen_gc_event_moves (); FOREACH_THREAD (info) { info->client_info.stack_start = NULL; memset (&info->client_info.ctx, 0, sizeof (MonoContext)); } FOREACH_THREAD_END TV_GETTIME (start_handshake); if (mono_thread_info_unified_management_enabled ()) sgen_unified_suspend_restart_world (); else sgen_thread_handshake (FALSE); TV_GETTIME (end_sw); time_restart_world += TV_ELAPSED (start_handshake, end_sw); usec = TV_ELAPSED (stop_world_time, end_sw); max_pause_usec = MAX (usec, max_pause_usec); end_of_last_stw = end_sw; SGEN_LOG (2, "restarted (pause time: %d usec, max: %d)", (int)usec, (int)max_pause_usec); /* * We must release the thread info suspend lock after doing * the thread handshake. Otherwise, if the GC stops the world * and a thread is in the process of starting up, but has not * yet registered (it's not in the thread_list), it is * possible that the thread does register while the world is * stopped. When restarting the GC will then try to restart * said thread, but since it never got the suspend signal, it * cannot answer the restart signal, so a deadlock results. */ release_gc_locks (); mono_profiler_gc_event (MONO_GC_EVENT_POST_START_WORLD_UNLOCKED, generation); *stw_time = usec; }
/* LOCKING: assumes the GC lock is held */ void sgen_client_stop_world (int generation) { TV_DECLARE (end_handshake); /* notify the profiler of the leftovers */ /* FIXME this is the wrong spot at we can STW for non collection reasons. */ if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_GC_MOVES)) mono_sgen_gc_event_moves (); acquire_gc_locks (); mono_profiler_gc_event (MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED, generation); /* We start to scan after locks are taking, this ensures we won't be interrupted. */ sgen_process_togglerefs (); update_current_thread_stack (&generation); sgen_global_stop_count++; SGEN_LOG (3, "stopping world n %d from %p %p", sgen_global_stop_count, mono_thread_info_current (), (gpointer) (gsize) mono_native_thread_id_get ()); TV_GETTIME (stop_world_time); if (mono_thread_info_unified_management_enabled ()) { sgen_unified_suspend_stop_world (); } else { int count, dead; count = sgen_thread_handshake (TRUE); dead = restart_threads_until_none_in_managed_allocator (); if (count < dead) g_error ("More threads have died (%d) that been initialy suspended %d", dead, count); } SGEN_LOG (3, "world stopped"); TV_GETTIME (end_handshake); time_stop_world += TV_ELAPSED (stop_world_time, end_handshake); sgen_memgov_collection_start (generation); if (sgen_need_bridge_processing ()) sgen_bridge_reset_data (); }