diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mutex.h b/compiler-rt/lib/sanitizer_common/sanitizer_mutex.h
--- a/compiler-rt/lib/sanitizer_common/sanitizer_mutex.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_mutex.h
@@ -149,9 +149,9 @@
 };
 
 // Reader-writer mutex.
-class MUTEX Mutex2 {
+class MUTEX Mutex {
  public:
-  constexpr Mutex2(MutexType type = MutexUnchecked) : checked_(type) {}
+  constexpr Mutex(MutexType type = MutexUnchecked) : checked_(type) {}
 
   void Lock() ACQUIRE() {
     checked_.Lock();
@@ -329,8 +329,8 @@
   static constexpr u64 kWriterLock = 1ull << (3 * kCounterWidth);
   static constexpr u64 kWriterSpinWait = 1ull << (3 * kCounterWidth + 1);
 
-  Mutex2(const Mutex2 &) = delete;
-  void operator=(const Mutex2 &) = delete;
+  Mutex(const Mutex &) = delete;
+  void operator=(const Mutex &) = delete;
 };
 
 void FutexWait(atomic_uint32_t *p, u32 cmp);
@@ -477,6 +477,8 @@
 typedef GenericScopedLock<BlockingMutex> BlockingMutexLock;
 typedef GenericScopedLock<RWMutex> RWMutexLock;
 typedef GenericScopedReadLock<RWMutex> RWMutexReadLock;
+typedef GenericScopedLock<Mutex> Lock;
+typedef GenericScopedReadLock<Mutex> ReadLock;
 
 }  // namespace __sanitizer
 
diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_mutex_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_mutex_test.cpp
--- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_mutex_test.cpp
+++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_mutex_test.cpp
@@ -158,12 +158,12 @@
   check_locked(mtx);
 }
 
-TEST(SanitizerCommon, Mutex2) {
-  Mutex2 mtx;
-  TestData<Mutex2> data(&mtx);
+TEST(SanitizerCommon, Mutex) {
+  Mutex mtx;
+  TestData<Mutex> data(&mtx);
   pthread_t threads[kThreads];
   for (int i = 0; i < kThreads; i++)
-    PTHREAD_CREATE(&threads[i], 0, read_write_thread<Mutex2>, &data);
+    PTHREAD_CREATE(&threads[i], 0, read_write_thread<Mutex>, &data);
   for (int i = 0; i < kThreads; i++) PTHREAD_JOIN(threads[i], 0);
 }
 
diff --git a/compiler-rt/lib/tsan/CMakeLists.txt b/compiler-rt/lib/tsan/CMakeLists.txt
--- a/compiler-rt/lib/tsan/CMakeLists.txt
+++ b/compiler-rt/lib/tsan/CMakeLists.txt
@@ -39,7 +39,6 @@
   rtl/tsan_malloc_mac.cpp
   rtl/tsan_md5.cpp
   rtl/tsan_mman.cpp
-  rtl/tsan_mutex.cpp
   rtl/tsan_mutexset.cpp
   rtl/tsan_preinit.cpp
   rtl/tsan_report.cpp
@@ -94,7 +93,6 @@
   rtl/tsan_interface_inl.h
   rtl/tsan_interface_java.h
   rtl/tsan_mman.h
-  rtl/tsan_mutex.h
   rtl/tsan_mutexset.h
   rtl/tsan_platform.h
   rtl/tsan_ppc_regs.h
diff --git a/compiler-rt/lib/tsan/go/build.bat b/compiler-rt/lib/tsan/go/build.bat
--- a/compiler-rt/lib/tsan/go/build.bat
+++ b/compiler-rt/lib/tsan/go/build.bat
@@ -4,7 +4,6 @@
   ..\rtl\tsan_clock.cpp ^
   ..\rtl\tsan_flags.cpp ^
   ..\rtl\tsan_md5.cpp ^
-  ..\rtl\tsan_mutex.cpp ^
   ..\rtl\tsan_report.cpp ^
   ..\rtl\tsan_rtl.cpp ^
   ..\rtl\tsan_rtl_mutex.cpp ^
diff --git a/compiler-rt/lib/tsan/go/buildgo.sh b/compiler-rt/lib/tsan/go/buildgo.sh
--- a/compiler-rt/lib/tsan/go/buildgo.sh
+++ b/compiler-rt/lib/tsan/go/buildgo.sh
@@ -9,7 +9,6 @@
 	../rtl/tsan_flags.cpp
 	../rtl/tsan_interface_atomic.cpp
 	../rtl/tsan_md5.cpp
-	../rtl/tsan_mutex.cpp
 	../rtl/tsan_report.cpp
 	../rtl/tsan_rtl.cpp
 	../rtl/tsan_rtl_mutex.cpp
diff --git a/compiler-rt/lib/tsan/rtl/tsan_defs.h b/compiler-rt/lib/tsan/rtl/tsan_defs.h
--- a/compiler-rt/lib/tsan/rtl/tsan_defs.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_defs.h
@@ -15,6 +15,7 @@
 
 #include "sanitizer_common/sanitizer_internal_defs.h"
 #include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_mutex.h"
 #include "ubsan/ubsan_platform.h"
 
 // Setup defaults for compile definitions.
@@ -172,6 +173,17 @@
   // as 16-bit values, see tsan_defs.h.
 };
 
