/* * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ #include "precompiled.hpp" #include "runtime/atomic.hpp" #include "runtime/orderAccess.hpp" #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 valid_value = 0; template class WBThread : public JavaTestThread { public: static volatile bool _exit; WaitBarrierType* _wait_barrier; Semaphore* _wrt_start; volatile int _on_barrier; WBThread(Semaphore* post, WaitBarrierType* wb, Semaphore* wrt_start) : JavaTestThread(post), _wait_barrier(wb), _wrt_start(wrt_start) {}; virtual ~WBThread(){} void main_run() { _wrt_start->signal(); int vv, tag; while (!_exit) { tag = OrderAccess::load_acquire(&wait_tag); OrderAccess::release_store_fence(&_on_barrier, tag); _wait_barrier->wait(tag); vv = OrderAccess::load_acquire(&valid_value); ASSERT_EQ((vv & 0x1), 0); } } }; template volatile bool WBThread::_exit = false; template class WBArmerThread : public JavaTestThread { public: WBArmerThread(Semaphore* post) : JavaTestThread(post) { }; virtual ~WBArmerThread(){} void main_run() { static const int NUMBER_OF_READERS = 4; Semaphore post; Semaphore wrt_start; WaitBarrierType wb; wait_tag = 2; WBThread* reader1 = new WBThread(&post, &wb, &wrt_start); WBThread* reader2 = new WBThread(&post, &wb, &wrt_start); WBThread* reader3 = new WBThread(&post, &wb, &wrt_start); WBThread* reader4 = new WBThread(&post, &wb, &wrt_start); reader1->doit(); reader2->doit(); reader3->doit(); reader4->doit(); 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 while (stop_ms > os::javaTimeMillis()) { wb.arm(wait_tag + 1); OrderAccess::release_store(&wait_tag, wait_tag + 1); while (reader1->_on_barrier != wait_tag || reader2->_on_barrier != wait_tag || reader3->_on_barrier != wait_tag || reader4->_on_barrier != wait_tag) { sp.wait(); } OrderAccess::release_store(&valid_value, valid_value + 1); // odd os::naked_short_sleep(1); OrderAccess::release_store(&valid_value, valid_value + 1); // even OrderAccess::storestore(); // Stores in WB must not float up. wb.disarm(); wb.wake(); } WBThread::_exit = true; for (int i = 0; i < NUMBER_OF_READERS; i++) { post.wait(); } } }; TEST_VM(WaitBarrier, default_wb) { WBThread::_exit = false; mt_test_doer >(); } #if defined(LINUX) TEST_VM(WaitBarrier, generic_wb) { WBThread::_exit = false; mt_test_doer >(); } #endif