Path: blob/master/test/hotspot/gtest/utilities/test_waitBarrier.cpp
41144 views
/*1* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223#include "precompiled.hpp"24#include "runtime/atomic.hpp"25#include "runtime/orderAccess.hpp"26#include "runtime/os.hpp"27#include "utilities/spinYield.hpp"28#include "utilities/waitBarrier.hpp"29#include "threadHelper.inline.hpp"3031static volatile int wait_tag = 0;32static volatile int valid_value = 0;3334template <typename WaitBarrierImpl>35class WBThread : public JavaTestThread {36public:37static volatile bool _exit;38WaitBarrierType<WaitBarrierImpl>* _wait_barrier;39Semaphore* _wrt_start;40volatile int _on_barrier;4142WBThread(Semaphore* post, WaitBarrierType<WaitBarrierImpl>* wb, Semaphore* wrt_start)43: JavaTestThread(post), _wait_barrier(wb), _wrt_start(wrt_start) {};44virtual ~WBThread(){}45void main_run() {46_wrt_start->signal();47int vv, tag;48// Similar to how a JavaThread would stop in a safepoint.49while (!_exit) {50// Load the published tag.51tag = Atomic::load_acquire(&wait_tag);52// Publish the tag this thread is going to wait for.53Atomic::release_store(&_on_barrier, tag);54if (_on_barrier == 0) {55SpinPause();56continue;57}58OrderAccess::storeload(); // Loads in WB must not float up.59// Wait until we are woken.60_wait_barrier->wait(tag);61// Verify that we do not see an invalid value.62vv = Atomic::load_acquire(&valid_value);63ASSERT_EQ((vv & 0x1), 0);64Atomic::release_store(&_on_barrier, 0);65}66}67};6869template <typename WaitBarrierImpl>70volatile bool WBThread<WaitBarrierImpl>::_exit = false;7172template <typename WaitBarrierImpl>73class WBArmerThread : public JavaTestThread {74public:75WBArmerThread(Semaphore* post) : JavaTestThread(post) {76};77virtual ~WBArmerThread(){}78void main_run() {79static const int NUMBER_OF_READERS = 4;80Semaphore post;81Semaphore wrt_start;82WaitBarrierType<WaitBarrierImpl> wb(this);8384WBThread<WaitBarrierImpl>* reader1 = new WBThread<WaitBarrierImpl>(&post, &wb, &wrt_start);85WBThread<WaitBarrierImpl>* reader2 = new WBThread<WaitBarrierImpl>(&post, &wb, &wrt_start);86WBThread<WaitBarrierImpl>* reader3 = new WBThread<WaitBarrierImpl>(&post, &wb, &wrt_start);87WBThread<WaitBarrierImpl>* reader4 = new WBThread<WaitBarrierImpl>(&post, &wb, &wrt_start);8889reader1->doit();90reader2->doit();91reader3->doit();92reader4->doit();9394int nw = NUMBER_OF_READERS;95while (nw > 0) {96wrt_start.wait();97--nw;98}99jlong stop_ms = os::javaTimeMillis() + 1000; // 1 seconds max test time100int next_tag = 1;101// Similar to how the VM thread would use a WaitBarrier in a safepoint.102while (stop_ms > os::javaTimeMillis()) {103// Arm next tag.104wb.arm(next_tag);105// Publish tag.106Atomic::release_store_fence(&wait_tag, next_tag);107108// Wait until threads picked up new tag.109while (reader1->_on_barrier != wait_tag ||110reader2->_on_barrier != wait_tag ||111reader3->_on_barrier != wait_tag ||112reader4->_on_barrier != wait_tag) {113SpinPause();114}115116// Set an invalid value.117Atomic::release_store(&valid_value, valid_value + 1); // odd118os::naked_yield();119// Set a valid value.120Atomic::release_store(&valid_value, valid_value + 1); // even121// Publish inactive tag.122Atomic::release_store_fence(&wait_tag, 0); // Stores in WB must not float up.123wb.disarm();124125// Wait until threads done valid_value verification.126while (reader1->_on_barrier != 0 ||127reader2->_on_barrier != 0 ||128reader3->_on_barrier != 0 ||129reader4->_on_barrier != 0) {130SpinPause();131}132++next_tag;133}134WBThread<WaitBarrierImpl>::_exit = true;135for (int i = 0; i < NUMBER_OF_READERS; i++) {136post.wait();137}138}139};140141TEST_VM(WaitBarrier, default_wb) {142WBThread<WaitBarrierDefault>::_exit = false;143mt_test_doer<WBArmerThread<WaitBarrierDefault> >();144}145146#if defined(LINUX)147TEST_VM(WaitBarrier, generic_wb) {148WBThread<GenericWaitBarrier>::_exit = false;149mt_test_doer<WBArmerThread<GenericWaitBarrier> >();150}151#endif152153154