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 Reclamation (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 // SMR Support for the Threads class. 81 // 82 class ThreadsSMRSupport : AllStatic { 83 // The coordination between ThreadsSMRSupport::release_stable_list() and 84 // ThreadsSMRSupport::smr_delete() uses the smr_delete_lock in order to 85 // reduce the traffic on the Threads_lock. 86 static Monitor* _smr_delete_lock; 87 // The '_cnt', '_max' and '_times" fields are enabled via 88 // -XX:+EnableThreadSMRStatistics (see thread.cpp for a 89 // description about each field): 90 static uint _smr_delete_lock_wait_cnt; 91 static uint _smr_delete_lock_wait_max; 92 // The smr_delete_notify flag is used for proper double-check 93 // locking in order to reduce the traffic on the smr_delete_lock. 94 static volatile uint _smr_delete_notify; 95 static volatile uint _smr_deleted_thread_cnt; 96 static volatile uint _smr_deleted_thread_time_max; 97 static volatile uint _smr_deleted_thread_times; 98 static ThreadsList* volatile _smr_java_thread_list; 99 static uint64_t _smr_java_thread_list_alloc_cnt; 100 static uint64_t _smr_java_thread_list_free_cnt; 101 static uint _smr_java_thread_list_max; 102 static uint _smr_nested_thread_list_max; 103 static volatile uint _smr_tlh_cnt; 104 static volatile uint _smr_tlh_time_max; 105 static volatile uint _smr_tlh_times; 106 static ThreadsList* _smr_to_delete_list; 107 static uint _smr_to_delete_list_cnt; 108 static uint _smr_to_delete_list_max; 109 110 static ThreadsList *acquire_stable_list_fast_path(Thread *self); 111 static ThreadsList *acquire_stable_list_nested_path(Thread *self); 112 static void add_smr_deleted_thread_times(uint add_value); 113 static void add_smr_tlh_times(uint add_value); 114 static void clear_smr_delete_notify(); 115 static void inc_smr_deleted_thread_cnt(); 116 static void inc_smr_java_thread_list_alloc_cnt(); 117 static void inc_smr_tlh_cnt(); 118 static bool is_a_protected_JavaThread(JavaThread *thread); 119 static void release_stable_list_fast_path(Thread *self); 120 static void release_stable_list_nested_path(Thread *self); 121 static void release_stable_list_wake_up(char *log_str); 122 static void set_smr_delete_notify(); 123 static Monitor* smr_delete_lock() { return _smr_delete_lock; } 124 static bool smr_delete_notify(); 125 static void smr_free_list(ThreadsList* threads); 126 static void update_smr_deleted_thread_time_max(uint new_value); 127 static void update_smr_java_thread_list_max(uint new_value); 128 static void update_smr_tlh_time_max(uint new_value); 129 static ThreadsList* xchg_smr_java_thread_list(ThreadsList* new_list); 130 131 public: 132 static ThreadsList *acquire_stable_list(Thread *self, bool is_ThreadsListSetter); 133 static void add_thread(JavaThread *thread); 134 static ThreadsList* get_smr_java_thread_list(); 135 static bool is_a_protected_JavaThread_with_lock(JavaThread *thread); 136 static void release_stable_list(Thread *self); 137 static void remove_thread(JavaThread *thread); 138 static void smr_delete(JavaThread *thread); 139 static void update_smr_tlh_stats(uint millis); 140 141 // Logging and printing support: 142 static void log_smr_statistics(); 143 static void print_smr_info_elements_on(outputStream* st, ThreadsList* t_list); 144 static void print_smr_info_on(outputStream* st); 145 }; 146 147 // A fast list of JavaThreads. 148 // 149 class ThreadsList : public CHeapObj<mtThread> { 150 friend class ThreadsSMRSupport; // for next_list(), set_next_list() access 151 152 const uint _length; 153 ThreadsList* _next_list; 154 JavaThread *const *const _threads; 155 156 template <class T> 157 void threads_do_dispatch(T *cl, JavaThread *const thread) const; 158 159 ThreadsList *next_list() const { return _next_list; } 160 void set_next_list(ThreadsList *list) { _next_list = list; } 161 162 static ThreadsList* add_thread(ThreadsList* list, JavaThread* java_thread); 163 static ThreadsList* remove_thread(ThreadsList* list, JavaThread* java_thread); 164 165 public: 166 ThreadsList(int entries); 167 ~ThreadsList(); 168 169 template <class T> 170 void threads_do(T *cl) const; 171 172 uint length() const { return _length; } 173 174 JavaThread *const thread_at(uint i) const { return _threads[i]; } 175 176 JavaThread *const *threads() const { return _threads; } 177 178 // Returns -1 if target is not found. 179 int find_index_of_JavaThread(JavaThread* target); 180 JavaThread* find_JavaThread_from_java_tid(jlong java_tid) const; 181 bool includes(const JavaThread * const p) const; 182 }; 183 184 // Linked list of ThreadsLists to support nested ThreadsListHandles. 185 class NestedThreadsList : public CHeapObj<mtThread> { 186 ThreadsList*const _t_list; 187 NestedThreadsList* _next; 188 189 public: 190 NestedThreadsList(ThreadsList* t_list) : _t_list(t_list) { 191 assert(Threads_lock->owned_by_self(), 192 "must own Threads_lock for saved t_list to be valid."); 193 } 194 195 ThreadsList* t_list() { return _t_list; } 196 NestedThreadsList* next() { return _next; } 197 void set_next(NestedThreadsList* value) { _next = value; } 198 }; 199 200 // A helper to optionally set the hazard ptr in ourself. This helper can 201 // be used by ourself or by another thread. If the hazard ptr is set(), 202 // then the destructor will release it. 203 // 204 class ThreadsListSetter : public StackObj { 205 private: 206 bool _target_needs_release; // needs release only when set() 207 Thread * _target; 208 209 public: 210 ThreadsListSetter() : _target_needs_release(false), _target(Thread::current()) { 211 } 212 ~ThreadsListSetter(); 213 ThreadsList* list(); 214 void set(); 215 bool target_needs_release() { return _target_needs_release; } 216 }; 217 218 // This stack allocated ThreadsListHandle keeps all JavaThreads in the 219 // ThreadsList from being deleted until it is safe. 220 // 221 class ThreadsListHandle : public StackObj { 222 ThreadsList * _list; 223 Thread *const _self; 224 elapsedTimer _timer; // Enabled via -XX:+EnableThreadSMRStatistics. 225 226 public: 227 ThreadsListHandle(Thread *self = Thread::current()); 228 ~ThreadsListHandle(); 229 230 ThreadsList *list() const { 231 return _list; 232 } 233 234 template <class T> 235 void threads_do(T *cl) const { 236 return _list->threads_do(cl); 237 } 238 239 bool cv_internal_thread_to_JavaThread(jobject jthread, JavaThread ** jt_pp, oop * thread_oop_p); 240 241 bool includes(JavaThread* p) { 242 return _list->includes(p); 243 } 244 245 uint length() const { 246 return _list->length(); 247 } 248 }; 249 250 // This stack allocated JavaThreadIterator is used to walk the 251 // specified ThreadsList using the following style: 252 // 253 // JavaThreadIterator jti(t_list); 254 // for (JavaThread *jt = jti.first(); jt != NULL; jt = jti.next()) { 255 // ... 256 // } 257 // 258 class JavaThreadIterator : public StackObj { 259 ThreadsList * _list; 260 uint _index; 261 262 public: 263 JavaThreadIterator(ThreadsList *list) : _list(list), _index(0) { 264 assert(list != NULL, "ThreadsList must not be NULL."); 265 } 266 267 JavaThread *first() { 268 _index = 0; 269 return _list->thread_at(_index); 270 } 271 272 uint length() const { 273 return _list->length(); 274 } 275 276 ThreadsList *list() const { 277 return _list; 278 } 279 280 JavaThread *next() { 281 if (++_index >= length()) { 282 return NULL; 283 } 284 return _list->thread_at(_index); 285 } 286 }; 287 288 // This stack allocated ThreadsListHandle and JavaThreadIterator combo 289 // is used to walk the ThreadsList in the included ThreadsListHandle 290 // using the following style: 291 // 292 // for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) { 293 // ... 294 // } 295 // 296 class JavaThreadIteratorWithHandle : public StackObj { 297 ThreadsListHandle _tlh; 298 uint _index; 299 300 public: 301 JavaThreadIteratorWithHandle() : _index(0) {} 302 303 uint length() const { 304 return _tlh.length(); 305 } 306 307 ThreadsList *list() const { 308 return _tlh.list(); 309 } 310 311 JavaThread *next() { 312 if (_index >= length()) { 313 return NULL; 314 } 315 return _tlh.list()->thread_at(_index++); 316 } 317 318 void rewind() { 319 _index = 0; 320 } 321 }; 322 323 #endif // SHARE_VM_RUNTIME_THREADSMR_HPP