< 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 >