[compiler-rt] [TSan] Add interceptor for os_unfair_lock_lock_with_flags (PR #153815)

Dan Blackwell via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 19 04:06:29 PDT 2025


https://github.com/DanBlackwell updated https://github.com/llvm/llvm-project/pull/153815

>From 6ada59bb80eab6d3a623f189712e107c1afb88fb Mon Sep 17 00:00:00 2001
From: Dan Blackwell <dan_blackwell at apple.com>
Date: Fri, 15 Aug 2025 11:55:16 +0100
Subject: [PATCH 1/2] [TSan] Add interceptor for os_unfair_lock_lock_with_flags

Also update os_unfair_lock tsan test to check this function on platforms where it is available.
---
 .../lib/tsan/rtl/tsan_interceptors_mac.cpp    | 18 +++++++++
 compiler-rt/test/tsan/Darwin/os_unfair_lock.c | 37 ++++++++++++++++++-
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cpp
index 978664411fff4..7ab232ba0538e 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cpp
@@ -281,6 +281,24 @@ TSAN_INTERCEPTOR(void, os_unfair_lock_lock, os_unfair_lock_t lock) {
   Acquire(thr, pc, (uptr)lock);
 }
 
+// os_unfair_lock_lock_with_flags was introduced in macOS 15
+#  if defined(__MAC_15_0)
+#    pragma clang diagnostic push
+#    pragma clang diagnostic ignored "-Wunguarded-availability-new"
+// We're just intercepting this - if it doesn't exist on the platform, then the
+// process shouldn't have called it in the first place.
+TSAN_INTERCEPTOR(void, os_unfair_lock_lock_with_flags, os_unfair_lock_t lock,
+                 os_unfair_lock_flags_t flags) {
+  if (!cur_thread()->is_inited || cur_thread()->is_dead) {
+    return REAL(os_unfair_lock_lock_with_flags)(lock, flags);
+  }
+  SCOPED_TSAN_INTERCEPTOR(os_unfair_lock_lock_with_flags, lock, flags);
+  REAL(os_unfair_lock_lock_with_flags)(lock, flags);
+  Acquire(thr, pc, (uptr)lock);
+}
+#    pragma clang diagnostic pop
+#  endif
+
 TSAN_INTERCEPTOR(void, os_unfair_lock_lock_with_options, os_unfair_lock_t lock,
                  u32 options) {
   if (!cur_thread()->is_inited || cur_thread()->is_dead) {
diff --git a/compiler-rt/test/tsan/Darwin/os_unfair_lock.c b/compiler-rt/test/tsan/Darwin/os_unfair_lock.c
index 320e7f5e56d1d..24577ad2f7dbc 100644
--- a/compiler-rt/test/tsan/Darwin/os_unfair_lock.c
+++ b/compiler-rt/test/tsan/Darwin/os_unfair_lock.c
@@ -1,6 +1,7 @@
 // RUN: %clang_tsan %s -o %t
 // RUN: %run %t 2>&1 | FileCheck %s --implicit-check-not='ThreadSanitizer'
 
+#include <Availability.h>
 #include <os/lock.h>
 #include <pthread.h>
 #include <stdio.h>
@@ -15,6 +16,18 @@ void *Thread(void *a) {
   return NULL;
 }
 
+#if defined(__MAC_15_0)
+void *ThreadWithFlags(void *a) {
+#  pragma clang diagnostic push
+#  pragma clang diagnostic ignored "-Wunguarded-availability-new"
+  os_unfair_lock_lock_with_flags(&lock, OS_UNFAIR_LOCK_FLAG_ADAPTIVE_SPIN);
+#  pragma clang diagnostic pop
+  global_variable++;
+  os_unfair_lock_unlock(&lock);
+  return NULL;
+}
+#endif
+
 int main() {
   pthread_t t1, t2;
   global_variable = 0;
@@ -23,6 +36,28 @@ int main() {
   pthread_join(t1, NULL);
   pthread_join(t2, NULL);
   fprintf(stderr, "global_variable = %ld\n", global_variable);
+
+  // CHECK: global_variable = 2
+
+  void *(*func)(void *) = Thread;
+  char flags_available = 0;
+#if defined(__MAC_15_0)
+#  pragma clang diagnostic push
+#  pragma clang diagnostic ignored "-Wunguarded-availability-new"
+  if (&os_unfair_lock_lock_with_flags) {
+#  pragma clang diagnostic pop
+    func = ThreadWithFlags;
+    flags_available = 1;
+  }
+#endif
+
+  pthread_create(&t1, NULL, func, NULL);
+  pthread_create(&t2, NULL, func, NULL);
+  pthread_join(t1, NULL);
+  pthread_join(t2, NULL);
+  fprintf(stderr,
+          "global_variable = %ld, os_unfair_lock_lock_with_flags %savailable\n",
+          global_variable, flags_available ? "" : "un");
 }
 
-// CHECK: global_variable = 2
+// CHECK: global_variable = 4

>From b1caf381f6d51918c3344159b8b044a1a506e71e Mon Sep 17 00:00:00 2001
From: Dan Blackwell <dan_blackwell at apple.com>
Date: Tue, 19 Aug 2025 11:59:48 +0100
Subject: [PATCH 2/2] Update version guarding logic to be cleaner, and handle
 more platforms.

---
 compiler-rt/test/tsan/Darwin/os_unfair_lock.c | 18 +++++++-----------
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/compiler-rt/test/tsan/Darwin/os_unfair_lock.c b/compiler-rt/test/tsan/Darwin/os_unfair_lock.c
index 24577ad2f7dbc..f9a85d631bc03 100644
--- a/compiler-rt/test/tsan/Darwin/os_unfair_lock.c
+++ b/compiler-rt/test/tsan/Darwin/os_unfair_lock.c
@@ -16,17 +16,20 @@ void *Thread(void *a) {
   return NULL;
 }
 
-#if defined(__MAC_15_0)
 void *ThreadWithFlags(void *a) {
+#if defined(__MAC_15_0) || defined(__IPHONE_18_0) || defined(__TVOS_18_0) ||   \
+    defined(__VISIONOS_2_0) || defined(__WATCHOS_11_0)
 #  pragma clang diagnostic push
 #  pragma clang diagnostic ignored "-Wunguarded-availability-new"
   os_unfair_lock_lock_with_flags(&lock, OS_UNFAIR_LOCK_FLAG_ADAPTIVE_SPIN);
 #  pragma clang diagnostic pop
+#else
+  os_unfair_lock_lock(&lock);
+#endif
   global_variable++;
   os_unfair_lock_unlock(&lock);
   return NULL;
 }
-#endif
 
 int main() {
   pthread_t t1, t2;
@@ -41,15 +44,8 @@ int main() {
 
   void *(*func)(void *) = Thread;
   char flags_available = 0;
-#if defined(__MAC_15_0)
-#  pragma clang diagnostic push
-#  pragma clang diagnostic ignored "-Wunguarded-availability-new"
-  if (&os_unfair_lock_lock_with_flags) {
-#  pragma clang diagnostic pop
-    func = ThreadWithFlags;
-    flags_available = 1;
-  }
-#endif
+  func = ThreadWithFlags;
+  flags_available = 1;
 
   pthread_create(&t1, NULL, func, NULL);
   pthread_create(&t2, NULL, func, NULL);



More information about the llvm-commits mailing list