+enum MutexType {
+  MutexTypeTrace = MutexLastCommon,
+  MutexTypeReport,
+  MutexTypeSyncVar,
+  MutexTypeAnnotations,
+  MutexTypeAtExit,
+  MutexTypeFired,
+  MutexTypeRacy,
+  MutexTypeGlobalProc,
+};
+
 }  // namespace __tsan
 
 #endif  // TSAN_DEFS_H
diff --git a/compiler-rt/lib/tsan/rtl/tsan_dense_alloc.h b/compiler-rt/lib/tsan/rtl/tsan_dense_alloc.h
--- a/compiler-rt/lib/tsan/rtl/tsan_dense_alloc.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_dense_alloc.h
@@ -20,7 +20,6 @@
 
 #include "sanitizer_common/sanitizer_common.h"
 #include "tsan_defs.h"
-#include "tsan_mutex.h"
 
 namespace __tsan {
 
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
@@ -196,12 +196,10 @@
   unsigned finalize_key;
 #endif
 
-  BlockingMutex atexit_mu;
+  Mutex atexit_mu;
   Vector<struct AtExitCtx *> AtExitStack;
 
-  InterceptorContext()
-      : libignore(LINKER_INITIALIZED), AtExitStack() {
-  }
+  InterceptorContext() : libignore(LINKER_INITIALIZED), atexit_mu(MutexTypeAtExit), AtExitStack() {}
 };
 
 static ALIGNED(64) char interceptor_placeholder[sizeof(InterceptorContext)];
@@ -267,7 +265,7 @@
   if (!thr_->ignore_interceptors) {
     ProcessPendingSignals(thr_);
     FuncExit(thr_);
-    CheckNoLocks(thr_);
+    CheckedMutex::CheckNoLocks();
   }
 }
 
