Make folly pass TSAN checks
[folly.git] / folly / test / SpinLockTest.cpp
index 7ce90d71e9aee48d9801b591ba0bcb4a17948e89..67279a700f82367151b122f673fcb118616c2617 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 #include <folly/SpinLock.h>
 
-#include <gtest/gtest.h>
+#include <folly/Random.h>
+
 #include <thread>
 
+#include <folly/portability/Asm.h>
+#include <folly/portability/GTest.h>
+
 using folly::SpinLockGuardImpl;
 
 namespace {
@@ -35,17 +40,17 @@ struct LockedVal {
 template <typename LOCK>
 void spinlockTestThread(LockedVal<LOCK>* v) {
   const int max = 1000;
-  unsigned int seed = (uintptr_t)pthread_self();
+  auto rng = folly::ThreadLocalPRNG();
   for (int i = 0; i < max; i++) {
-    asm("pause");
+    folly::asm_pause();
     SpinLockGuardImpl<LOCK> g(v->lock);
 
     int first = v->ar[0];
-    for (size_t i = 1; i < sizeof v->ar / sizeof i; ++i) {
-      EXPECT_EQ(first, v->ar[i]);
+    for (size_t j = 1; j < sizeof v->ar / sizeof j; ++j) {
+      EXPECT_EQ(first, v->ar[j]);
     }
 
-    int byte = rand_r(&seed);
+    int byte = folly::Random::rand32(rng);
     memset(v->ar, char(byte), sizeof v->ar);
   }
 }
@@ -62,17 +67,20 @@ struct TryLockState {
 template <typename LOCK>
 void trylockTestThread(TryLockState<LOCK>* state, size_t count) {
   while (true) {
-    asm("pause");
+    folly::asm_pause();
+    bool ret = state->lock2.try_lock();
     SpinLockGuardImpl<LOCK> g(state->lock1);
     if (state->obtained >= count) {
+      if (ret) {
+        state->lock2.unlock();
+      }
       break;
     }
 
-    bool ret = state->lock2.trylock();
-    EXPECT_NE(state->locked, ret);
 
     if (ret) {
       // We got lock2.
+      EXPECT_NE(state->locked, ret);
       ++state->obtained;
       state->locked = true;
 
@@ -81,7 +89,7 @@ void trylockTestThread(TryLockState<LOCK>* state, size_t count) {
       auto oldFailed = state->failed;
       while (state->failed == oldFailed && state->obtained < count) {
         state->lock1.unlock();
-        asm("pause");
+        folly::asm_pause();
         state->lock1.lock();
       }
 
@@ -128,36 +136,9 @@ void trylockTest() {
 
 } // unnamed namespace
 
-#if __x86_64__
-TEST(SpinLock, MslCorrectness) {
-  correctnessTest<folly::SpinLockMslImpl>();
-}
-TEST(SpinLock, MslTryLock) {
-  trylockTest<folly::SpinLockMslImpl>();
-}
-#endif
-
-#if __APPLE__
-TEST(SpinLock, AppleCorrectness) {
-  correctnessTest<folly::SpinLockAppleImpl>();
-}
-TEST(SpinLock, AppleTryLock) {
-  trylockTest<folly::SpinLockAppleImpl>();
-}
-#endif
-
-#if FOLLY_HAVE_PTHREAD_SPINLOCK_T
-TEST(SpinLock, PthreadCorrectness) {
-  correctnessTest<folly::SpinLockPthreadImpl>();
-}
-TEST(SpinLock, PthreadTryLock) {
-  trylockTest<folly::SpinLockPthreadImpl>();
-}
-#endif
-
-TEST(SpinLock, MutexCorrectness) {
-  correctnessTest<folly::SpinLockPthreadMutexImpl>();
+TEST(SpinLock, Correctness) {
+  correctnessTest<folly::SpinLock>();
 }
-TEST(SpinLock, MutexTryLock) {
-  trylockTest<folly::SpinLockPthreadMutexImpl>();
+TEST(SpinLock, TryLock) {
+  trylockTest<folly::SpinLock>();
 }