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