@@ -377,7 +375,7 @@
   AtExitCtx *ctx;
   {
     // Ensure thread-safety.
-    BlockingMutexLock l(&interceptor_ctx()->atexit_mu);
+    Lock l(&interceptor_ctx()->atexit_mu);
 
     // Pop AtExitCtx from the top of the stack of callback functions
     uptr element = interceptor_ctx()->AtExitStack.Size() - 1;
@@ -433,7 +431,10 @@
     // Store ctx in a local stack-like structure
 
     // Ensure thread-safety.
-    BlockingMutexLock l(&interceptor_ctx()->atexit_mu);
+    Lock l(&interceptor_ctx()->atexit_mu);
+    // __cxa_atexit calls calloc, without this we fail with
+    // atexit_mu held on exit from the calloc interceptor.
+    ScopedIgnoreInterceptors ignore;
 
     res = REAL(__cxa_atexit)((void (*)(void *a))at_exit_wrapper, 0, 0);
     // Push AtExitCtx on the top of the stack of callback functions
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp b/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp
--- a/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp
@@ -15,7 +15,6 @@
 #include "sanitizer_common/sanitizer_stacktrace.h"
 #include "sanitizer_common/sanitizer_vector.h"
 #include "tsan_interface_ann.h"
-#include "tsan_mutex.h"
 #include "tsan_report.h"
 #include "tsan_rtl.h"
 #include "tsan_mman.h"
@@ -38,7 +37,7 @@
 
   ~ScopedAnnotation() {
     FuncExit(thr_);
-    CheckNoLocks(thr_);
+    CheckedMutex::CheckNoLocks();
   }
  private:
   ThreadState *const thr_;
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface_java.cpp b/compiler-rt/lib/tsan/rtl/tsan_interface_java.cpp
--- a/compiler-rt/lib/tsan/rtl/tsan_interface_java.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_interface_java.cpp
@@ -12,7 +12,6 @@
 
 #include "tsan_interface_java.h"
 #include "tsan_rtl.h"
-#include "tsan_mutex.h"
 #include "sanitizer_common/sanitizer_internal_defs.h"
 #include "sanitizer_common/sanitizer_common.h"
 #include "sanitizer_common/sanitizer_placement_new.h"
diff --git a/compiler-rt/lib/tsan/rtl/tsan_mutex.h b/compiler-rt/lib/tsan/rtl/tsan_mutex.h
deleted file mode 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_mutex.h
+++ /dev/null
@@ -1,87 +0,0 @@
-//===-- tsan_mutex.h --------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of ThreadSanitizer (TSan), a race detector.
-//
-//===----------------------------------------------------------------------===//
-#ifndef TSAN_MUTEX_H
-#define TSAN_MUTEX_H
-
-#include "sanitizer_common/sanitizer_atomic.h"
-#include "sanitizer_common/sanitizer_mutex.h"
-#include "tsan_defs.h"
-
-namespace __tsan {
-
-enum MutexType {
-  MutexTypeInvalid,
-  MutexTypeTrace,
-  MutexTypeThreads,
-  MutexTypeReport,
-  MutexTypeSyncVar,
-  MutexTypeSyncTab,
-  MutexTypeSlab,
-  MutexTypeAnnotations,
-  MutexTypeAtExit,
-  MutexTypeMBlock,
-  MutexTypeJavaMBlock,
-  MutexTypeDDetector,
-  MutexTypeFired,
-  MutexTypeRacy,
-  MutexTypeGlobalProc,
-
-  // This must be the last.
-  MutexTypeCount
-};
-
-class Mutex {
- public:
-  explicit Mutex(MutexType type);
-  ~Mutex();
-
-  void Lock();
-  void Unlock();
-
-  void ReadLock();
-  void ReadUnlock();
-
-  void CheckLocked();
-
- private:
-  atomic_uintptr_t state_;
-#if SANITIZER_DEBUG
-  MutexType type_;
-#endif
-
-  Mutex(const Mutex&);
-  void operator = (const Mutex&);
-};
-
-typedef GenericScopedLock<Mutex> Lock;
-typedef GenericScopedReadLock<Mutex> ReadLock;
-
-class InternalDeadlockDetector {
- public:
-  InternalDeadlockDetector();
-  void Lock(MutexType t);
-  void Unlock(MutexType t);
-  void CheckNoLocks();
- private:
-  u64 seq_;
-  u64 locked_[MutexTypeCount];
-};
-
-void InitializeMutex();
-
-// Checks that the current thread does not hold any runtime locks
-// (e.g. when returning from an interceptor).
-void CheckNoLocks(ThreadState *thr);
-
-}  // namespace __tsan
-
-#endif  // TSAN_MUTEX_H
diff --git a/compiler-rt/lib/tsan/rtl/tsan_mutex.cpp b/compiler-rt/lib/tsan/rtl/tsan_mutex.cpp
deleted file mode 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_mutex.cpp
+++ /dev/null
@@ -1,280 +0,0 @@
-//===-- tsan_mutex.cpp ----------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of ThreadSanitizer (TSan), a race detector.
-//
-//===----------------------------------------------------------------------===//
-#include "sanitizer_common/sanitizer_libc.h"
-#include "tsan_mutex.h"
-#include "tsan_platform.h"
-#include "tsan_rtl.h"
-
-namespace __tsan {
-
-// Simple reader-writer spin-mutex. Optimized for not-so-contended case.
-// Readers have preference, can possibly starvate writers.
-
-// The table fixes what mutexes can be locked under what mutexes.
-// E.g. if the row for MutexTypeThreads contains MutexTypeReport,
-// then Report mutex can be locked while under Threads mutex.
-// The leaf mutexes can be locked under any other mutexes.
-// Recursive locking is not supported.
-#if SANITIZER_DEBUG && !SANITIZER_GO
-const MutexType MutexTypeLeaf = (MutexType)-1;
-static MutexType CanLockTab[MutexTypeCount][MutexTypeCount] = {
-  /*0  MutexTypeInvalid*/     {},
-  /*1  MutexTypeTrace*/       {MutexTypeLeaf},
-  /*2  MutexTypeThreads*/     {MutexTypeReport},
-  /*3  MutexTypeReport*/      {MutexTypeSyncVar,
-                               MutexTypeMBlock, MutexTypeJavaMBlock},
-  /*4  MutexTypeSyncVar*/     {MutexTypeDDetector},
-  /*5  MutexTypeSyncTab*/     {},  // unused
-  /*6  MutexTypeSlab*/        {MutexTypeLeaf},
-  /*7  MutexTypeAnnotations*/ {},
-  /*8  MutexTypeAtExit*/      {MutexTypeSyncVar},
-  /*9  MutexTypeMBlock*/      {MutexTypeSyncVar},
-  /*10 MutexTypeJavaMBlock*/  {MutexTypeSyncVar},
-  /*11 MutexTypeDDetector*/   {},
-  /*12 MutexTypeFired*/       {MutexTypeLeaf},
-  /*13 MutexTypeRacy*/        {MutexTypeLeaf},
-  /*14 MutexTypeGlobalProc*/  {},
-};
-
-static bool CanLockAdj[MutexTypeCount][MutexTypeCount];
-#endif
-
-void InitializeMutex() {
-#if SANITIZER_DEBUG && !SANITIZER_GO
-  // Build the "can lock" adjacency matrix.
-  // If [i][j]==true, then one can lock mutex j while under mutex i.
-  const int N = MutexTypeCount;
-  int cnt[N] = {};
-  bool leaf[N] = {};
-  for (int i = 1; i < N; i++) {
-    for (int j = 0; j < N; j++) {
-      MutexType z = CanLockTab[i][j];
-      if (z == MutexTypeInvalid)
-        continue;
-      if (z == MutexTypeLeaf) {
-        CHECK(!leaf[i]);
-        leaf[i] = true;
-        continue;
-      }
-      CHECK(!CanLockAdj[i][(int)z]);
-      CanLockAdj[i][(int)z] = true;
-      cnt[i]++;
-    }
-  }
-  for (int i = 0; i < N; i++) {
-    CHECK(!leaf[i] || cnt[i] == 0);
-  }
-  // Add leaf mutexes.
-  for (int i = 0; i < N; i++) {
-    if (!leaf[i])
-      continue;
-    for (int j = 0; j < N; j++) {
-      if (i == j || leaf[j] || j == MutexTypeInvalid)
-        continue;
-      CHECK(!CanLockAdj[j][i]);
-      CanLockAdj[j][i] = true;
-    }
-  }
-  // Build the transitive closure.
-  bool CanLockAdj2[MutexTypeCount][MutexTypeCount];
-  for (int i = 0; i < N; i++) {
-    for (int j = 0; j < N; j++) {
-      CanLockAdj2[i][j] = CanLockAdj[i][j];
-    }
-  }
-  for (int k = 0; k < N; k++) {
-    for (int i = 0; i < N; i++) {
-      for (int j = 0; j < N; j++) {
-        if (CanLockAdj2[i][k] && CanLockAdj2[k][j]) {
-          CanLockAdj2[i][j] = true;
-        }
-      }
-    }
-  }
-#if 0
-  Printf("Can lock graph:\n");
-  for (int i = 0; i < N; i++) {
-    for (int j = 0; j < N; j++) {
-      Printf("%d ", CanLockAdj[i][j]);
-    }
-    Printf("\n");
-  }
-  Printf("Can lock graph closure:\n");
-  for (int i = 0; i < N; i++) {
-    for (int j = 0; j < N; j++) {
-      Printf("%d ", CanLockAdj2[i][j]);
-    }
-    Printf("\n");
-  }
-#endif
-  // Verify that the graph is acyclic.
-  for (int i = 0; i < N; i++) {
-    if (CanLockAdj2[i][i]) {
-      Printf("Mutex %d participates in a cycle\n", i);
-      Die();
-    }
-  }
-#endif
-}
-
-InternalDeadlockDetector::InternalDeadlockDetector() {
-  // Rely on zero initialization because some mutexes can be locked before ctor.
-}
-
-#if SANITIZER_DEBUG && !SANITIZER_GO
-void InternalDeadlockDetector::Lock(MutexType t) {
-  // Printf("LOCK %d @%zu\n", t, seq_ + 1);
-  CHECK_GT(t, MutexTypeInvalid);
-  CHECK_LT(t, MutexTypeCount);
-  u64 max_seq = 0;
-  u64 max_idx = MutexTypeInvalid;
-  for (int i = 0; i != MutexTypeCount; i++) {
-    if (locked_[i] == 0)
-      continue;
-    CHECK_NE(locked_[i], max_seq);
-    if (max_seq < locked_[i]) {
-      max_seq = locked_[i];
-      max_idx = i;
-    }
-  }
-  locked_[t] = ++seq_;
-  if (max_idx == MutexTypeInvalid)
-    return;
-  // Printf("  last %d @%zu\n", max_idx, max_seq);
-  if (!CanLockAdj[max_idx][t]) {
-    Printf("ThreadSanitizer: internal deadlock detected\n");
-    Printf("ThreadSanitizer: can't lock %d while under %zu\n",
-               t, (uptr)max_idx);
-    CHECK(0);
-  }
-}
-
-void InternalDeadlockDetector::Unlock(MutexType t) {
-  // Printf("UNLO %d @%zu #%zu\n", t, seq_, locked_[t]);
-  CHECK(locked_[t]);
-  locked_[t] = 0;
-}
-
-void InternalDeadlockDetector::CheckNoLocks() {
-  for (int i = 0; i != MutexTypeCount; i++) {
-    CHECK_EQ(locked_[i], 0);
-  }
-}
-#endif
-
-void CheckNoLocks(ThreadState *thr) {
-#if SANITIZER_DEBUG && !SANITIZER_GO
-  thr->internal_deadlock_detector.CheckNoLocks();
-#endif
-}
-
-const uptr kUnlocked = 0;
-const uptr kWriteLock = 1;
-const uptr kReadLock = 2;
-
-class Backoff {
- public:
-  Backoff()
-    : iter_() {
-  }
-
-  bool Do() {
-    if (iter_++ < kActiveSpinIters)
-      proc_yield(kActiveSpinCnt);
-    else
-      internal_sched_yield();
-    return true;
-  }
-
-  u64 Contention() const {
-    u64 active = iter_ % kActiveSpinIters;
-    u64 passive = iter_ - active;
-    return active + 10 * passive;
-  }
-
- private:
-  int iter_;
-  static const int kActiveSpinIters = 10;
-  static const int kActiveSpinCnt = 20;
-};
-
-Mutex::Mutex(MutexType type) {
-  CHECK_GT(type, MutexTypeInvalid);
-  CHECK_LT(type, MutexTypeCount);
-#if SANITIZER_DEBUG
-  type_ = type;
-#endif
-  atomic_store(&state_, kUnlocked, memory_order_relaxed);
-}
-
-Mutex::~Mutex() {
-  CHECK_EQ(atomic_load(&state_, memory_order_relaxed), kUnlocked);
-}
-
-void Mutex::Lock() {
-#if SANITIZER_DEBUG && !SANITIZER_GO
-  cur_thread()->internal_deadlock_detector.Lock(type_);
-#endif
-  uptr cmp = kUnlocked;
-  if (atomic_compare_exchange_strong(&state_, &cmp, kWriteLock,
-                                     memory_order_acquire))
-    return;
-  for (Backoff backoff; backoff.Do();) {
-    if (atomic_load(&state_, memory_order_relaxed) == kUnlocked) {
-      cmp = kUnlocked;
-      if (atomic_compare_exchange_weak(&state_, &cmp, kWriteLock,
-                                       memory_order_acquire)) {
-        return;
-      }
-    }
-  }
-}
-
-void Mutex::Unlock() {
-  uptr prev = atomic_fetch_sub(&state_, kWriteLock, memory_order_release);
-  (void)prev;
-  DCHECK_NE(prev & kWriteLock, 0);
-#if SANITIZER_DEBUG && !SANITIZER_GO
-  cur_thread()->internal_deadlock_detector.Unlock(type_);
-#endif
-}
-
-void Mutex::ReadLock() {
-#if SANITIZER_DEBUG && !SANITIZER_GO
-  cur_thread()->internal_deadlock_detector.Lock(type_);
-#endif
-  uptr prev = atomic_fetch_add(&state_, kReadLock, memory_order_acquire);
-  if ((prev & kWriteLock) == 0)
-    return;
-  for (Backoff backoff; backoff.Do();) {
-    prev = atomic_load(&state_, memory_order_acquire);
-    if ((prev & kWriteLock) == 0) {
-      return;
-    }
-  }
-}
-
-void Mutex::ReadUnlock() {
-  uptr prev = atomic_fetch_sub(&state_, kReadLock, memory_order_release);
-  (void)prev;
-  DCHECK_EQ(prev & kWriteLock, 0);
-  DCHECK_GT(prev & ~kWriteLock, 0);
-#if SANITIZER_DEBUG && !SANITIZER_GO
-  cur_thread()->internal_deadlock_detector.Unlock(type_);
-#endif
-}
-
-void Mutex::CheckLocked() {
-  CHECK_NE(atomic_load(&state_, memory_order_relaxed), 0);
-}
-
-}  // namespace __tsan
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
@@ -422,7 +422,6 @@
   InitializeInterceptors();
   CheckShadowMapping();
   InitializePlatform();
-  InitializeMutex();
   InitializeDynamicAnnotations();
 #if !SANITIZER_GO
   InitializeShadowMemory();
@@ -1133,7 +1132,28 @@
 
 }  // namespace __tsan
 
+#if SANITIZER_CHECK_DEADLOCKS
+namespace __sanitizer {
+using namespace __tsan;
+MutexMeta mutex_meta[] = {
+    {MutexInvalid, "Invalid", {}},
+    {MutexThreadRegistry, "ThreadRegistry", {}},
+    {MutexTypeTrace, "Trace", {MutexLeaf}},
+    {MutexTypeReport, "Report", {MutexTypeSyncVar}},
+    {MutexTypeSyncVar, "SyncVar", {}},
+    {MutexTypeAnnotations, "Annotations", {}},
+    {MutexTypeAtExit, "AtExit", {MutexTypeSyncVar}},
+    {MutexTypeFired, "Fired", {MutexLeaf}},
+    {MutexTypeRacy, "Racy", {MutexLeaf}},
+    {MutexTypeGlobalProc, "GlobalProc", {}},
+    {},
+};
+
+void PrintMutexPC(uptr pc) { StackTrace(&pc, 1).Print(); }
+}  // namespace __sanitizer
+#endif
+
 #if !SANITIZER_GO
 // Must be included in this file to make sure everything is inlined.
-#include "tsan_interface_inl.h"
+#  include "tsan_interface_inl.h"
 #endif
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp
@@ -129,7 +129,7 @@
   // We set thr->suppress_reports in the fork context.
   // Taking any locking in the fork context can lead to deadlocks.
   // If any locks are already taken, it's too late to do this check.
