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; }
/* Locking: threadpool_io->updates_lock must be held */ static ThreadPoolIOUpdate* update_get_new (void) { ThreadPoolIOUpdate *update = NULL; g_assert (threadpool_io->updates_size <= UPDATES_CAPACITY); while (threadpool_io->updates_size == UPDATES_CAPACITY) { /* we wait for updates to be applied in the selector_thread and we loop * as long as none are available. if it happends too much, then we need * to increase UPDATES_CAPACITY */ mono_coop_cond_wait (&threadpool_io->updates_cond, &threadpool_io->updates_lock); } g_assert (threadpool_io->updates_size < UPDATES_CAPACITY); update = &threadpool_io->updates [threadpool_io->updates_size ++]; return update; }
void mono_threadpool_ms_io_remove_domain_jobs (MonoDomain *domain) { ThreadPoolIOUpdate *update; if (!mono_lazy_is_initialized (&io_status)) return; mono_coop_mutex_lock (&threadpool_io->updates_lock); update = update_get_new (); update->type = UPDATE_REMOVE_DOMAIN; update->data.remove_domain.domain = domain; mono_memory_barrier (); /* Ensure this is safely published before we wake up the selector */ selector_thread_wakeup (); mono_coop_cond_wait (&threadpool_io->updates_cond, &threadpool_io->updates_lock); mono_coop_mutex_unlock (&threadpool_io->updates_lock); }
void mono_threadpool_ms_io_remove_socket (int fd) { ThreadPoolIOUpdate *update; if (!mono_lazy_is_initialized (&io_status)) return; mono_coop_mutex_lock (&threadpool_io->updates_lock); update = update_get_new (); update->type = UPDATE_REMOVE_SOCKET; update->data.add.fd = fd; mono_memory_barrier (); /* Ensure this is safely published before we wake up the selector */ selector_thread_wakeup (); mono_coop_cond_wait (&threadpool_io->updates_cond, &threadpool_io->updates_lock); mono_coop_mutex_unlock (&threadpool_io->updates_lock); }