[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)
This commit is contained in:
parent
4370072022
commit
f811c7df0a
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user