Index: lib/sanitizer_common/sanitizer_stoptheworld.h
===================================================================
--- lib/sanitizer_common/sanitizer_stoptheworld.h
+++ lib/sanitizer_common/sanitizer_stoptheworld.h
@@ -17,36 +17,65 @@
 #include "sanitizer_internal_defs.h"
 #include "sanitizer_common.h"
 
+#if SANITIZER_MAC
+#include <mach/mach.h>
+#endif
+
 namespace __sanitizer {
 typedef int SuspendedThreadID;
 
+#if SANITIZER_LINUX
+typedef SuspendedThreadID SuspendedThread;
+#elif SANITIZER_MAC
+typedef thread_t SuspendedThread;
+#endif
+
+// On Darwin, we need both the thread_t and the tid, but
+// converting between the two requires an expensive syscall,
+// so we store both in the struct. On Linux, contains 2 copies
+// of the tid.
+struct SuspendedThreadInfo {
+  SuspendedThread thread;
+  SuspendedThreadID tid;
+};
+
 // Holds the list of suspended threads and provides an interface to dump their
 // register contexts.
 class SuspendedThreadsList {
  public:
   SuspendedThreadsList()
-    : thread_ids_(1024) {}
+    : threads_(1024) {}
+
+  SuspendedThread GetThread(uptr index) const {
+    CHECK_LT(index, threads_.size());
+    return threads_[index].thread;
+  }
+
   SuspendedThreadID GetThreadID(uptr index) const {
-    CHECK_LT(index, thread_ids_.size());
-    return thread_ids_[index];
+    CHECK_LT(index, threads_.size());
+    return threads_[index].tid;
   }
+
+  SuspendedThreadID ThreadToThreadID(SuspendedThread) const;
+
   int GetRegistersAndSP(uptr index, uptr *buffer, uptr *sp) const;
   // The buffer in GetRegistersAndSP should be at least this big.
   static uptr RegisterCount();
-  uptr thread_count() const { return thread_ids_.size(); }
-  bool Contains(SuspendedThreadID thread_id) const {
-    for (uptr i = 0; i < thread_ids_.size(); i++) {
-      if (thread_ids_[i] == thread_id)
+  uptr thread_count() const { return threads_.size(); }
+  bool Contains(SuspendedThread thread) const {
+    for (uptr i = 0; i < threads_.size(); i++) {
+      if (threads_[i].thread == thread)
         return true;
     }
     return false;
   }
-  void Append(SuspendedThreadID thread_id) {
-    thread_ids_.push_back(thread_id);
+
+  void Append(SuspendedThread thread) {
+    threads_.push_back({thread, ThreadToThreadID(thread)});
   }
 
  private:
-  InternalMmapVector<SuspendedThreadID> thread_ids_;
+  InternalMmapVector<SuspendedThreadInfo> threads_;
 
   // Prohibit copy and assign.
   SuspendedThreadsList(const SuspendedThreadsList&);
Index: lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
===================================================================
--- lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
+++ lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
@@ -493,6 +493,11 @@
 #error "Unsupported architecture"
 #endif // SANITIZER_ANDROID && defined(__arm__)
 
+SuspendedThreadID
+SuspendedThreadsList::ThreadToThreadID(SuspendedThread thread) const {
+  return thread;
+}
+
 int SuspendedThreadsList::GetRegistersAndSP(uptr index,
                                             uptr *buffer,
                                             uptr *sp) const {
Index: lib/sanitizer_common/sanitizer_stoptheworld_mac.cc
===================================================================
--- lib/sanitizer_common/sanitizer_stoptheworld_mac.cc
+++ lib/sanitizer_common/sanitizer_stoptheworld_mac.cc
@@ -16,6 +16,8 @@
 #if SANITIZER_MAC && (defined(__x86_64__) || defined(__aarch64__) || \
                       defined(__mips64) || defined(__i386))
 
+#include <mach/thread_info.h>
+
 #include "sanitizer_stoptheworld.h"
 
 namespace __sanitizer {
@@ -23,6 +25,19 @@
   CHECK(0 && "unimplemented");
 }
 
+SuspendedThreadID
+SuspendedThreadsList::ThreadToThreadID(SuspendedThread thread) const {
+  thread_identifier_info_data_t info;
+  mach_msg_type_number_t info_count = THREAD_IDENTIFIER_INFO_COUNT;
+  kern_return_t err = thread_info(thread, THREAD_IDENTIFIER_INFO,
+                                  (thread_info_t)&info, &info_count);
+  if (err != KERN_SUCCESS) {
+    VReport(1, "Error - unable to get thread ident for a thread\n");
+    return 0;
+  }
+  return info.thread_id;
+}
+
 int SuspendedThreadsList::GetRegistersAndSP(uptr index,
                                             uptr *buffer,
                                             uptr *sp) const {