Fixes RCU test cases error (loads should use Consume ordering)
[folly.git] / folly / stress-test / stress-parallel-folly-sync.cpp
index addc92ce94b1fb8dfb5288baf7292b5624409694..c1b6ed573e31171dfe4ea4e1914c472cfca7ea13 100644 (file)
@@ -11,7 +11,7 @@ protected:
   // For RCU, we mostly want to benchmark the readers (cause it's designed for
   // very fast readers and occasional writers). We have a writer thread that
   // runs nonstop until all other reader threads are done.
   // For RCU, we mostly want to benchmark the readers (cause it's designed for
   // very fast readers and occasional writers). We have a writer thread that
   // runs nonstop until all other reader threads are done.
-  static std::atomic_bool rcu_readers_done;
+  static std::atomic_uint rcu_readers_num;
   // MicroLock
   static size_t s_nMicroLockPassCount;
   // MicroSpinLock
   // MicroLock
   static size_t s_nMicroLockPassCount;
   // MicroSpinLock
@@ -55,12 +55,12 @@ protected:
   }
 
   static void run_rcu_writer_sync() {
   }
 
   static void run_rcu_writer_sync() {
-    while (!rcu_readers_done.load(std::memory_order_acquire)) {
-      auto *old_data = rcu_data.load(std::memory_order_relaxed);
+    while (rcu_readers_num.load(std::memory_order_acquire) > 0) {
+      auto *old_data = rcu_data.load(std::memory_order_consume);
       auto *new_data = new RcuData(*old_data);
       new_data->d1++;
       new_data->d2++;
       auto *new_data = new RcuData(*old_data);
       new_data->d1++;
       new_data->d2++;
-      rcu_data.store(new_data, std::memory_order_relaxed);
+      rcu_data.store(new_data, std::memory_order_release);
       folly::synchronize_rcu();
       delete old_data;
       std::this_thread::sleep_for(
       folly::synchronize_rcu();
       delete old_data;
       std::this_thread::sleep_for(
@@ -69,12 +69,12 @@ protected:
   }
 
   static void run_rcu_writer_no_sync() {
   }
 
   static void run_rcu_writer_no_sync() {
-    while (!rcu_readers_done.load(std::memory_order_acquire)) {
-      auto *old_data = rcu_data.load(std::memory_order_relaxed);
+    while (rcu_readers_num.load(std::memory_order_acquire) > 0) {
+      auto *old_data = rcu_data.load(std::memory_order_consume);
       auto *new_data = new RcuData(*old_data);
       new_data->d1++;
       new_data->d2++;
       auto *new_data = new RcuData(*old_data);
       new_data->d1++;
       new_data->d2++;
-      rcu_data.store(new_data, std::memory_order_relaxed);
+      rcu_data.store(new_data, std::memory_order_release);
       folly::rcu_retire(old_data);
       std::this_thread::sleep_for(
           std::chrono::milliseconds(s_nRcuWriterFrequency));
       folly::rcu_retire(old_data);
       std::this_thread::sleep_for(
           std::chrono::milliseconds(s_nRcuWriterFrequency));
@@ -85,10 +85,10 @@ protected:
     size_t sum = 0;
     for (size_t count = 0; count < pass_count; count++) {
       folly::rcu_reader g;
     size_t sum = 0;
     for (size_t count = 0; count < pass_count; count++) {
       folly::rcu_reader g;
-      auto *data = rcu_data.load(std::memory_order_relaxed);
+      auto *data = rcu_data.load(std::memory_order_consume);
       sum += (data->d1 + data->d2);
     }
       sum += (data->d1 + data->d2);
     }
-    std::cout << "Reader done" << std::endl;
+    rcu_readers_num.fetch_sub(1, std::memory_order_release);
     // Just want to simulate the reading.
     EXPECT_GT(sum, 0);
   }
     // Just want to simulate the reading.
     EXPECT_GT(sum, 0);
   }
@@ -133,20 +133,17 @@ protected:
 
   template <typename WriterFunc>
   static void FollyRcuThreading(WriterFunc writer_func) {
 
   template <typename WriterFunc>
   static void FollyRcuThreading(WriterFunc writer_func) {
+    rcu_readers_num.store(s_nThreadCount - 1, std::memory_order_release);
+
+    std::unique_ptr<std::thread[]> threads(new std::thread[s_nThreadCount]);
     // One of the threads is a writer.
     // One of the threads is a writer.
-    size_t reader_thrd_cnt = s_nThreadCount - 1;
-    rcu_readers_done.store(false, std::memory_order_release);
-    std::unique_ptr<std::thread[]> reader_threads(
-        new std::thread[reader_thrd_cnt]);
-    std::thread writer_thread(writer_func);
-    for (size_t i = 0; i < reader_thrd_cnt; i++) {
-      reader_threads[i] = std::thread(run_rcu_reader, s_nRcuReaderPassCount);
+    threads[0] = std::thread(writer_func);
+    for (size_t i = 1; i < s_nThreadCount; i++) {
+      threads[i] = std::thread(run_rcu_reader, s_nRcuReaderPassCount);
     }
     }
-    for (size_t i = 0; i < reader_thrd_cnt; i++) {
-      reader_threads[i].join();
+    for (size_t i = 0; i < s_nThreadCount; i++) {
+      threads[i].join();
     }
     }
-    rcu_readers_done.store(true, std::memory_order_release);
-    writer_thread.join();
   }
 
   template <typename SmallLockType>
   }
 
   template <typename SmallLockType>
@@ -169,7 +166,7 @@ protected:
 
 size_t FollySyncTest_Parallel::locked_data;
 std::atomic<RcuData*> FollySyncTest_Parallel::rcu_data;
 
 size_t FollySyncTest_Parallel::locked_data;
 std::atomic<RcuData*> FollySyncTest_Parallel::rcu_data;
-std::atomic_bool FollySyncTest_Parallel::rcu_readers_done;
+std::atomic_uint FollySyncTest_Parallel::rcu_readers_num;
 size_t FollySyncTest_Parallel::s_nThreadCount;
 size_t FollySyncTest_Parallel::s_nMicroLockPassCount;
 size_t FollySyncTest_Parallel::s_nMicroSpinLockPassCount;
 size_t FollySyncTest_Parallel::s_nThreadCount;
 size_t FollySyncTest_Parallel::s_nMicroLockPassCount;
 size_t FollySyncTest_Parallel::s_nMicroSpinLockPassCount;