120 static void free_list(ThreadsList* threads); |
126 static void free_list(ThreadsList* threads); |
121 static void inc_deleted_thread_cnt(); |
127 static void inc_deleted_thread_cnt(); |
122 static void inc_java_thread_list_alloc_cnt(); |
128 static void inc_java_thread_list_alloc_cnt(); |
123 static void inc_tlh_cnt(); |
129 static void inc_tlh_cnt(); |
124 static bool is_a_protected_JavaThread(JavaThread *thread); |
130 static bool is_a_protected_JavaThread(JavaThread *thread); |
125 static void release_stable_list_fast_path(Thread *self); |
131 static void release_stable_list_wake_up(bool is_nested); |
126 static void release_stable_list_nested_path(Thread *self); |
|
127 static void release_stable_list_wake_up(char *log_str); |
|
128 static void set_delete_notify(); |
132 static void set_delete_notify(); |
129 static void threads_do(ThreadClosure *tc); |
133 static void threads_do(ThreadClosure *tc); |
130 static void threads_do(ThreadClosure *tc, ThreadsList *list); |
134 static void threads_do(ThreadClosure *tc, ThreadsList *list); |
131 static void update_deleted_thread_time_max(uint new_value); |
135 static void update_deleted_thread_time_max(uint new_value); |
132 static void update_java_thread_list_max(uint new_value); |
136 static void update_java_thread_list_max(uint new_value); |
133 static void update_tlh_time_max(uint new_value); |
137 static void update_tlh_time_max(uint new_value); |
134 static void verify_hazard_pointer_scanned(Thread *self, ThreadsList *threads); |
138 static void verify_hazard_ptr_scanned(Thread *self, ThreadsList *threads); |
135 static ThreadsList* xchg_java_thread_list(ThreadsList* new_list); |
139 static ThreadsList* xchg_java_thread_list(ThreadsList* new_list); |
136 |
140 |
137 public: |
141 public: |
138 static ThreadsList *acquire_stable_list(Thread *self, bool is_ThreadsListSetter); |
|
139 static void add_thread(JavaThread *thread); |
142 static void add_thread(JavaThread *thread); |
140 static ThreadsList* get_java_thread_list(); |
143 static ThreadsList* get_java_thread_list(); |
141 static bool is_a_protected_JavaThread_with_lock(JavaThread *thread); |
144 static bool is_a_protected_JavaThread_with_lock(JavaThread *thread); |
142 static void release_stable_list(Thread *self); |
|
143 static void remove_thread(JavaThread *thread); |
145 static void remove_thread(JavaThread *thread); |
144 static void smr_delete(JavaThread *thread); |
146 static void smr_delete(JavaThread *thread); |
145 static void update_tlh_stats(uint millis); |
147 static void update_tlh_stats(uint millis); |
146 |
148 |
147 // Logging and printing support: |
149 // Logging and printing support: |
148 static void log_statistics(); |
150 static void log_statistics(); |
149 static void print_info_elements_on(outputStream* st, ThreadsList* t_list); |
151 static void print_info_elements_on(outputStream* st, ThreadsList* t_list); |
150 static void print_info_on(outputStream* st); |
152 static void print_info_on(outputStream* st); |
|
153 static void print_info_on(const Thread* thread, outputStream* st); |
151 }; |
154 }; |
152 |
155 |
153 // A fast list of JavaThreads. |
156 // A fast list of JavaThreads. |
154 // |
157 // |
155 class ThreadsList : public CHeapObj<mtThread> { |
158 class ThreadsList : public CHeapObj<mtThread> { |
156 friend class ThreadsSMRSupport; // for next_list(), set_next_list() access |
159 friend class SafeThreadsListPtr; // for {dec,inc}_nested_handle_cnt() access |
|
160 friend class ThreadsSMRSupport; // for _nested_handle_cnt, {add,remove}_thread(), {,set_}next_list() access |
157 |
161 |
158 const uint _length; |
162 const uint _length; |
159 ThreadsList* _next_list; |
163 ThreadsList* _next_list; |
160 JavaThread *const *const _threads; |
164 JavaThread *const *const _threads; |
|
165 volatile intx _nested_handle_cnt; |
161 |
166 |
162 template <class T> |
167 template <class T> |
163 void threads_do_dispatch(T *cl, JavaThread *const thread) const; |
168 void threads_do_dispatch(T *cl, JavaThread *const thread) const; |
164 |
169 |
165 ThreadsList *next_list() const { return _next_list; } |
170 ThreadsList *next_list() const { return _next_list; } |
166 void set_next_list(ThreadsList *list) { _next_list = list; } |
171 void set_next_list(ThreadsList *list) { _next_list = list; } |
|
172 |
|
173 void inc_nested_handle_cnt(); |
|
174 void dec_nested_handle_cnt(); |
167 |
175 |
168 static ThreadsList* add_thread(ThreadsList* list, JavaThread* java_thread); |
176 static ThreadsList* add_thread(ThreadsList* list, JavaThread* java_thread); |
169 static ThreadsList* remove_thread(ThreadsList* list, JavaThread* java_thread); |
177 static ThreadsList* remove_thread(ThreadsList* list, JavaThread* java_thread); |
170 |
178 |
171 public: |
179 public: |
185 int find_index_of_JavaThread(JavaThread* target); |
193 int find_index_of_JavaThread(JavaThread* target); |
186 JavaThread* find_JavaThread_from_java_tid(jlong java_tid) const; |
194 JavaThread* find_JavaThread_from_java_tid(jlong java_tid) const; |
187 bool includes(const JavaThread * const p) const; |
195 bool includes(const JavaThread * const p) const; |
188 }; |
196 }; |
189 |
197 |
190 // Linked list of ThreadsLists to support nested ThreadsListHandles. |
198 // An abstract safe ptr to a ThreadsList comprising either a stable hazard ptr |
191 class NestedThreadsList : public CHeapObj<mtThread> { |
199 // for leaves, or a retained reference count for nested uses. The user of this |
192 ThreadsList*const _t_list; |
200 // API does not need to know which mechanism is providing the safety. |
193 NestedThreadsList* _next; |
201 class SafeThreadsListPtr { |
194 |
202 friend class ThreadsListSetter; |
195 public: |
203 |
196 NestedThreadsList(ThreadsList* t_list) : _t_list(t_list) { |
204 SafeThreadsListPtr* _previous; |
197 assert(Threads_lock->owned_by_self(), |
205 Thread* _thread; |
198 "must own Threads_lock for saved t_list to be valid."); |
206 ThreadsList* _list; |
199 } |
207 bool _has_ref_count; |
200 |
208 bool _needs_release; |
201 ThreadsList* t_list() { return _t_list; } |
209 |
202 NestedThreadsList* next() { return _next; } |
210 void acquire_stable_list(); |
203 void set_next(NestedThreadsList* value) { _next = value; } |
211 void acquire_stable_list_fast_path(); |
|
212 void acquire_stable_list_nested_path(); |
|
213 |
|
214 void release_stable_list(); |
|
215 |
|
216 void verify_hazard_ptr_scanned(); |
|
217 |
|
218 public: |
|
219 // Constructor that attaches the list onto a thread. |
|
220 SafeThreadsListPtr(Thread *thread, bool acquire) : |
|
221 _previous(NULL), |
|
222 _thread(thread), |
|
223 _list(NULL), |
|
224 _has_ref_count(false), |
|
225 _needs_release(false) |
|
226 { |
|
227 if (acquire) { |
|
228 acquire_stable_list(); |
|
229 } |
|
230 } |
|
231 |
|
232 // Constructor that transfers ownership of the pointer. |
|
233 SafeThreadsListPtr(SafeThreadsListPtr& other) : |
|
234 _previous(other._previous), |
|
235 _thread(other._thread), |
|
236 _list(other._list), |
|
237 _has_ref_count(other._has_ref_count), |
|
238 _needs_release(other._needs_release) |
|
239 { |
|
240 other._needs_release = false; |
|
241 } |
|
242 |
|
243 ~SafeThreadsListPtr() { |
|
244 if (_needs_release) { |
|
245 release_stable_list(); |
|
246 } |
|
247 } |
|
248 |
|
249 ThreadsList* list() const { return _list; } |
|
250 SafeThreadsListPtr* previous() const { return _previous; } |
|
251 void print_on(outputStream* st); |
204 }; |
252 }; |
205 |
253 |
206 // A helper to optionally set the hazard ptr in ourself. This helper can |
254 // A helper to optionally set the hazard ptr in ourself. This helper can |
207 // be used by ourself or by another thread. If the hazard ptr is set(), |
255 // be used by ourself or by another thread. If the hazard ptr is set(), |
208 // then the destructor will release it. |
256 // then the destructor will release it. |
209 // |
257 // |
210 class ThreadsListSetter : public StackObj { |
258 class ThreadsListSetter : public StackObj { |
211 private: |
259 private: |
212 bool _target_needs_release; // needs release only when set() |
260 SafeThreadsListPtr _list_ptr; |
213 Thread * _target; |
261 |
214 |
262 public: |
215 public: |
263 ThreadsListSetter() : _list_ptr(Thread::current(), /* acquire */ false) {} |
216 ThreadsListSetter() : _target_needs_release(false), _target(Thread::current()) { |
264 ThreadsList* list() { return _list_ptr.list(); } |
217 } |
265 void set() { _list_ptr.acquire_stable_list(); } |
218 ~ThreadsListSetter(); |
266 bool is_set() { return _list_ptr._needs_release; } |
219 ThreadsList* list(); |
|
220 void set(); |
|
221 bool target_needs_release() { return _target_needs_release; } |
|
222 }; |
267 }; |
223 |
268 |
224 // This stack allocated ThreadsListHandle keeps all JavaThreads in the |
269 // This stack allocated ThreadsListHandle keeps all JavaThreads in the |
225 // ThreadsList from being deleted until it is safe. |
270 // ThreadsList from being deleted until it is safe. |
226 // |
271 // |
227 class ThreadsListHandle : public StackObj { |
272 class ThreadsListHandle : public StackObj { |
228 ThreadsList * _list; |
273 SafeThreadsListPtr _list_ptr; |
229 Thread *const _self; |
|
230 elapsedTimer _timer; // Enabled via -XX:+EnableThreadSMRStatistics. |
274 elapsedTimer _timer; // Enabled via -XX:+EnableThreadSMRStatistics. |
231 |
275 |
232 public: |
276 public: |
233 ThreadsListHandle(Thread *self = Thread::current()); |
277 ThreadsListHandle(Thread *self = Thread::current()); |
234 ~ThreadsListHandle(); |
278 ~ThreadsListHandle(); |
235 |
279 |
236 ThreadsList *list() const { |
280 ThreadsList *list() const { |
237 return _list; |
281 return _list_ptr.list(); |
238 } |
282 } |
239 |
283 |
240 template <class T> |
284 template <class T> |
241 void threads_do(T *cl) const { |
285 void threads_do(T *cl) const { |
242 return _list->threads_do(cl); |
286 return list()->threads_do(cl); |
243 } |
287 } |
244 |
288 |
245 bool cv_internal_thread_to_JavaThread(jobject jthread, JavaThread ** jt_pp, oop * thread_oop_p); |
289 bool cv_internal_thread_to_JavaThread(jobject jthread, JavaThread ** jt_pp, oop * thread_oop_p); |
246 |
290 |
247 bool includes(JavaThread* p) { |
291 bool includes(JavaThread* p) { |
248 return _list->includes(p); |
292 return list()->includes(p); |
249 } |
293 } |
250 |
294 |
251 uint length() const { |
295 uint length() const { |
252 return _list->length(); |
296 return list()->length(); |
253 } |
297 } |
254 }; |
298 }; |
255 |
299 |
256 // This stack allocated JavaThreadIterator is used to walk the |
300 // This stack allocated JavaThreadIterator is used to walk the |
257 // specified ThreadsList using the following style: |
301 // specified ThreadsList using the following style: |