-  CheckNoLocks(thr);
+  CheckedMutex::CheckNoLocks();
   // For the same reason check we didn't lock thread_registry yet.
   if (SANITIZER_DEBUG)
     ThreadRegistryLock l(ctx->thread_registry);
@@ -596,7 +596,7 @@
 }
 
 void ReportRace(ThreadState *thr) {
-  CheckNoLocks(thr);
+  CheckedMutex::CheckNoLocks();
 
   // Symbolizer makes lots of intercepted calls. If we try to process them,
   // at best it will cause deadlocks on internal mutexes.
diff --git a/compiler-rt/lib/tsan/rtl/tsan_sync.h b/compiler-rt/lib/tsan/rtl/tsan_sync.h
--- a/compiler-rt/lib/tsan/rtl/tsan_sync.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_sync.h
@@ -17,7 +17,6 @@
 #include "sanitizer_common/sanitizer_deadlock_detector_interface.h"
 #include "tsan_defs.h"
 #include "tsan_clock.h"
-#include "tsan_mutex.h"
 #include "tsan_dense_alloc.h"
 
 namespace __tsan {
diff --git a/compiler-rt/lib/tsan/rtl/tsan_trace.h b/compiler-rt/lib/tsan/rtl/tsan_trace.h
--- a/compiler-rt/lib/tsan/rtl/tsan_trace.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_trace.h
@@ -13,7 +13,6 @@
 #define TSAN_TRACE_H
 
 #include "tsan_defs.h"
-#include "tsan_mutex.h"
 #include "tsan_stack_trace.h"
 #include "tsan_mutexset.h"
 
diff --git a/compiler-rt/lib/tsan/tests/unit/CMakeLists.txt b/compiler-rt/lib/tsan/tests/unit/CMakeLists.txt
--- a/compiler-rt/lib/tsan/tests/unit/CMakeLists.txt
+++ b/compiler-rt/lib/tsan/tests/unit/CMakeLists.txt
@@ -3,7 +3,6 @@
   tsan_dense_alloc_test.cpp
   tsan_flags_test.cpp
   tsan_mman_test.cpp
-  tsan_mutex_test.cpp
   tsan_shadow_test.cpp
   tsan_stack_test.cpp
   tsan_sync_test.cpp
diff --git a/compiler-rt/lib/tsan/tests/unit/tsan_mutex_test.cpp b/compiler-rt/lib/tsan/tests/unit/tsan_mutex_test.cpp
deleted file mode 100644
--- a/compiler-rt/lib/tsan/tests/unit/tsan_mutex_test.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-//===-- tsan_mutex_test.cpp -----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of ThreadSanitizer (TSan), a race detector.
-//
-//===----------------------------------------------------------------------===//
-#include "sanitizer_common/sanitizer_internal_defs.h"
-#include "sanitizer_common/sanitizer_atomic.h"
-#include "sanitizer_common/sanitizer_common.h"
-#include "sanitizer_common/sanitizer_mutex.h"
-#include "tsan_mutex.h"
-#include "gtest/gtest.h"
-
-namespace __tsan {
-
-template<typename MutexType>
-class TestData {
- public:
-  explicit TestData(MutexType *mtx)
-    : mtx_(mtx) {
-    for (int i = 0; i < kSize; i++)
-      data_[i] = 0;
-  }
-
-  void Write() {
-    Lock l(mtx_);
-    T v0 = data_[0];
-    for (int i = 0; i < kSize; i++) {
-      CHECK_EQ(data_[i], v0);
-      data_[i]++;
-    }
-  }
-
-  void Read() {
-    ReadLock l(mtx_);
-    T v0 = data_[0];
-    for (int i = 0; i < kSize; i++) {
-      CHECK_EQ(data_[i], v0);
-    }
-  }
-
-  void Backoff() {
-    volatile T data[kSize] = {};
-    for (int i = 0; i < kSize; i++) {
-      data[i]++;
-      CHECK_EQ(data[i], 1);
-    }
-  }
-
- private:
-  typedef GenericScopedLock<MutexType> Lock;
-  static const int kSize = 64;
-  typedef u64 T;
-  MutexType *mtx_;
-  char pad_[kCacheLineSize];
-  T data_[kSize];
-};
-
-const int kThreads = 8;
-const int kWriteRate = 1024;
-#if SANITIZER_DEBUG
-const int kIters = 16*1024;
-#else
-const int kIters = 64*1024;
-#endif
-
-template<typename MutexType>
-static void *write_mutex_thread(void *param) {
-  TestData<MutexType> *data = (TestData<MutexType>*)param;
-  for (int i = 0; i < kIters; i++) {
-    data->Write();
-    data->Backoff();
-  }
-  return 0;
-}
-
-template<typename MutexType>
-static void *read_mutex_thread(void *param) {
-  TestData<MutexType> *data = (TestData<MutexType>*)param;
-  for (int i = 0; i < kIters; i++) {
-    if ((i % kWriteRate) == 0)
-      data->Write();
-    else
-      data->Read();
-    data->Backoff();
-  }
-  return 0;
-}
-
-TEST(Mutex, Write) {
-  Mutex mtx(MutexTypeAnnotations);
-  TestData<Mutex> data(&mtx);
-  pthread_t threads[kThreads];
-  for (int i = 0; i < kThreads; i++)
-    pthread_create(&threads[i], 0, write_mutex_thread<Mutex>, &data);
-  for (int i = 0; i < kThreads; i++)
-    pthread_join(threads[i], 0);
-}
-
-TEST(Mutex, ReadWrite) {
-  Mutex mtx(MutexTypeAnnotations);
-  TestData<Mutex> data(&mtx);
-  pthread_t threads[kThreads];
-  for (int i = 0; i < kThreads; i++)
-    pthread_create(&threads[i], 0, read_mutex_thread<Mutex>, &data);
-  for (int i = 0; i < kThreads; i++)
-    pthread_join(threads[i], 0);
-}
-
-TEST(Mutex, SpinWrite) {
-  SpinMutex mtx;
-  TestData<SpinMutex> data(&mtx);
-  pthread_t threads[kThreads];
-  for (int i = 0; i < kThreads; i++)
-    pthread_create(&threads[i], 0, write_mutex_thread<SpinMutex>, &data);
-  for (int i = 0; i < kThreads; i++)
-    pthread_join(threads[i], 0);
-}
-
-}  // namespace __tsan