Tsan fix
diff --git a/include/perfetto/base/thread_annotations.h b/include/perfetto/base/thread_annotations.h
index 3d91269..691b521 100644
--- a/include/perfetto/base/thread_annotations.h
+++ b/include/perfetto/base/thread_annotations.h
@@ -55,6 +55,26 @@
 
 #include "perfetto/base/build_config.h"
 
+#ifdef THREAD_SANITIZER
+#include <sanitizer/tsan_interface.h>
+
+#define PERFETTO_TSAN_MUTEX_CREATE __tsan_mutex_create
+#define PERFETTO_TSAN_MUTEX_DESTROY __tsan_mutex_destroy
+#define PERFETTO_TSAN_MUTEX_PRE_LOCK __tsan_mutex_pre_lock
+#define PERFETTO_TSAN_MUTEX_POST_LOCK __tsan_mutex_post_lock
+#define PERFETTO_TSAN_MUTEX_PRE_UNLOCK __tsan_mutex_pre_unlock
+#define PERFETTO_TSAN_MUTEX_POST_UNLOCK __tsan_mutex_post_unlock
+#else
+
+#define PERFETTO_TSAN_MUTEX_CREATE(...)
+#define PERFETTO_TSAN_MUTEX_DESTROY(...)
+#define PERFETTO_TSAN_MUTEX_PRE_LOCK(...)
+#define PERFETTO_TSAN_MUTEX_POST_LOCK(...)
+#define PERFETTO_TSAN_MUTEX_PRE_UNLOCK(...)
+#define PERFETTO_TSAN_MUTEX_POST_UNLOCK(...)
+
+#endif
+
 #if defined(__clang__) && PERFETTO_BUILDFLAG(PERFETTO_THREAD_SAFETY_ANNOTATIONS)
 #define PERFETTO_THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
 #else
diff --git a/include/perfetto/ext/base/rt_mutex.h b/include/perfetto/ext/base/rt_mutex.h
index 8b8053c..764186c 100644
--- a/include/perfetto/ext/base/rt_mutex.h
+++ b/include/perfetto/ext/base/rt_mutex.h
@@ -30,6 +30,7 @@
 //   https://github.com/MicrosoftDocs/win32/commit/a43cb3b5039c5cfc53642bfcea174003a2f1168f
 
 #include "perfetto/base/build_config.h"
+#include "perfetto/base/thread_annotations.h"
 
 // Note: PERFETTO_HAS_RT_FUTEX() does not imply that we will use futexes. For
 // now the usage of futexes is gated behind a runtime flag (for experiment
@@ -91,8 +92,8 @@
 //   waiters.
 class PERFETTO_LOCKABLE RtFutex {
  public:
-  RtFutex() = default;
-  ~RtFutex() = default;
+  RtFutex() { PERFETTO_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static); }
+  ~RtFutex() { PERFETTO_TSAN_MUTEX_DESTROY(this, __tsan_mutex_not_static); }
 
   // Disable copy or move. Copy doesn't make sense. Move isn't feasible because
   // the pointer to the atomic integer is the handle used by the kernel to setup
@@ -112,29 +113,37 @@
   }
 
   bool try_lock() noexcept PERFETTO_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
-    if (PERFETTO_LIKELY(TryLockFastpath())) {
+    PERFETTO_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_try_lock);
+    if (PERFETTO_LIKELY(TryLockFastpath()) || TryLockSlowpath()) {
+      PERFETTO_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_try_lock, 0);
       return true;
     }
-    return TryLockSlowpath();
+    PERFETTO_TSAN_MUTEX_POST_LOCK(
+        this, __tsan_mutex_try_lock | __tsan_mutex_try_lock_failed, 0);
+    return false;
   }
 
   void lock() PERFETTO_EXCLUSIVE_LOCK_FUNCTION() {
+    PERFETTO_TSAN_MUTEX_PRE_LOCK(this, 0);
     if (!PERFETTO_LIKELY(TryLockFastpath())) {
       LockSlowpath();
     }
+    PERFETTO_TSAN_MUTEX_POST_LOCK(this, 0, 0);
   }
 
   void unlock() noexcept PERFETTO_UNLOCK_FUNCTION() {
+    PERFETTO_TSAN_MUTEX_PRE_UNLOCK(this, 0);
     int expected = GetTid();
-    if (lock_.compare_exchange_strong(expected, 0, std::memory_order_release,
-                                      std::memory_order_relaxed)) {
-      // If the current value is our tid, we can unlock without a syscall since
-      // there are no current waiters.
-      return;
+    // If the current value is our tid, we can unlock without a syscall since
+    // there are no current waiters.
+    if (!PERFETTO_LIKELY(lock_.compare_exchange_strong(
+            expected, 0, std::memory_order_release,
+            std::memory_order_relaxed))) {
+      // The tid doesn't match because the kernel appended the FUTEX_WAITERS
+      // bit. There are waiters, tell the kernel to notify them and unlock.
+      UnlockSlowpath();
     }
-    // The tid doesn't match because the kernel appended the FUTEX_WAITERS bit.
-    // There are waiters, tell the kernel to notify them and unlock.
-    UnlockSlowpath();
+    PERFETTO_TSAN_MUTEX_POST_UNLOCK(this, 0);
   }
 
  private:
diff --git a/src/base/rt_mutex_benchmark.cc b/src/base/rt_mutex_benchmark.cc
index ac0f924..7f2ed8a 100644
--- a/src/base/rt_mutex_benchmark.cc
+++ b/src/base/rt_mutex_benchmark.cc
@@ -38,8 +38,8 @@
   for (auto _ : state) {
     mutex.lock();
     n++;
-    mutex.unlock();
     benchmark::DoNotOptimize(n);
+    mutex.unlock();
     benchmark::ClobberMemory();
   }
 }
@@ -55,8 +55,8 @@
     while (!stop.load(std::memory_order_relaxed)) {
       mutex.lock();
       counter++;
-      mutex.unlock();
       benchmark::DoNotOptimize(counter);
+      mutex.unlock();
     }
   };