Cleanup new cxa guard implementation.

* Add TSAN annotations around the futex syscalls.
* Test that the futex syscall wrappers actually work.
* Fix bad names.

git-svn-id: https://llvm.org/svn/llvm-project/libcxxabi/trunk@359069 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/src/cxa_guard_impl.h b/src/cxa_guard_impl.h
index 8c31848..ea82d20 100644
--- a/src/cxa_guard_impl.h
+++ b/src/cxa_guard_impl.h
@@ -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 @@
 #endif
 
 
-constexpr bool DoesPlatformSupportThreadID() {
+constexpr bool PlatformSupportsThreadID() {
 #ifdef __clang__
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wtautological-pointer-compare"
@@ -265,7 +272,7 @@
   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 @@
 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 (*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 @@
 #endif
 
 static_assert(CurrentImplementation != Implementation::Futex
-           || DoesPlatformSupportFutex(), "Futex selected but not supported");
+           || PlatformSupportsFutex(), "Futex selected but not supported");
 
 using SelectedImplementation =
     SelectImplementation<CurrentImplementation>::type;
diff --git a/test/guard_test_basic.pass.cpp b/test/guard_test_basic.pass.cpp
index e04d694..a325dd0 100644
--- a/test/guard_test_basic.pass.cpp
+++ b/test/guard_test_basic.pass.cpp
@@ -129,7 +129,7 @@
 #if defined(__APPLE__) || defined(__linux__)
     assert(PlatformThreadID);
 #endif
-    if (+PlatformThreadID) {
+    if (PlatformSupportsThreadID()) {
       assert(PlatformThreadID() != 0);
       assert(PlatformThreadID() == PlatformThreadID());
     }
diff --git a/test/guard_threaded_test.pass.cpp b/test/guard_threaded_test.pass.cpp
index e38e132..e46af56 100644
--- a/test/guard_threaded_test.pass.cpp
+++ b/test/guard_threaded_test.pass.cpp
@@ -356,14 +356,14 @@
   }
 }
 
-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 @@
   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();
+}