+static MonoException* mono_thread_execute_interruption (MonoThread *thread);
+
+/**
+ * mono_threads_set_shutting_down:
+ *
+ * Is called by a thread that wants to shut down Mono. If the runtime is already
+ * shutting down, the calling thread is suspended/stopped, and this function never
+ * returns.
+ */
+void
+mono_threads_set_shutting_down (void)
+{
+ MonoThread *current_thread = mono_thread_current ();
+
+ mono_threads_lock ();
+
+ if (shutting_down) {
+ mono_threads_unlock ();
+
+ /* Make sure we're properly suspended/stopped */
+
+ EnterCriticalSection (current_thread->synch_cs);
+
+ if ((current_thread->state & ThreadState_SuspendRequested) ||
+ (current_thread->state & ThreadState_AbortRequested) ||
+ (current_thread->state & ThreadState_StopRequested)) {
+ LeaveCriticalSection (current_thread->synch_cs);
+ mono_thread_execute_interruption (current_thread);
+ } else {
+ current_thread->state |= ThreadState_Stopped;
+ LeaveCriticalSection (current_thread->synch_cs);
+ }
+
+ /* Wake up other threads potentially waiting for us */
+ ExitThread (0);
+ } else {
+ shutting_down = TRUE;
+
+ /* Not really a background state change, but this will
+ * interrupt the main thread if it is waiting for all
+ * the other threads.
+ */
+ SetEvent (background_change_event);
+
+ mono_threads_unlock ();
+ }
+}
+
+/**
+ * mono_threads_is_shutting_down:
+ *
+ * Returns whether a thread has commenced shutdown of Mono. Note that
+ * if the function returns FALSE the caller must not assume that
+ * shutdown is not in progress, because the situation might have
+ * changed since the function returned. For that reason this function
+ * is of very limited utility.
+ */
+gboolean
+mono_threads_is_shutting_down (void)
+{
+ return shutting_down;
+}
+