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:
Eric Fiselier 2019-04-24 04:21:05 +00:00
parent b5f3984541
commit 5a235865f7
3 changed files with 58 additions and 8 deletions

View File

@ -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;

View File

@ -129,7 +129,7 @@ int main() {
#if defined(__APPLE__) || defined(__linux__)
assert(PlatformThreadID);
#endif
if (+PlatformThreadID) {
if (PlatformSupportsThreadID()) {
assert(PlatformThreadID() != 0);
assert(PlatformThreadID() == PlatformThreadID());
}

View File

@ -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();
}