+static void
+collect_threads (gpointer key, gpointer value, gpointer user_data)
+{
+ MonoThread *thread = (MonoThread*)value;
+ struct wait_data *wait = (struct wait_data*)user_data;
+ HANDLE handle;
+
+ if (wait->num<MAXIMUM_WAIT_OBJECTS) {
+ handle = OpenThread (THREAD_ALL_ACCESS, TRUE, thread->tid);
+ if (handle == NULL)
+ return;
+
+ wait->handles [wait->num] = handle;
+ wait->threads [wait->num] = thread;
+ wait->num++;
+ }
+}
+
+/*
+ * mono_thread_suspend_all_other_threads:
+ *
+ * Suspend all managed threads except the finalizer thread and this thread.
+ */
+void mono_thread_suspend_all_other_threads (void)
+{
+ struct wait_data *wait = g_new0 (struct wait_data, 1);
+ int i, waitnum;
+ gsize self = GetCurrentThreadId ();
+ gpointer *events;
+ guint32 eventidx = 0;
+
+ /*
+ * Make a copy of the hashtable since we can't do anything with
+ * threads while threads_mutex is held.
+ */
+ EnterCriticalSection (&threads_mutex);
+ mono_g_hash_table_foreach (threads, collect_threads, wait);
+ LeaveCriticalSection (&threads_mutex);
+
+ events = g_new0 (gpointer, wait->num);
+ waitnum = 0;
+ /* Get the suspended events that we'll be waiting for */
+ for (i = 0; i < wait->num; ++i) {
+ MonoThread *thread = wait->threads [i];
+
+ if ((thread->tid == self) || mono_gc_is_finalizer_thread (thread)) {
+ //CloseHandle (wait->handles [i]);
+ wait->threads [i] = NULL; /* ignore this thread in next loop */
+ continue;
+ }
+
+ mono_monitor_enter (thread->synch_lock);
+
+ if ((thread->state & ThreadState_Suspended) != 0 ||
+ (thread->state & ThreadState_SuspendRequested) != 0 ||
+ (thread->state & ThreadState_StopRequested) != 0 ||
+ (thread->state & ThreadState_Stopped) != 0) {
+ mono_monitor_exit (thread->synch_lock);
+ CloseHandle (wait->handles [i]);
+ wait->threads [i] = NULL; /* ignore this thread in next loop */
+ continue;
+ }
+
+ /* Convert abort requests into suspend requests */
+ if ((thread->state & ThreadState_AbortRequested) != 0)
+ thread->state &= ~ThreadState_AbortRequested;
+
+ thread->state |= ThreadState_SuspendRequested;
+
+ if (thread->suspended_event == NULL)
+ thread->suspended_event = CreateEvent (NULL, TRUE, FALSE, NULL);
+
+ events [eventidx++] = thread->suspended_event;
+ mono_monitor_exit (thread->synch_lock);
+
+ /* Signal the thread to suspend */
+ signal_thread_state_change (thread);
+ }
+
+ WaitForMultipleObjectsEx (eventidx, events, TRUE, INFINITE, FALSE);
+ for (i = 0; i < wait->num; ++i) {
+ MonoThread *thread = wait->threads [i];
+
+ if (thread == NULL)
+ continue;
+
+ mono_monitor_enter (thread->synch_lock);
+ CloseHandle (thread->suspended_event);
+ thread->suspended_event = NULL;
+ mono_monitor_exit (thread->synch_lock);
+ }
+
+ g_free (events);
+ g_free (wait);
+}
+