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);
}
Exemple #2
0
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);
	
}
Exemple #4
0
/* 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;
}
Exemple #5
0
/* 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 ();
}