Author: davidtrevelyan Date: 2025-05-10T11:01:54-07:00 New Revision: f811c7df0a105549aeae2aa42ca31f6d55e652f2
URL: https://github.com/llvm/llvm-project/commit/f811c7df0a105549aeae2aa42ca31f6d55e652f2 DIFF: https://github.com/llvm/llvm-project/commit/f811c7df0a105549aeae2aa42ca31f6d55e652f2.diff LOG: [rtsan][Apple] Add interceptor for _os_nospin_lock_lock (#131034) Follows the discussion here: https://github.com/llvm/llvm-project/pull/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._ (cherry picked from commit 481a55a3d9645a6bc1540d326319b78ad8ed8db1) Added: Modified: compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp Removed: ################################################################################ diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp index 6816119065263..4d602a88ba9ae 100644 --- a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp +++ b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp @@ -30,6 +30,12 @@ extern "C" { typedef int32_t OSSpinLock; void OSSpinLockLock(volatile OSSpinLock *__lock); +// A pointer to this type is in the interface for `_os_nospin_lock_lock`, but +// it's an internal implementation detail of `os/lock.c` on Darwin, and +// therefore not available in any headers. As a workaround, we forward declare +// it here, which is enough to facilitate interception of _os_nospin_lock_lock. +struct _os_nospin_lock_s; +using _os_nospin_lock_t = _os_nospin_lock_s *; } #endif // TARGET_OS_MAC @@ -642,6 +648,11 @@ INTERCEPTOR(void, os_unfair_lock_lock, os_unfair_lock_t lock) { __rtsan_notify_intercepted_call("os_unfair_lock_lock"); return REAL(os_unfair_lock_lock)(lock); } + +INTERCEPTOR(void, _os_nospin_lock_lock, _os_nospin_lock_t lock) { + __rtsan_notify_intercepted_call("_os_nospin_lock_lock"); + return REAL(_os_nospin_lock_lock)(lock); +} #define RTSAN_MAYBE_INTERCEPT_OS_UNFAIR_LOCK_LOCK \ INTERCEPT_FUNCTION(os_unfair_lock_lock) #else diff --git a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp index 59663776366bb..75f723081c4b6 100644 --- a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp +++ b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp @@ -1058,6 +1058,25 @@ TEST(TestRtsanInterceptors, OsUnfairLockLockDiesWhenRealtime) { ExpectRealtimeDeath(Func, "os_unfair_lock_lock"); ExpectNonRealtimeSurvival(Func); } + +// We intercept _os_nospin_lock_lock because it's the internal +// locking mechanism for MacOS's atomic implementation for data +// types that are larger than the hardware's maximum lock-free size. +// However, it's a private implementation detail and not visible in any headers, +// so we must duplicate the required type definitions to forward declaration +// what we need here. +extern "C" { +struct _os_nospin_lock_s { + unsigned int oul_value; +}; +void _os_nospin_lock_lock(_os_nospin_lock_s *); +} +TEST(TestRtsanInterceptors, OsNoSpinLockLockDiesWhenRealtime) { + _os_nospin_lock_s lock{}; + auto Func = [&]() { _os_nospin_lock_lock(&lock); }; + ExpectRealtimeDeath(Func, "_os_nospin_lock_lock"); + ExpectNonRealtimeSurvival(Func); +} #endif #if SANITIZER_LINUX _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits