1 /* 2 * Copyright (c) 2017, 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_VM_RUNTIME_THREADSMR_HPP 26 #define SHARE_VM_RUNTIME_THREADSMR_HPP 27 28 #include "memory/allocation.hpp" 29 #include "runtime/timer.hpp" 30 31 // Thread Safe Memory Reclaimation (Thread-SMR) support. 32 // 33 // ThreadsListHandles are used to safely perform operations on one or more 34 // threads without the risk of the thread or threads exiting during the 35 // operation. It is no longer necessary to hold the Threads_lock to safely 36 // perform an operation on a target thread. 37 // 38 // There are several different ways to refer to java.lang.Thread objects 39 // so we have a few ways to get a protected JavaThread *: 40 // 41 // JNI jobject example: 42 // jobject jthread = ...; 43 // : 44 // ThreadsListHandle tlh; 45 // JavaThread* jt = NULL; 46 // bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &jt, NULL); 47 // if (is_alive) { 48 // : // do stuff with 'jt'... 49 // } 50 // 51 // JVM/TI jthread example: 52 // jthread thread = ...; 53 // : 54 // JavaThread* jt = NULL; 55 // ThreadsListHandle tlh; 56 // jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), thread, &jt, NULL); 57 // if (err != JVMTI_ERROR_NONE) { 58 // return err; 59 // } 60 // : // do stuff with 'jt'... 61 // 62 // JVM/TI oop example (this one should be very rare): 63 // oop thread_obj = ...; 64 // : 65 // JavaThread *jt = NULL; 66 // ThreadsListHandle tlh; 67 // jvmtiError err = JvmtiExport::cv_oop_to_JavaThread(tlh.list(), thread_obj, &jt); 68 // if (err != JVMTI_ERROR_NONE) { 69 // return err; 70 // } 71 // : // do stuff with 'jt'... 72 // 73 // A JavaThread * that is included in the ThreadsList that is held by 74 // a ThreadsListHandle is protected as long as the ThreadsListHandle 75 // remains in scope. The target JavaThread * may have logically exited, 76 // but that target JavaThread * will not be deleted until it is no 77 // longer protected by a ThreadsListHandle. 78 79 80 // A fast list of JavaThreads. 81 // 82 class ThreadsList : public CHeapObj<mtThread> { 83 friend class ScanHazardPtrGatherProtectedThreadsClosure; 84 friend class Threads; 85 86 const uint _length; 87 ThreadsList* _next_list; 88 JavaThread *const *const _threads; 89 90 template <class T> 91 void threads_do_dispatch(T *cl, JavaThread *const thread) const; 92 93 ThreadsList *next_list() const { return _next_list; } 94 void set_next_list(ThreadsList *list) { _next_list = list; } 95 96 public: 97 ThreadsList(int entries); 98 ~ThreadsList(); 99 100 template <class T> 101 void threads_do(T *cl) const; 102 103 uint length() const { return _length; } 104 105 JavaThread *const thread_at(uint i) const { return _threads[i]; } 106 107 JavaThread *const *threads() const { return _threads; } 108 109 // Returns -1 if target is not found. 110 int find_index_of_JavaThread(JavaThread* target); 111 JavaThread* find_JavaThread_from_java_tid(jlong java_tid) const; 112 bool includes(const JavaThread * const p) const; 113 114 static ThreadsList* add_thread(ThreadsList* list, JavaThread* java_thread); 115 static ThreadsList* remove_thread(ThreadsList* list, JavaThread* java_thread); 116 }; 117 118 // Linked list of ThreadsLists to support nested ThreadsListHandles. 119 class NestedThreadsList : public CHeapObj<mtThread> { 120 ThreadsList*const _t_list; 121 NestedThreadsList* _next; 122 123 public: 124 NestedThreadsList(ThreadsList* t_list) : _t_list(t_list) { 125 assert(Threads_lock->owned_by_self(), 126 "must own Threads_lock for saved t_list to be valid."); 127 } 128 129 ThreadsList* t_list() { return _t_list; } 130 NestedThreadsList* next() { return _next; } 131 void set_next(NestedThreadsList* value) { _next = value; } 132 }; 133 134 // A helper to optionally set the hazard ptr in ourself. This helper can 135 // be used by ourself or by another thread. If the hazard ptr is set(), 136 // then the destructor will release it. 137 // 138 class ThreadsListSetter : public StackObj { 139 private: 140 bool _target_needs_release; // needs release only when set() 141 Thread * _target; 142 143 public: 144 ThreadsListSetter() : _target_needs_release(false), _target(Thread::current()) { 145 } 146 ~ThreadsListSetter(); 147 ThreadsList* list(); 148 void set(); 149 bool target_needs_release() { return _target_needs_release; } 150 }; 151 152 // This stack allocated ThreadsListHandle keeps all JavaThreads in the 153 // ThreadsList from being deleted until it is safe. 154 // 155 class ThreadsListHandle : public StackObj { 156 ThreadsList * _list; 157 Thread *const _self; 158 elapsedTimer _timer; // Enabled via -XX:+EnableThreadSMRStatistics. 159 160 public: 161 ThreadsListHandle(Thread *self = Thread::current()); 162 ~ThreadsListHandle(); 163 164 ThreadsList *list() const { 165 return _list; 166 } 167 168 template <class T> 169 void threads_do(T *cl) const { 170 return _list->threads_do(cl); 171 } 172 173 bool cv_internal_thread_to_JavaThread(jobject jthread, JavaThread ** jt_pp, oop * thread_oop_p); 174 175 bool includes(JavaThread* p) { 176 return _list->includes(p); 177 } 178 179 uint length() const { 180 return _list->length(); 181 } 182 }; 183 184 // This stack allocated JavaThreadIterator is used to walk the 185 // specified ThreadsList using the following style: 186 // 187 // JavaThreadIterator jti(t_list); 188 // for (JavaThread *jt = jti.first(); jt != NULL; jt = jti.next()) { 189 // ... 190 // } 191 // 192 class JavaThreadIterator : public StackObj { 193 ThreadsList * _list; 194 uint _index; 195 196 public: 197 JavaThreadIterator(ThreadsList *list) : _list(list), _index(0) { 198 assert(list != NULL, "ThreadsList must not be NULL."); 199 } 200 201 JavaThread *first() { 202 _index = 0; 203 return _list->thread_at(_index); 204 } 205 206 uint length() const { 207 return _list->length(); 208 } 209 210 ThreadsList *list() const { 211 return _list; 212 } 213 214 JavaThread *next() { 215 if (++_index >= length()) { 216 return NULL; 217 } 218 return _list->thread_at(_index); 219 } 220 }; 221 222 // This stack allocated ThreadsListHandle and JavaThreadIterator combo 223 // is used to walk the ThreadsList in the included ThreadsListHandle 224 // using the following style: 225 // 226 // for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) { 227 // ... 228 // } 229 // 230 class JavaThreadIteratorWithHandle : public StackObj { 231 ThreadsListHandle _tlh; 232 uint _index; 233 234 public: 235 JavaThreadIteratorWithHandle() : _index(0) {} 236 237 uint length() const { 238 return _tlh.length(); 239 } 240 241 ThreadsList *list() const { 242 return _tlh.list(); 243 } 244 245 JavaThread *next() { 246 if (_index >= length()) { 247 return NULL; 248 } 249 return _tlh.list()->thread_at(_index++); 250 } 251 252 void rewind() { 253 _index = 0; 254 } 255 }; 256 257 #endif // SHARE_VM_RUNTIME_THREADSMR_HPP