Esempio n. 1
0
/*
 * coop_cond_timedwait_alertable:
 *
 *   Wait on COND/MUTEX. If ALERTABLE is non-null, the wait can be interrupted.
 * In that case, *ALERTABLE will be set to TRUE, and 0 is returned.
 */
static inline gint
coop_cond_timedwait_alertable (MonoCoopCond *cond, MonoCoopMutex *mutex, guint32 timeout_ms, gboolean *alertable)
{
	BreakCoopAlertableWaitUD *ud;
	int res;

	if (alertable) {
		ud = g_new0 (BreakCoopAlertableWaitUD, 1);
		ud->cond = cond;
		ud->mutex = mutex;

		mono_thread_info_install_interrupt (break_coop_alertable_wait, ud, alertable);
		if (*alertable) {
			g_free (ud);
			return 0;
		}
	}
	res = mono_coop_cond_timedwait (cond, mutex, timeout_ms);
	if (alertable) {
		mono_thread_info_uninstall_interrupt (alertable);
		if (*alertable)
			return 0;
		else {
			/* the interrupt token has not been taken by another
			 * thread, so it's our responsability to free it up. */
			g_free (ud);
		}
	}
	return res;
}
Esempio n. 2
0
static inline guint32
sleep_interruptable (guint32 ms, gboolean *alerted)
{
	guint32 start, now, end;

	g_assert (INFINITE == G_MAXUINT32);

	g_assert (alerted);
	*alerted = FALSE;

	start = mono_msec_ticks ();

	if (start < G_MAXUINT32 - ms) {
		end = start + ms;
	} else {
		/* start + ms would overflow guint32 */
		end = G_MAXUINT32;
	}

	mono_lazy_initialize (&sleep_init, sleep_initialize);

	mono_coop_mutex_lock (&sleep_mutex);

	for (now = mono_msec_ticks (); ms == INFINITE || now - start < ms; now = mono_msec_ticks ()) {
		mono_thread_info_install_interrupt (sleep_interrupt, NULL, alerted);
		if (*alerted) {
			mono_coop_mutex_unlock (&sleep_mutex);
			return WAIT_IO_COMPLETION;
		}

		if (ms < INFINITE)
			mono_coop_cond_timedwait (&sleep_cond, &sleep_mutex, end - now);
		else
			mono_coop_cond_wait (&sleep_cond, &sleep_mutex);

		mono_thread_info_uninstall_interrupt (alerted);
		if (*alerted) {
			mono_coop_mutex_unlock (&sleep_mutex);
			return WAIT_IO_COMPLETION;
		}
	}

	mono_coop_mutex_unlock (&sleep_mutex);

	return 0;
}
Esempio n. 3
0
static inline guint32
sleep_interruptable (guint32 ms, gboolean *alerted)
{
	gint64 now, end;

	g_assert (INFINITE == G_MAXUINT32);

	g_assert (alerted);
	*alerted = FALSE;

	if (ms != INFINITE)
		end = mono_100ns_ticks () + (ms * 1000 * 10);

	mono_lazy_initialize (&sleep_init, sleep_initialize);

	mono_coop_mutex_lock (&sleep_mutex);

	for (;;) {
		if (ms != INFINITE) {
			now = mono_100ns_ticks ();
			if (now > end)
				break;
		}

		mono_thread_info_install_interrupt (sleep_interrupt, NULL, alerted);
		if (*alerted) {
			mono_coop_mutex_unlock (&sleep_mutex);
			return WAIT_IO_COMPLETION;
		}

		if (ms != INFINITE)
			mono_coop_cond_timedwait (&sleep_cond, &sleep_mutex, (end - now) / 10 / 1000);
		else
			mono_coop_cond_wait (&sleep_cond, &sleep_mutex);

		mono_thread_info_uninstall_interrupt (alerted);
		if (*alerted) {
			mono_coop_mutex_unlock (&sleep_mutex);
			return WAIT_IO_COMPLETION;
		}
	}

	mono_coop_mutex_unlock (&sleep_mutex);

	return 0;
}
Esempio n. 4
0
/*
 * ves_icall_System_IO_KqueueMonitor_kevent_notimeout:
 *
 *   Call kevent (), while handling runtime interruptions.
 */
int
ves_icall_System_IO_KqueueMonitor_kevent_notimeout (int *kq_ptr, gpointer changelist, int nchanges, gpointer eventlist, int nevents)
{
	int res;
	gboolean interrupted;

	mono_thread_info_install_interrupt (interrupt_kevent, kq_ptr, &interrupted);
	if (interrupted) {
		close (*kq_ptr);
		*kq_ptr = -1;
		return -1;
	}

	MONO_ENTER_GC_SAFE;
	res = kevent (*kq_ptr, changelist, nchanges, eventlist, nevents, NULL);
	MONO_EXIT_GC_SAFE;

	mono_thread_info_uninstall_interrupt (&interrupted);

	return res;
}
Esempio n. 5
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;
}