1 /* 2 * Copyright (c) 2018, 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 25 #ifndef SHARE_UTILITIES_WAITBARRIER_HPP 26 #define SHARE_UTILITIES_WAITBARRIER_HPP 27 28 #include "memory/allocation.hpp" 29 #include "runtime/thread.hpp" 30 #include "utilities/debug.hpp" 31 #include "utilities/waitBarrier_generic.hpp" 32 33 #if defined(LINUX) 34 #include "waitBarrier_linux.hpp" 35 typedef LinuxWaitBarrier WaitBarrierDefault; 36 #else 37 typedef GenericWaitBarrier WaitBarrierDefault; 38 #endif 39 40 // Platform independent WaitBarrier API. 41 // An armed WaitBarrier prevents threads from advancing until the 42 // barrier is disarmed and the waiting threads woken. The barrier is 43 // armed by setting a non-zero value - the tag. 44 // 45 // Expected Usage: 46 // - Arming thread: 47 // tag = ...; // non-zero value 48 // barrier.arm(tag); 49 // <publish tag> 50 // <work> 51 // barrier.disarm(); 52 // barrier.wake(); 53 // 54 // - After arm(tag) returns any thread calling wait(tag) will block. 55 // - After disarm() returns any subsequent calls to wait(tag) will not block. 56 // - After wake() returns all blocked threads are unblocked and eligible to 57 // execute again. 58 // - After calling disarm() and wake() the barrier is ready to be re-armed 59 // with a new tag. (may not be re-armed with last used tag) 60 // 61 // - Waiting threads 62 // wait(tag); // don't execute following code unless 'safe' 63 // <work> 64 // 65 // - A call to wait(tag) will block if the barrier is armed with the value 66 // 'tag'; else it will return immediately. 67 // - A blocked thread is eligible to execute again once the barrier is 68 // disarmed and wake() has been called. 69 // 70 // A primary goal of the WaitBarrier implementation is to wake all waiting 71 // threads as fast, and as concurrently, as possible. 72 // 73 template <typename WaitBarrierImpl> 74 class WaitBarrierType : public CHeapObj<mtInternal> { 75 WaitBarrierImpl _impl; 76 77 // Prevent copying and assignment of WaitBarrier instances. 78 WaitBarrierType(const WaitBarrierDefault&); 79 WaitBarrierType& operator=(const WaitBarrierDefault&); 80 81 #ifdef ASSERT 82 int _last_arm_tag; 83 Thread* _owner; 84 #endif 85 86 public: 87 WaitBarrierType(Thread* owner) : _impl() { 88 #ifdef ASSERT 89 _last_arm_tag = 0; 90 _owner = owner; 91 #endif 92 } 93 ~WaitBarrierType() {} 94 95 // Returns implementation type. 96 const char* description() { return _impl.description(); } 97 98 // Guarantees any thread calling wait() with same tag will be blocked. 99 // Provides a trailing fence. 100 void arm(int barrier_tag) { 101 #ifdef ASSERT 102 assert(_last_arm_tag != barrier_tag, "Re-arming with same tag"); 103 _last_arm_tag = barrier_tag; 104 assert(_owner == Thread::current(), "Not owner thread"); 105 #endif 106 _impl.arm(barrier_tag); 107 } 108 109 // Guarantees any thread calling wait() with any tag will not be blocked. 110 // Provides a trailing fence. 111 void disarm() { 112 assert(_owner == Thread::current(), "Not owner thread"); 113 _impl.disarm(); 114 } 115 116 // Guarantees any thread called wait() will be awake when it returns. 117 // Provides a trailing fence. 118 void wake() { 119 assert(_owner == Thread::current(), "Not owner thread"); 120 _impl.wake(); 121 } 122 123 // Guarantees to return if disarm() and wake() is called. 124 // Provides a trailing fence. 125 void wait(int barrier_tag) { 126 assert(_owner != Thread::current(), "Trying to wait with owner thread"); 127 _impl.wait(barrier_tag); 128 } 129 }; 130 131 typedef WaitBarrierType<WaitBarrierDefault> WaitBarrier; 132 133 #endif // SHARE_UTILITIES_WAITBARRIER_HPP