static void cleanup (void) { /* we make the assumption along the code that we are * cleaning up only if the runtime is shutting down */ g_assert (mono_runtime_is_shutting_down ()); selector_thread_wakeup (); while (io_selector_running) mono_thread_info_usleep (1000); }
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); }
/** * mono_threads_attach_tools_thread * * Attach the current thread as a tool thread. DON'T USE THIS FUNCTION WITHOUT READING ALL DISCLAIMERS. * * A tools thread is a very special kind of thread that needs access to core runtime facilities but should * not be counted as a regular thread for high order facilities such as executing managed code or accessing * the managed heap. * * This is intended only to tools such as a profiler than needs to be able to use our lock-free support when * doing things like resolving backtraces in their background processing thread. */ void mono_threads_attach_tools_thread (void) { int dummy = 0; MonoThreadInfo *info; /* Must only be called once */ g_assert (!mono_native_tls_get_value (thread_info_key)); while (!mono_threads_inited) { mono_thread_info_usleep (10); } info = mono_thread_info_attach (&dummy); g_assert (info); info->tools_thread = TRUE; }