Skip to content

Commit 5a23586

Browse files
committed
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
1 parent b5f3984 commit 5a23586

File tree

3 files changed

+58
-8
lines changed

3 files changed

+58
-8
lines changed

libcxxabi/src/cxa_guard_impl.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@
7070
# error "Either BUILDING_CXA_GUARD or TESTING_CXA_GUARD must be defined"
7171
#endif
7272

73+
#if __has_feature(thread_sanitizer)
74+
extern "C" void __tsan_acquire(void*);
75+
extern "C" void __tsan_release(void*);
76+
#else
77+
#define __tsan_acquire(addr) ((void)0)
78+
#define __tsan_release(addr) ((void)0)
79+
#endif
7380

7481
namespace __cxxabiv1 {
7582
// Use an anonymous namespace to ensure that the tests and actual implementation
@@ -116,7 +123,7 @@ constexpr uint32_t (*PlatformThreadID)() = nullptr;
116123
#endif
117124

118125

119-
constexpr bool DoesPlatformSupportThreadID() {
126+
constexpr bool PlatformSupportsThreadID() {
120127
#ifdef __clang__
121128
#pragma clang diagnostic push
122129
#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
@@ -265,7 +272,7 @@ struct InitByteGlobalMutex
265272
explicit InitByteGlobalMutex(uint32_t *g)
266273
: BaseT(g), has_thread_id_support(false) {}
267274
explicit InitByteGlobalMutex(uint64_t *g)
268-
: BaseT(g), has_thread_id_support(DoesPlatformSupportThreadID()) {}
275+
: BaseT(g), has_thread_id_support(PlatformSupportsThreadID()) {}
269276

270277
public:
271278
AcquireResult acquire_init_byte() {
@@ -358,17 +365,19 @@ struct InitByteGlobalMutex
358365
void PlatformFutexWait(int* addr, int expect) {
359366
constexpr int WAIT = 0;
360367
syscall(SYS_futex, addr, WAIT, expect, 0);
368+
__tsan_acquire(addr);
361369
}
362370
void PlatformFutexWake(int* addr) {
363371
constexpr int WAKE = 1;
372+
__tsan_release(addr);
364373
syscall(SYS_futex, addr, WAKE, INT_MAX);
365374
}
366375
#else
367376
constexpr void (*PlatformFutexWait)(int*, int) = nullptr;
368377
constexpr void (*PlatformFutexWake)(int*) = nullptr;
369378
#endif
370379

371-
constexpr bool DoesPlatformSupportFutex() {
380+
constexpr bool PlatformSupportsFutex() {
372381
#ifdef __clang__
373382
#pragma clang diagnostic push
374383
#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
@@ -539,7 +548,7 @@ constexpr Implementation CurrentImplementation =
539548
#endif
540549

541550
static_assert(CurrentImplementation != Implementation::Futex
542-
|| DoesPlatformSupportFutex(), "Futex selected but not supported");
551+
|| PlatformSupportsFutex(), "Futex selected but not supported");
543552

544553
using SelectedImplementation =
545554
SelectImplementation<CurrentImplementation>::type;

libcxxabi/test/guard_test_basic.pass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ int main() {
129129
#if defined(__APPLE__) || defined(__linux__)
130130
assert(PlatformThreadID);
131131
#endif
132-
if (+PlatformThreadID) {
132+
if (PlatformSupportsThreadID()) {
133133
assert(PlatformThreadID() != 0);
134134
assert(PlatformThreadID() == PlatformThreadID());
135135
}

libcxxabi/test/guard_threaded_test.pass.cpp

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,14 +356,14 @@ void test_impl() {
356356
}
357357
}
358358

359-
int main() {
359+
void test_all_impls() {
360360
using MutexImpl = SelectImplementation<Implementation::GlobalLock>::type;
361361

362362
// Attempt to test the Futex based implementation if it's supported on the
363363
// target platform.
364364
using RealFutexImpl = SelectImplementation<Implementation::Futex>::type;
365365
using FutexImpl = typename std::conditional<
366-
DoesPlatformSupportFutex(),
366+
PlatformSupportsFutex(),
367367
RealFutexImpl,
368368
MutexImpl
369369
>::type;
@@ -372,7 +372,48 @@ int main() {
372372
const int num_runs = 5;
373373
for (int i=0; i < num_runs; ++i) {
374374
test_impl<MutexImpl>();
375-
if (DoesPlatformSupportFutex())
375+
if (PlatformSupportsFutex())
376376
test_impl<FutexImpl>();
377377
}
378378
}
379+
380+
// A dummy
381+
template <bool Dummy = true>
382+
void test_futex_syscall() {
383+
if (!PlatformSupportsFutex())
384+
return;
385+
int lock1 = 0;
386+
int lock2 = 0;
387+
int lock3 = 0;
388+
std::thread waiter1([&]() {
389+
int expect = 0;
390+
PlatformFutexWait(&lock1, expect);
391+
assert(lock1 == 1);
392+
});
393+
std::thread waiter2([&]() {
394+
int expect = 0;
395+
PlatformFutexWait(&lock2, expect);
396+
assert(lock2 == 2);
397+
});
398+
std::thread waiter3([&]() {
399+
int expect = 42; // not the value
400+
PlatformFutexWait(&lock3, expect); // doesn't block
401+
});
402+
std::thread waker([&]() {
403+
lock1 = 1;
404+
PlatformFutexWake(&lock1);
405+
lock2 = 2;
406+
PlatformFutexWake(&lock2);
407+
});
408+
waiter1.join();
409+
waiter2.join();
410+
waiter3.join();
411+
waker.join();
412+
}
413+
414+
int main() {
415+
// Test each multi-threaded implementation with real threads.
416+
test_all_impls();
417+
// Test the basic sanity of the futex syscall wrappers.
418+
test_futex_syscall();
419+
}

0 commit comments

Comments
 (0)