Skip to content

Commit 481a55a

Browse files
[rtsan][Apple] Add interceptor for _os_nospin_lock_lock (llvm#131034)
Follows the discussion here: llvm#129309 Recently, the test `TestRtsan.AccessingALargeAtomicVariableDiesWhenRealtime` has been failing on newer MacOS versions, because the internal locking mechanism in `std::atomic<T>::load` (for types `T` that are larger than the hardware lock-free limit), has changed to a function that wasn't being intercepted by rtsan. This PR introduces an interceptor for `_os_nospin_lock_lock`, which is the new internal locking mechanism. _Note: we'd probably do well to introduce interceptors for `_os_nospin_lock_unlock` (and `os_unfair_lock_unlock`) too, which also appear to have blocking implementations. This can follow in a separate PR._
1 parent abdbaff commit 481a55a

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@
3030
extern "C" {
3131
typedef int32_t OSSpinLock;
3232
void OSSpinLockLock(volatile OSSpinLock *__lock);
33+
// A pointer to this type is in the interface for `_os_nospin_lock_lock`, but
34+
// it's an internal implementation detail of `os/lock.c` on Darwin, and
35+
// therefore not available in any headers. As a workaround, we forward declare
36+
// it here, which is enough to facilitate interception of _os_nospin_lock_lock.
37+
struct _os_nospin_lock_s;
38+
using _os_nospin_lock_t = _os_nospin_lock_s *;
3339
}
3440
#endif // TARGET_OS_MAC
3541

@@ -711,6 +717,11 @@ INTERCEPTOR(void, os_unfair_lock_lock, os_unfair_lock_t lock) {
711717
__rtsan_notify_intercepted_call("os_unfair_lock_lock");
712718
return REAL(os_unfair_lock_lock)(lock);
713719
}
720+
721+
INTERCEPTOR(void, _os_nospin_lock_lock, _os_nospin_lock_t lock) {
722+
__rtsan_notify_intercepted_call("_os_nospin_lock_lock");
723+
return REAL(_os_nospin_lock_lock)(lock);
724+
}
714725
#define RTSAN_MAYBE_INTERCEPT_OS_UNFAIR_LOCK_LOCK \
715726
INTERCEPT_FUNCTION(os_unfair_lock_lock)
716727
#else

compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,6 +1122,25 @@ TEST(TestRtsanInterceptors, OsUnfairLockLockDiesWhenRealtime) {
11221122
ExpectRealtimeDeath(Func, "os_unfair_lock_lock");
11231123
ExpectNonRealtimeSurvival(Func);
11241124
}
1125+
1126+
// We intercept _os_nospin_lock_lock because it's the internal
1127+
// locking mechanism for MacOS's atomic implementation for data
1128+
// types that are larger than the hardware's maximum lock-free size.
1129+
// However, it's a private implementation detail and not visible in any headers,
1130+
// so we must duplicate the required type definitions to forward declaration
1131+
// what we need here.
1132+
extern "C" {
1133+
struct _os_nospin_lock_s {
1134+
unsigned int oul_value;
1135+
};
1136+
void _os_nospin_lock_lock(_os_nospin_lock_s *);
1137+
}
1138+
TEST(TestRtsanInterceptors, OsNoSpinLockLockDiesWhenRealtime) {
1139+
_os_nospin_lock_s lock{};
1140+
auto Func = [&]() { _os_nospin_lock_lock(&lock); };
1141+
ExpectRealtimeDeath(Func, "_os_nospin_lock_lock");
1142+
ExpectNonRealtimeSurvival(Func);
1143+
}
11251144
#endif
11261145

11271146
#if SANITIZER_LINUX

0 commit comments

Comments
 (0)