1 /* 2 * Copyright (c) 2003, 2015, 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 #include "precompiled.hpp" 26 #include "runtime/atomic.hpp" 27 #include "runtime/globalSynchronizer.hpp" 28 #include "runtime/thread.inline.hpp" 29 30 #ifndef MIN 31 #define MIN(x, y) (((x) < (y)) ? (x) : (y)) 32 #endif 33 34 volatile int GlobalSynchronizer::_global_serialized_memory_version = 0; 35 volatile int GlobalSynchronizer::_latest_global_serialized_memory_version = 0; 36 37 int GlobalSynchronizer::global_serialized_memory_version() { 38 return _global_serialized_memory_version; 39 } 40 41 GlobalSynchronizer::GlobalSynchronizer(UrgencyLevel start_urgency, UrgencyLevel max_urgency) 42 : _current_urgency(start_urgency), _max_urgency(max_urgency) { 43 assert(max_urgency >= start_urgency, "sanity"); 44 assert(start_urgency >= UrgencyLevel1 && start_urgency <= UrgencyLevelMax, "sanity"); 45 } 46 47 GlobalSynchronizer::~GlobalSynchronizer() { 48 } 49 50 void GlobalSynchronizer::start_synchronizing() { 51 assert(ThreadLocalSafepoints, "sanity"); 52 _local_serialized_memory_version = Atomic::add(1, &_global_serialized_memory_version); 53 } 54 55 bool GlobalSynchronizer::increase_urgency() { 56 if (_current_urgency + 1 < _max_urgency) { 57 _current_urgency = (UrgencyLevel)(int(_current_urgency) + 1); 58 return true; 59 } else { 60 return false; 61 } 62 } 63 64 void GlobalSynchronizer::maximize_urgency() { 65 _current_urgency = _max_urgency; 66 } 67 68 void GlobalSynchronizer::threads_do(ThreadClosure *cl) { 69 Threads::java_threads_do_fast(cl, Thread::current()); 70 } 71 72 class GSHasFinishedThreadClosure : public ThreadClosure { 73 private: 74 int _needed_version; 75 int _min_agreed_version; 76 bool _check_thread_state; 77 78 public: 79 GSHasFinishedThreadClosure(int version, bool check_thread_state) : _needed_version(version), _min_agreed_version(INT_MAX), _check_thread_state(check_thread_state) {} 80 81 virtual void do_thread(Thread *thread) { 82 JavaThread *jthread = reinterpret_cast<JavaThread*>(thread); 83 int thread_version = jthread->serialized_memory_version(); 84 if (thread_version < _needed_version) { 85 if (!jthread->is_online_vm()) _min_agreed_version = MIN(_needed_version, _min_agreed_version); 86 else if (_check_thread_state && !jthread->is_online_os()) _min_agreed_version = MIN(_needed_version, _min_agreed_version); 87 else _min_agreed_version = MIN(thread_version, _min_agreed_version); 88 } else { 89 _min_agreed_version = MIN(thread_version, _min_agreed_version); 90 } 91 } 92 93 bool did_synchronize() { return _min_agreed_version >= _needed_version; } 94 void fixup_global_version() { 95 int global_version = GlobalSynchronizer::_latest_global_serialized_memory_version; 96 if (global_version < _min_agreed_version) { 97 (void) Atomic::cmpxchg(_min_agreed_version, &GlobalSynchronizer::_latest_global_serialized_memory_version, global_version); 98 } 99 } 100 }; 101 102 class GSSetYieldpointThreadClosure : public ThreadClosure { 103 const int _target_version; 104 const bool _force_yields; 105 public: 106 GSSetYieldpointThreadClosure(bool force_yields, int target_version) : _force_yields(force_yields), _target_version(target_version) {} 107 108 virtual void do_thread(Thread *thread) { 109 JavaThread *const jthread = (JavaThread*)thread; 110 if (jthread->serialized_memory_version() >= _target_version) return; 111 if (_force_yields) jthread->set_force_yield(); 112 jthread->set_yieldpoint(true); 113 } 114 }; 115 116 bool GlobalSynchronizer::try_synchronize() { 117 Thread *thread = Thread::current(); 118 if (thread->is_Java_thread()) { 119 JavaThread *jthread = reinterpret_cast<JavaThread*>(thread); 120 jthread->update_serialized_memory_version(); 121 } 122 123 if (_latest_global_serialized_memory_version >= _local_serialized_memory_version) { 124 return true; 125 } 126 127 GSHasFinishedThreadClosure cl(_local_serialized_memory_version, /* check_thread_state */ _current_urgency >= UrgencyLevel2); 128 threads_do(&cl); 129 if (cl.did_synchronize()) { 130 cl.fixup_global_version(); 131 return true; 132 } 133 134 switch (_current_urgency) { 135 case UrgencyLevel3: 136 case UrgencyLevel4: { 137 GSSetYieldpointThreadClosure cl(false, _local_serialized_memory_version); 138 threads_do(&cl); 139 return false; 140 } 141 default: return false; 142 } 143 } 144 145 void GlobalSynchronizer::synchronize() { 146 while (!try_synchronize()) os::naked_yield(); 147 }