static void sleep_interrupt (gpointer data) { mono_coop_mutex_lock (&sleep_mutex); mono_coop_cond_broadcast (&sleep_cond); mono_coop_mutex_unlock (&sleep_mutex); }
void ves_icall_System_IOSelector_Add (gpointer handle, MonoIOSelectorJob *job) { ThreadPoolIOUpdate *update; g_assert (handle >= 0); g_assert ((job->operation == EVENT_IN) ^ (job->operation == EVENT_OUT)); g_assert (job->callback); if (mono_runtime_is_shutting_down ()) return; if (mono_domain_is_unloading (mono_object_domain (job))) return; mono_lazy_initialize (&io_status, initialize); mono_coop_mutex_lock (&threadpool_io->updates_lock); update = update_get_new (); update->type = UPDATE_ADD; update->data.add.fd = GPOINTER_TO_INT (handle); update->data.add.job = job; mono_memory_barrier (); /* Ensure this is safely published before we wake up the selector */ selector_thread_wakeup (); mono_coop_mutex_unlock (&threadpool_io->updates_lock); }
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; }
static inline void break_coop_alertable_wait (gpointer user_data) { BreakCoopAlertableWaitUD *ud = (BreakCoopAlertableWaitUD*)user_data; mono_coop_mutex_lock (ud->mutex); mono_coop_cond_signal (ud->cond); mono_coop_mutex_unlock (ud->mutex); g_free (ud); }
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); }
static void named_regions_unlock (void) { mono_coop_mutex_unlock (&named_regions_mutex); }
void mono_w32handle_namespace_unlock (void) { mono_coop_mutex_unlock (&lock); }
static void selector_thread (gpointer data) { MonoError error; MonoGHashTable *states; io_selector_running = TRUE; if (mono_runtime_is_shutting_down ()) { io_selector_running = FALSE; return; } states = mono_g_hash_table_new_type (g_direct_hash, g_direct_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_THREAD_POOL, "i/o thread pool states table"); for (;;) { gint i, j; gint res; mono_coop_mutex_lock (&threadpool_io->updates_lock); for (i = 0; i < threadpool_io->updates_size; ++i) { ThreadPoolIOUpdate *update = &threadpool_io->updates [i]; switch (update->type) { case UPDATE_EMPTY: break; case UPDATE_ADD: { gint fd; gint operations; gpointer k; gboolean exists; MonoMList *list = NULL; MonoIOSelectorJob *job; fd = update->data.add.fd; g_assert (fd >= 0); job = update->data.add.job; g_assert (job); exists = mono_g_hash_table_lookup_extended (states, GINT_TO_POINTER (fd), &k, (gpointer*) &list); list = mono_mlist_append_checked (list, (MonoObject*) job, &error); mono_error_assert_ok (&error); mono_g_hash_table_replace (states, GINT_TO_POINTER (fd), list); operations = get_operations_for_jobs (list); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_THREADPOOL, "io threadpool: %3s fd %3d, operations = %2s | %2s | %3s", exists ? "mod" : "add", fd, (operations & EVENT_IN) ? "RD" : "..", (operations & EVENT_OUT) ? "WR" : "..", (operations & EVENT_ERR) ? "ERR" : "..."); threadpool_io->backend.register_fd (fd, operations, !exists); break; } case UPDATE_REMOVE_SOCKET: { gint fd; gpointer k; MonoMList *list = NULL; fd = update->data.remove_socket.fd; g_assert (fd >= 0); if (mono_g_hash_table_lookup_extended (states, GINT_TO_POINTER (fd), &k, (gpointer*) &list)) { mono_g_hash_table_remove (states, GINT_TO_POINTER (fd)); for (j = i + 1; j < threadpool_io->updates_size; ++j) { ThreadPoolIOUpdate *update = &threadpool_io->updates [j]; if (update->type == UPDATE_ADD && update->data.add.fd == fd) memset (update, 0, sizeof (ThreadPoolIOUpdate)); } for (; list; list = mono_mlist_remove_item (list, list)) { mono_threadpool_ms_enqueue_work_item (mono_object_domain (mono_mlist_get_data (list)), mono_mlist_get_data (list), &error); mono_error_assert_ok (&error); } mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_THREADPOOL, "io threadpool: del fd %3d", fd); threadpool_io->backend.remove_fd (fd); } break; } case UPDATE_REMOVE_DOMAIN: { MonoDomain *domain; domain = update->data.remove_domain.domain; g_assert (domain); FilterSockaresForDomainData user_data = { .domain = domain, .states = states }; mono_g_hash_table_foreach (states, filter_jobs_for_domain, &user_data); for (j = i + 1; j < threadpool_io->updates_size; ++j) { ThreadPoolIOUpdate *update = &threadpool_io->updates [j]; if (update->type == UPDATE_ADD && mono_object_domain (update->data.add.job) == domain) memset (update, 0, sizeof (ThreadPoolIOUpdate)); } break; } default: g_assert_not_reached (); } } mono_coop_cond_broadcast (&threadpool_io->updates_cond); if (threadpool_io->updates_size > 0) { threadpool_io->updates_size = 0; memset (&threadpool_io->updates, 0, UPDATES_CAPACITY * sizeof (ThreadPoolIOUpdate)); } mono_coop_mutex_unlock (&threadpool_io->updates_lock); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_THREADPOOL, "io threadpool: wai"); res = threadpool_io->backend.event_wait (wait_callback, states); if (res == -1 || mono_runtime_is_shutting_down ()) break; } mono_g_hash_table_destroy (states); io_selector_running = FALSE; }