Skip to content

Commit 71f7f8a

Browse files
authored
[TSan] Add interceptor for os_unfair_lock_lock_with_flags (#153815)
Also update os_unfair_lock tsan test to check this function on platforms where it is available. rdar://158294950
1 parent a401f46 commit 71f7f8a

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,25 @@ TSAN_INTERCEPTOR(void, os_unfair_lock_lock, os_unfair_lock_t lock) {
281281
Acquire(thr, pc, (uptr)lock);
282282
}
283283

284+
// os_unfair_lock_lock_with_flags was introduced in macOS 15
285+
# if defined(__MAC_15_0) || defined(__IPHONE_18_0) || defined(__TVOS_18_0) || \
286+
defined(__VISIONOS_2_0) || defined(__WATCHOS_11_0)
287+
# pragma clang diagnostic push
288+
# pragma clang diagnostic ignored "-Wunguarded-availability-new"
289+
// We're just intercepting this - if it doesn't exist on the platform, then the
290+
// process shouldn't have called it in the first place.
291+
TSAN_INTERCEPTOR(void, os_unfair_lock_lock_with_flags, os_unfair_lock_t lock,
292+
os_unfair_lock_flags_t flags) {
293+
if (!cur_thread()->is_inited || cur_thread()->is_dead) {
294+
return REAL(os_unfair_lock_lock_with_flags)(lock, flags);
295+
}
296+
SCOPED_TSAN_INTERCEPTOR(os_unfair_lock_lock_with_flags, lock, flags);
297+
REAL(os_unfair_lock_lock_with_flags)(lock, flags);
298+
Acquire(thr, pc, (uptr)lock);
299+
}
300+
# pragma clang diagnostic pop
301+
# endif
302+
284303
TSAN_INTERCEPTOR(void, os_unfair_lock_lock_with_options, os_unfair_lock_t lock,
285304
u32 options) {
286305
if (!cur_thread()->is_inited || cur_thread()->is_dead) {

compiler-rt/test/tsan/Darwin/os_unfair_lock.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
// RUN: %clang_tsan %s -o %t
22
// RUN: %run %t 2>&1 | FileCheck %s --implicit-check-not='ThreadSanitizer'
33

4+
#include <Availability.h>
45
#include <os/lock.h>
56
#include <pthread.h>
67
#include <stdio.h>
78

89
long global_variable;
910
os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;
11+
char flags_available = 0;
1012

1113
void *Thread(void *a) {
1214
os_unfair_lock_lock(&lock);
@@ -15,6 +17,22 @@ void *Thread(void *a) {
1517
return NULL;
1618
}
1719

20+
void *ThreadWithFlags(void *a) {
21+
#if defined(__MAC_15_0) || defined(__IPHONE_18_0) || defined(__TVOS_18_0) || \
22+
defined(__VISIONOS_2_0) || defined(__WATCHOS_11_0)
23+
# pragma clang diagnostic push
24+
# pragma clang diagnostic ignored "-Wunguarded-availability-new"
25+
os_unfair_lock_lock_with_flags(&lock, OS_UNFAIR_LOCK_FLAG_ADAPTIVE_SPIN);
26+
flags_available = 1;
27+
# pragma clang diagnostic pop
28+
#else
29+
os_unfair_lock_lock(&lock);
30+
#endif
31+
global_variable++;
32+
os_unfair_lock_unlock(&lock);
33+
return NULL;
34+
}
35+
1836
int main() {
1937
pthread_t t1, t2;
2038
global_variable = 0;
@@ -23,6 +41,16 @@ int main() {
2341
pthread_join(t1, NULL);
2442
pthread_join(t2, NULL);
2543
fprintf(stderr, "global_variable = %ld\n", global_variable);
44+
45+
// CHECK: global_variable = 2
46+
47+
pthread_create(&t1, NULL, ThreadWithFlags, NULL);
48+
pthread_create(&t2, NULL, ThreadWithFlags, NULL);
49+
pthread_join(t1, NULL);
50+
pthread_join(t2, NULL);
51+
fprintf(stderr,
52+
"global_variable = %ld, os_unfair_lock_lock_with_flags %savailable\n",
53+
global_variable, flags_available ? "" : "un");
2654
}
2755

28-
// CHECK: global_variable = 2
56+
// CHECK: global_variable = 4

0 commit comments

Comments
 (0)