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); }
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); } }
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); }
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; }