/* * 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; }
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; }
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; }