Esempio n. 1
0
static void
thread_handle_destroy (gpointer data)
{
	MonoThreadHandle *thread_handle;

	thread_handle = (MonoThreadHandle*) data;

	mono_os_event_destroy (&thread_handle->event);
	g_free (thread_handle);
}
Esempio n. 2
0
static void
signal_and_unref (gpointer user_data)
{
	OSEventWaitData *data;

	data = (OSEventWaitData*) user_data;

	mono_os_event_set (&data->event);
	if (InterlockedDecrement ((gint32*) &data->ref) == 0) {
		mono_os_event_destroy (&data->event);
		g_free (data);
	}
}
Esempio n. 3
0
void
mono_runtime_shutdown_stat_profiler (void)
{
	mono_atomic_store_i32 (&sampling_thread_running, 0);

	mono_profiler_sampling_thread_post ();

#ifndef HOST_DARWIN
	/*
	 * There is a slight problem when we're using CLOCK_PROCESS_CPUTIME_ID: If
	 * we're shutting down and there's largely no activity in the process other
	 * than waiting for the sampler thread to shut down, it can take upwards of
	 * 20 seconds (depending on a lot of factors) for us to shut down because
	 * the sleep progresses very slowly as a result of the low CPU activity.
	 *
	 * We fix this by repeatedly sending the profiler signal to the sampler
	 * thread in order to interrupt the sleep. clock_sleep_ns_abs () will check
	 * sampling_thread_running upon an interrupt and return immediately if it's
	 * zero. profiler_signal_handler () has a special case to ignore the signal
	 * for the sampler thread.
	 */
	MonoThreadInfo *info;

	// Did it shut down already?
	if ((info = mono_thread_info_lookup (sampling_thread))) {
		while (!mono_atomic_load_i32 (&sampling_thread_exiting)) {
			mono_threads_pthread_kill (info, profiler_signal);
			mono_thread_info_usleep (10 * 1000 /* 10ms */);
		}

		// Make sure info can be freed.
		mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1);
	}
#endif

	mono_os_event_wait_one (&sampling_thread_exited, MONO_INFINITE_WAIT, FALSE);
	mono_os_event_destroy (&sampling_thread_exited);

	/*
	 * We can't safely remove the signal handler because we have no guarantee
	 * that all pending signals have been delivered at this point. This should
	 * not really be a problem anyway.
	 */
	//remove_signal_handler (profiler_signal);
}
Esempio n. 4
0
MonoOSEventWaitRet
mono_os_event_wait_multiple (MonoOSEvent **events, gsize nevents, gboolean waitall, guint32 timeout, gboolean alertable)
{
	MonoOSEventWaitRet ret;
	mono_cond_t signal_cond;
	OSEventWaitData *data;
	gboolean alerted;
	gint64 start;
	gint i;

	g_assert (mono_lazy_is_initialized (&status));

	g_assert (events);
	g_assert (nevents > 0);
	g_assert (nevents <= MONO_OS_EVENT_WAIT_MAXIMUM_OBJECTS);

	for (i = 0; i < nevents; ++i)
		g_assert (events [i]);

	if (alertable) {
		data = g_new0 (OSEventWaitData, 1);
		data->ref = 2;
		mono_os_event_init (&data->event, FALSE);

		alerted = FALSE;
		mono_thread_info_install_interrupt (signal_and_unref, data, &alerted);
		if (alerted) {
			mono_os_event_destroy (&data->event);
			g_free (data);
			return MONO_OS_EVENT_WAIT_RET_ALERTED;
		}
	}

	if (timeout != MONO_INFINITE_WAIT)
		start = mono_msec_ticks ();

	mono_os_cond_init (&signal_cond);

	mono_os_mutex_lock (&signal_mutex);

	for (i = 0; i < nevents; ++i)
		g_ptr_array_add (events [i]->conds, &signal_cond);

	if (alertable)
		g_ptr_array_add (data->event.conds, &signal_cond);

	for (;;) {
		gint count, lowest;
		gboolean signalled;

		count = 0;
		lowest = -1;

		for (i = 0; i < nevents; ++i) {
			if (mono_os_event_is_signalled (events [i])) {
				count += 1;
				if (lowest == -1)
					lowest = i;
			}
		}

		if (alertable && mono_os_event_is_signalled (&data->event))
			signalled = TRUE;
		else if (waitall)
			signalled = (count == nevents);
		else /* waitany */
			signalled = (count > 0);

		if (signalled) {
			ret = MONO_OS_EVENT_WAIT_RET_SUCCESS_0 + lowest;
			goto done;
		}

		if (timeout == MONO_INFINITE_WAIT) {
			mono_os_cond_wait (&signal_cond, &signal_mutex);
		} else {
			gint64 elapsed;
			gint res;

			elapsed = mono_msec_ticks () - start;
			if (elapsed >= timeout) {
				ret = MONO_OS_EVENT_WAIT_RET_TIMEOUT;
				goto done;
			}

			res = mono_os_cond_timedwait (&signal_cond, &signal_mutex, timeout - elapsed);
			if (res != 0) {
				ret = MONO_OS_EVENT_WAIT_RET_TIMEOUT;
				goto done;
			}
		}
	}

done:
	for (i = 0; i < nevents; ++i)
		g_ptr_array_remove (events [i]->conds, &signal_cond);

	if (alertable)
		g_ptr_array_remove (data->event.conds, &signal_cond);

	mono_os_mutex_unlock (&signal_mutex);

	mono_os_cond_destroy (&signal_cond);

	if (alertable) {
		mono_thread_info_uninstall_interrupt (&alerted);
		if (alerted) {
			if (InterlockedDecrement ((gint32*) &data->ref) == 0) {
				mono_os_event_destroy (&data->event);
				g_free (data);
			}
			return MONO_OS_EVENT_WAIT_RET_ALERTED;
		}

		mono_os_event_destroy (&data->event);
		g_free (data);
	}

	return ret;
}