< prev index next >

test/hotspot/gtest/utilities/test_waitBarrier.cpp

Print this page
rev 53038 : 8214271: Fast primitive to wake many threads
Reviewed-by:
rev 53039 : [mq]: 8214271-3

@@ -27,11 +27,11 @@
 #include "runtime/os.hpp"
 #include "utilities/spinYield.hpp"
 #include "utilities/waitBarrier.hpp"
 #include "threadHelper.inline.hpp"
 
-static volatile int wait_tag = 1;
+static volatile int wait_tag = 0;
 static volatile int valid_value = 0;
 
 template <typename WaitBarrierImpl>
 class WBThread : public JavaTestThread {
 public:

@@ -44,16 +44,27 @@
     : JavaTestThread(post), _wait_barrier(wb), _wrt_start(wrt_start) {};
   virtual ~WBThread(){}
   void main_run() {
     _wrt_start->signal();
     int vv, tag;
+    // Similar to how a JavaThread would stop in a safepoint.
     while (!_exit) {
+      // Load the published tag.
       tag = OrderAccess::load_acquire(&wait_tag);
-      OrderAccess::release_store_fence(&_on_barrier, tag);
+      // Publish the tag this thread is going to wait for.
+      OrderAccess::release_store(&_on_barrier, tag);
+      if (_on_barrier == 0) {
+        SpinPause();
+        continue;
+      }
+      OrderAccess::storeload(); // Loads in WB must not float up.
+      // Wait until we are woken.
       _wait_barrier->wait(tag);
+      // Verify that we do not see an invalid value.
       vv = OrderAccess::load_acquire(&valid_value);
       ASSERT_EQ((vv & 0x1), 0);
+      OrderAccess::release_store(&_on_barrier, 0);
     }
   }
 };
 
 template <typename WaitBarrierImpl>

@@ -67,13 +78,11 @@
   virtual ~WBArmerThread(){}
   void main_run() {
     static const int NUMBER_OF_READERS = 4;
     Semaphore post;
     Semaphore wrt_start;
-    WaitBarrierType<WaitBarrierImpl> wb;
-
-    wait_tag = 2;
+    WaitBarrierType<WaitBarrierImpl> wb(this);
 
     WBThread<WaitBarrierImpl>* reader1 = new WBThread<WaitBarrierImpl>(&post, &wb, &wrt_start);
     WBThread<WaitBarrierImpl>* reader2 = new WBThread<WaitBarrierImpl>(&post, &wb, &wrt_start);
     WBThread<WaitBarrierImpl>* reader3 = new WBThread<WaitBarrierImpl>(&post, &wb, &wrt_start);
     WBThread<WaitBarrierImpl>* reader4 = new WBThread<WaitBarrierImpl>(&post, &wb, &wrt_start);

@@ -86,28 +95,45 @@
     int nw = NUMBER_OF_READERS;
     while (nw > 0) {
       wrt_start.wait();
       --nw;
     }
-    SpinYield sp;
     jlong stop_ms = os::javaTimeMillis() + 1000; // 1 seconds max test time
+    int next_tag = 1;
+    // Similar to how the VM thread would use a WaitBarrier in a safepoint.
     while (stop_ms > os::javaTimeMillis()) {
-      wb.arm(wait_tag + 1);
-      OrderAccess::release_store(&wait_tag, wait_tag + 1);
+      // Arm next tag.
+      wb.arm(next_tag);
+      // Publish tag.
+      OrderAccess::release_store_fence(&wait_tag, next_tag);
 
+      // Wait until threads picked up new tag.
       while (reader1->_on_barrier != wait_tag ||
              reader2->_on_barrier != wait_tag ||
              reader3->_on_barrier != wait_tag ||
              reader4->_on_barrier != wait_tag) {
-        sp.wait();
+        SpinPause();
       }
+
+      // Set an invalid value.
       OrderAccess::release_store(&valid_value, valid_value + 1); // odd
-      os::naked_short_sleep(1);
+      os::naked_yield();
+      // Set a valid value.
       OrderAccess::release_store(&valid_value, valid_value + 1); // even
-      OrderAccess::storestore(); // Stores in WB must not float up.
+      // Publish inactive tag.
+      OrderAccess::release_store_fence(&wait_tag, 0); // Stores in WB must not float up.
       wb.disarm();
       wb.wake();
+
+      // Wait until threads done valid_value verification.
+      while (reader1->_on_barrier != 0 ||
+             reader2->_on_barrier != 0 ||
+             reader3->_on_barrier != 0 ||
+             reader4->_on_barrier != 0) {
+        SpinPause();
+      }
+      ++next_tag;
     }
     WBThread<WaitBarrierImpl>::_exit = true;
     for (int i = 0; i < NUMBER_OF_READERS; i++) {
       post.wait();
     }
< prev index next >