+
+#ifdef HAVE_CLOCK_NANOSLEEP
+ /*
+ * 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.
+ *
+ * We do not need to do this on platforms where we use a regular sleep
+ * based on a monotonic clock. The sleep will return in a reasonable amount
+ * of time in those cases.
+ */
+ if (mono_profiler_get_sampling_mode () == MONO_PROFILER_STAT_MODE_PROCESS) {
+ MonoThreadInfo *info;
+
+ // Did it shut down already?
+ if ((info = mono_thread_info_lookup (sampling_thread))) {
+ while (!InterlockedRead (&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
+