+bool MachineThreads::tryCopyOtherThreadStacks(MutexLocker&, void* buffer, size_t capacity, size_t* size)
+{
+ // Prevent two VMs from suspending each other's threads at the same time,
+ // which can cause deadlock: <rdar://problem/20300842>.
+ static StaticSpinLock mutex;
+ std::lock_guard<StaticSpinLock> lock(mutex);
+
+ *size = 0;
+
+ PlatformThread currentPlatformThread = getCurrentPlatformThread();
+ int numberOfThreads = 0; // Using 0 to denote that we haven't counted the number of threads yet.
+ int index = 1;
+ Thread* threadsToBeDeleted = nullptr;
+
+ Thread* previousThread = nullptr;
+ for (Thread* thread = m_registeredThreads; thread; index++) {
+ if (*thread != currentPlatformThread) {
+ bool success = thread->suspend();
+#if OS(DARWIN)
+ if (!success) {
+ if (!numberOfThreads) {
+ for (Thread* countedThread = m_registeredThreads; countedThread; countedThread = countedThread->next)
+ numberOfThreads++;
+ }
+
+ // Re-do the suspension to get the actual failure result for logging.
+ kern_return_t error = thread_suspend(thread->platformThread);
+ ASSERT(error != KERN_SUCCESS);
+
+ WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION,
+ "JavaScript garbage collection encountered an invalid thread (err 0x%x): Thread [%d/%d: %p] platformThread %p.",
+ error, index, numberOfThreads, thread, reinterpret_cast<void*>(thread->platformThread));
+
+ // Put the invalid thread on the threadsToBeDeleted list.
+ // We can't just delete it here because we have suspended other
+ // threads, and they may still be holding the C heap lock which
+ // we need for deleting the invalid thread. Hence, we need to
+ // defer the deletion till after we have resumed all threads.
+ Thread* nextThread = thread->next;
+ thread->next = threadsToBeDeleted;
+ threadsToBeDeleted = thread;
+
+ if (previousThread)
+ previousThread->next = nextThread;
+ else
+ m_registeredThreads = nextThread;
+ thread = nextThread;
+ continue;
+ }
+#else
+ UNUSED_PARAM(numberOfThreads);
+ UNUSED_PARAM(previousThread);
+ ASSERT_UNUSED(success, success);