[RTSan][Darwin] Adjust OSSpinLock/_os_nospin_lock interceptor and tests (#132867)
These changes align with these lock types and allows builds and tests to pass with various SDKS. rdar://147067322
This commit is contained in:
parent
3191cfd824
commit
7cc4472037
@ -21,24 +21,6 @@
|
|||||||
#include "rtsan/rtsan.h"
|
#include "rtsan/rtsan.h"
|
||||||
|
|
||||||
#if SANITIZER_APPLE
|
#if SANITIZER_APPLE
|
||||||
|
|
||||||
#if TARGET_OS_MAC
|
|
||||||
// On MacOS OSSpinLockLock is deprecated and no longer present in the headers,
|
|
||||||
// but the symbol still exists on the system. Forward declare here so we
|
|
||||||
// don't get compilation errors.
|
|
||||||
#include <stdint.h>
|
|
||||||
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
|
|
||||||
|
|
||||||
#include <libkern/OSAtomic.h>
|
#include <libkern/OSAtomic.h>
|
||||||
#include <os/lock.h>
|
#include <os/lock.h>
|
||||||
#endif // SANITIZER_APPLE
|
#endif // SANITIZER_APPLE
|
||||||
@ -717,26 +699,35 @@ INTERCEPTOR(mode_t, umask, mode_t cmask) {
|
|||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
// OSSpinLockLock is deprecated, but still in use in libc++
|
// OSSpinLockLock is deprecated, but still in use in libc++
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
#undef OSSpinLockLock
|
||||||
|
|
||||||
INTERCEPTOR(void, OSSpinLockLock, volatile OSSpinLock *lock) {
|
INTERCEPTOR(void, OSSpinLockLock, volatile OSSpinLock *lock) {
|
||||||
__rtsan_notify_intercepted_call("OSSpinLockLock");
|
__rtsan_notify_intercepted_call("OSSpinLockLock");
|
||||||
return REAL(OSSpinLockLock)(lock);
|
return REAL(OSSpinLockLock)(lock);
|
||||||
}
|
}
|
||||||
#pragma clang diagnostic pop
|
|
||||||
#define RTSAN_MAYBE_INTERCEPT_OSSPINLOCKLOCK INTERCEPT_FUNCTION(OSSpinLockLock)
|
#define RTSAN_MAYBE_INTERCEPT_OSSPINLOCKLOCK INTERCEPT_FUNCTION(OSSpinLockLock)
|
||||||
#else
|
#else
|
||||||
#define RTSAN_MAYBE_INTERCEPT_OSSPINLOCKLOCK
|
#define RTSAN_MAYBE_INTERCEPT_OSSPINLOCKLOCK
|
||||||
#endif // SANITIZER_APPLE
|
#endif // SANITIZER_APPLE
|
||||||
|
|
||||||
|
#if SANITIZER_APPLE
|
||||||
|
// _os_nospin_lock_lock may replace OSSpinLockLock due to deprecation macro.
|
||||||
|
typedef volatile OSSpinLock *_os_nospin_lock_t;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
#pragma clang diagnostic pop // "-Wdeprecated-declarations"
|
||||||
|
#endif // SANITIZER_APPLE
|
||||||
|
|
||||||
#if SANITIZER_APPLE
|
#if SANITIZER_APPLE
|
||||||
INTERCEPTOR(void, os_unfair_lock_lock, os_unfair_lock_t lock) {
|
INTERCEPTOR(void, os_unfair_lock_lock, os_unfair_lock_t lock) {
|
||||||
__rtsan_notify_intercepted_call("os_unfair_lock_lock");
|
__rtsan_notify_intercepted_call("os_unfair_lock_lock");
|
||||||
return REAL(os_unfair_lock_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 \
|
#define RTSAN_MAYBE_INTERCEPT_OS_UNFAIR_LOCK_LOCK \
|
||||||
INTERCEPT_FUNCTION(os_unfair_lock_lock)
|
INTERCEPT_FUNCTION(os_unfair_lock_lock)
|
||||||
#else
|
#else
|
||||||
|
@ -1126,10 +1126,18 @@ TEST(TestRtsanInterceptors, PthreadJoinDiesWhenRealtime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if SANITIZER_APPLE
|
#if SANITIZER_APPLE
|
||||||
|
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
// OSSpinLockLock is deprecated, but still in use in libc++
|
// OSSpinLockLock is deprecated, but still in use in libc++
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
#undef OSSpinLockLock
|
||||||
|
extern "C" {
|
||||||
|
typedef int32_t OSSpinLock;
|
||||||
|
void OSSpinLockLock(volatile OSSpinLock *__lock);
|
||||||
|
// _os_nospin_lock_lock may replace OSSpinLockLock due to deprecation macro.
|
||||||
|
typedef volatile OSSpinLock *_os_nospin_lock_t;
|
||||||
|
void _os_nospin_lock_lock(_os_nospin_lock_t lock);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(TestRtsanInterceptors, OsSpinLockLockDiesWhenRealtime) {
|
TEST(TestRtsanInterceptors, OsSpinLockLockDiesWhenRealtime) {
|
||||||
auto Func = []() {
|
auto Func = []() {
|
||||||
OSSpinLock spin_lock{};
|
OSSpinLock spin_lock{};
|
||||||
@ -1138,7 +1146,14 @@ TEST(TestRtsanInterceptors, OsSpinLockLockDiesWhenRealtime) {
|
|||||||
ExpectRealtimeDeath(Func, "OSSpinLockLock");
|
ExpectRealtimeDeath(Func, "OSSpinLockLock");
|
||||||
ExpectNonRealtimeSurvival(Func);
|
ExpectNonRealtimeSurvival(Func);
|
||||||
}
|
}
|
||||||
#pragma clang diagnostic pop
|
|
||||||
|
TEST(TestRtsanInterceptors, OsNoSpinLockLockDiesWhenRealtime) {
|
||||||
|
OSSpinLock lock{};
|
||||||
|
auto Func = [&]() { _os_nospin_lock_lock(&lock); };
|
||||||
|
ExpectRealtimeDeath(Func, "_os_nospin_lock_lock");
|
||||||
|
ExpectNonRealtimeSurvival(Func);
|
||||||
|
}
|
||||||
|
#pragma clang diagnostic pop //"-Wdeprecated-declarations"
|
||||||
|
|
||||||
TEST(TestRtsanInterceptors, OsUnfairLockLockDiesWhenRealtime) {
|
TEST(TestRtsanInterceptors, OsUnfairLockLockDiesWhenRealtime) {
|
||||||
auto Func = []() {
|
auto Func = []() {
|
||||||
@ -1148,26 +1163,7 @@ TEST(TestRtsanInterceptors, OsUnfairLockLockDiesWhenRealtime) {
|
|||||||
ExpectRealtimeDeath(Func, "os_unfair_lock_lock");
|
ExpectRealtimeDeath(Func, "os_unfair_lock_lock");
|
||||||
ExpectNonRealtimeSurvival(Func);
|
ExpectNonRealtimeSurvival(Func);
|
||||||
}
|
}
|
||||||
|
#endif // SANITIZER_APPLE
|
||||||
// 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
|
#if SANITIZER_LINUX
|
||||||
TEST(TestRtsanInterceptors, SpinLockLockDiesWhenRealtime) {
|
TEST(TestRtsanInterceptors, SpinLockLockDiesWhenRealtime) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user