forked from OSchip/llvm-project
Cleanup new cxa guard implementation.
* Add TSAN annotations around the futex syscalls. * Test that the futex syscall wrappers actually work. * Fix bad names. llvm-svn: 359069
This commit is contained in:
parent
b5f3984541
commit
5a235865f7
|
@ -70,6 +70,13 @@
|
|||
# error "Either BUILDING_CXA_GUARD or TESTING_CXA_GUARD must be defined"
|
||||
#endif
|
||||
|
||||
#if __has_feature(thread_sanitizer)
|
||||
extern "C" void __tsan_acquire(void*);
|
||||
extern "C" void __tsan_release(void*);
|
||||
#else
|
||||
#define __tsan_acquire(addr) ((void)0)
|
||||
#define __tsan_release(addr) ((void)0)
|
||||
#endif
|
||||
|
||||
namespace __cxxabiv1 {
|
||||
// Use an anonymous namespace to ensure that the tests and actual implementation
|
||||
|
@ -116,7 +123,7 @@ constexpr uint32_t (*PlatformThreadID)() = nullptr;
|
|||
#endif
|
||||
|
||||
|
||||
constexpr bool DoesPlatformSupportThreadID() {
|
||||
constexpr bool PlatformSupportsThreadID() {
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
|
||||
|
@ -265,7 +272,7 @@ struct InitByteGlobalMutex
|
|||
explicit InitByteGlobalMutex(uint32_t *g)
|
||||
: BaseT(g), has_thread_id_support(false) {}
|
||||
explicit InitByteGlobalMutex(uint64_t *g)
|
||||
: BaseT(g), has_thread_id_support(DoesPlatformSupportThreadID()) {}
|
||||
: BaseT(g), has_thread_id_support(PlatformSupportsThreadID()) {}
|
||||
|
||||
public:
|
||||
AcquireResult acquire_init_byte() {
|
||||
|
@ -358,9 +365,11 @@ private:
|
|||
void PlatformFutexWait(int* addr, int expect) {
|
||||
constexpr int WAIT = 0;
|
||||
syscall(SYS_futex, addr, WAIT, expect, 0);
|
||||
__tsan_acquire(addr);
|
||||
}
|
||||
void PlatformFutexWake(int* addr) {
|
||||
constexpr int WAKE = 1;
|
||||
__tsan_release(addr);
|
||||
syscall(SYS_futex, addr, WAKE, INT_MAX);
|
||||
}
|
||||
#else
|
||||
|
@ -368,7 +377,7 @@ constexpr void (*PlatformFutexWait)(int*, int) = nullptr;
|
|||
constexpr void (*PlatformFutexWake)(int*) = nullptr;
|
||||
#endif
|
||||
|
||||
constexpr bool DoesPlatformSupportFutex() {
|
||||
constexpr bool PlatformSupportsFutex() {
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
|
||||
|
@ -539,7 +548,7 @@ constexpr Implementation CurrentImplementation =
|
|||
#endif
|
||||
|
||||
static_assert(CurrentImplementation != Implementation::Futex
|
||||
|| DoesPlatformSupportFutex(), "Futex selected but not supported");
|
||||
|| PlatformSupportsFutex(), "Futex selected but not supported");
|
||||
|
||||
using SelectedImplementation =
|
||||
SelectImplementation<CurrentImplementation>::type;
|
||||
|
|
|
@ -129,7 +129,7 @@ int main() {
|
|||
#if defined(__APPLE__) || defined(__linux__)
|
||||
assert(PlatformThreadID);
|
||||
#endif
|
||||
if (+PlatformThreadID) {
|
||||
if (PlatformSupportsThreadID()) {
|
||||
assert(PlatformThreadID() != 0);
|
||||
assert(PlatformThreadID() == PlatformThreadID());
|
||||
}
|
||||
|
|
|
@ -356,14 +356,14 @@ void test_impl() {
|
|||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
void test_all_impls() {
|
||||
using MutexImpl = SelectImplementation<Implementation::GlobalLock>::type;
|
||||
|
||||
// Attempt to test the Futex based implementation if it's supported on the
|
||||
// target platform.
|
||||
using RealFutexImpl = SelectImplementation<Implementation::Futex>::type;
|
||||
using FutexImpl = typename std::conditional<
|
||||
DoesPlatformSupportFutex(),
|
||||
PlatformSupportsFutex(),
|
||||
RealFutexImpl,
|
||||
MutexImpl
|
||||
>::type;
|
||||
|
@ -372,7 +372,48 @@ int main() {
|
|||
const int num_runs = 5;
|
||||
for (int i=0; i < num_runs; ++i) {
|
||||
test_impl<MutexImpl>();
|
||||
if (DoesPlatformSupportFutex())
|
||||
if (PlatformSupportsFutex())
|
||||
test_impl<FutexImpl>();
|
||||
}
|
||||
}
|
||||
|
||||
// A dummy
|
||||
template <bool Dummy = true>
|
||||
void test_futex_syscall() {
|
||||
if (!PlatformSupportsFutex())
|
||||
return;
|
||||
int lock1 = 0;
|
||||
int lock2 = 0;
|
||||
int lock3 = 0;
|
||||
std::thread waiter1([&]() {
|
||||
int expect = 0;
|
||||
PlatformFutexWait(&lock1, expect);
|
||||
assert(lock1 == 1);
|
||||
});
|
||||
std::thread waiter2([&]() {
|
||||
int expect = 0;
|
||||
PlatformFutexWait(&lock2, expect);
|
||||
assert(lock2 == 2);
|
||||
});
|
||||
std::thread waiter3([&]() {
|
||||
int expect = 42; // not the value
|
||||
PlatformFutexWait(&lock3, expect); // doesn't block
|
||||
});
|
||||
std::thread waker([&]() {
|
||||
lock1 = 1;
|
||||
PlatformFutexWake(&lock1);
|
||||
lock2 = 2;
|
||||
PlatformFutexWake(&lock2);
|
||||
});
|
||||
waiter1.join();
|
||||
waiter2.join();
|
||||
waiter3.join();
|
||||
waker.join();
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Test each multi-threaded implementation with real threads.
|
||||
test_all_impls();
|
||||
// Test the basic sanity of the futex syscall wrappers.
|
||||
test_futex_syscall();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue