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 // A fast list of JavaThreads. 32 // 33 class ThreadsList : public CHeapObj<mtThread> { 34 friend class ScanHazardPtrGatherProtectedThreadsClosure; 35 friend class Threads; 36 37 const uint _length; 38 ThreadsList* _next_list; 39 JavaThread *const *const _threads; 40 41 template <class T> 42 void threads_do_dispatch(T *cl, JavaThread *const thread) const; 43 44 ThreadsList *next_list() const { return _next_list; } 45 void set_next_list(ThreadsList *list) { _next_list = list; } 46 47 public: 48 ThreadsList(int entries); 49 ~ThreadsList(); 50 51 template <class T> 52 void threads_do(T *cl) const; 53 54 uint length() const { return _length; } 55 56 JavaThread *const thread_at(uint i) const { return _threads[i]; } 57 58 JavaThread *const *threads() const { return _threads; } 59 60 // Returns -1 if target is not found. 61 int find_index_of_JavaThread(JavaThread* target); 62 JavaThread* find_JavaThread_from_java_tid(jlong java_tid) const; 63 bool includes(const JavaThread * const p) const; 64 65 static ThreadsList* add_thread(ThreadsList* list, JavaThread* java_thread); 66 static ThreadsList* remove_thread(ThreadsList* list, JavaThread* java_thread); 67 }; 68 69 // Linked list of ThreadsLists to support nested ThreadsListHandles. 70 class NestedThreadsList : public CHeapObj<mtThread> { 71 ThreadsList*const _t_list; 72 NestedThreadsList* _next; 73 74 public: 75 NestedThreadsList(ThreadsList* t_list) : _t_list(t_list) { 76 assert(Threads_lock->owned_by_self(), 77 "must own Threads_lock for saved t_list to be valid."); 78 } 79 80 ThreadsList* t_list() { return _t_list; } 81 NestedThreadsList* next() { return _next; } 82 void set_next(NestedThreadsList* value) { _next = value; } 83 }; 84 85 // A helper to optionally set the hazard ptr in ourself. This helper can 86 // be used by ourself or by another thread. If the hazard ptr is set(), 87 // then the destructor will release it. 88 // 89 class ThreadsListSetter : public StackObj { 90 private: 91 bool _target_needs_release; // needs release only when set() 92 Thread * _target; 93 94 public: 95 ThreadsListSetter() : _target_needs_release(false), _target(Thread::current()) { 96 } 97 ~ThreadsListSetter(); 98 ThreadsList* list(); 99 void set(); 100 bool target_needs_release() { return _target_needs_release; } 101 }; 102 103 // This stack allocated ThreadsListHandle keeps all JavaThreads in the 104 // ThreadsList from being deleted until it is safe. 105 // 106 class ThreadsListHandle : public StackObj { 107 ThreadsList * _list; 108 Thread *const _self; 109 elapsedTimer _timer; // Enabled via -XX:+EnableThreadSMRStatistics. 110 111 public: 112 ThreadsListHandle(Thread *self = Thread::current()); 113 ~ThreadsListHandle(); 114 115 ThreadsList *list() const { 116 return _list; 117 } 118 119 template <class T> 120 void threads_do(T *cl) const { 121 return _list->threads_do(cl); 122 } 123 124 bool cv_internal_thread_to_JavaThread(jobject jthread, JavaThread ** jt_pp, oop * thread_oop_p); 125 126 bool includes(JavaThread* p) { 127 return _list->includes(p); 128 } 129 130 uint length() const { 131 return _list->length(); 132 } 133 }; 134 135 // This stack allocated JavaThreadIterator is used to walk the 136 // specified ThreadsList using the following style: 137 // 138 // JavaThreadIterator jti(t_list); 139 // for (JavaThread *jt = jti.first(); jt != NULL; jt = jti.next()) { 140 // ... 141 // } 142 // 143 class JavaThreadIterator : public StackObj { 144 ThreadsList * _list; 145 uint _index; 146 147 public: 148 JavaThreadIterator(ThreadsList *list) : _list(list), _index(0) { 149 assert(list != NULL, "ThreadsList must not be NULL."); 150 } 151 152 JavaThread *first() { 153 _index = 0; 154 return _list->thread_at(_index); 155 } 156 157 uint length() const { 158 return _list->length(); 159 } 160 161 ThreadsList *list() const { 162 return _list; 163 } 164 165 JavaThread *next() { 166 if (++_index >= length()) { 167 return NULL; 168 } 169 return _list->thread_at(_index); 170 } 171 }; 172 173 // This stack allocated ThreadsListHandle and JavaThreadIterator combo 174 // is used to walk the ThreadsList in the included ThreadsListHandle 175 // using the following style: 176 // 177 // for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) { 178 // ... 179 // } 180 // 181 class JavaThreadIteratorWithHandle : public StackObj { 182 ThreadsListHandle _tlh; 183 uint _index; 184 185 public: 186 JavaThreadIteratorWithHandle() : _tlh(), _index(0) {} 187 188 uint length() const { 189 return _tlh.length(); 190 } 191 192 ThreadsList *list() const { 193 return _tlh.list(); 194 } 195 196 JavaThread *next() { 197 if (_index >= length()) { 198 return NULL; 199 } 200 return _tlh.list()->thread_at(_index++); 201 } 202 203 void rewind() { 204 _index = 0; 205 } 206 }; 207 208 #endif // SHARE_VM_RUNTIME_THREADSMR_HPP