Mercurial > hg > truffle
annotate src/share/vm/services/threadService.hpp @ 8733:9def4075da6d
8008079: G1: Add nextObject routine to CMBitMapRO and replace nextWord
Summary: Update the task local finger to the start of the next object when marking aborts, in order to avoid the redundant scanning of all 0's when the marking task restarts, if otherwise updating to the next word. In addition, reuse the routine nextObject() in routine iterate().
Reviewed-by: johnc, ysr
Contributed-by: tamao <tao.mao@oracle.com>
author | tamao |
---|---|
date | Tue, 05 Mar 2013 15:36:56 -0800 |
parents | da91efe96a93 |
children | 0b9ea9a72436 |
rev | line source |
---|---|
0 | 1 /* |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
948
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
948
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
948
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #ifndef SHARE_VM_SERVICES_THREADSERVICE_HPP |
26 #define SHARE_VM_SERVICES_THREADSERVICE_HPP | |
27 | |
28 #include "classfile/javaClasses.hpp" | |
29 #include "runtime/handles.hpp" | |
30 #include "runtime/init.hpp" | |
31 #include "runtime/jniHandles.hpp" | |
32 #include "runtime/objectMonitor.hpp" | |
33 #include "runtime/objectMonitor.inline.hpp" | |
34 #include "runtime/perfData.hpp" | |
35 #include "services/management.hpp" | |
36 #include "services/serviceUtil.hpp" | |
37 | |
0 | 38 class OopClosure; |
39 class ThreadDumpResult; | |
40 class ThreadStackTrace; | |
41 class ThreadSnapshot; | |
42 class StackFrameInfo; | |
43 class ThreadConcurrentLocks; | |
44 class DeadlockCycle; | |
45 | |
46 // VM monitoring and management support for the thread and | |
47 // synchronization subsystem | |
48 // | |
49 // Thread contention monitoring is disabled by default. | |
50 // When enabled, the VM will begin measuring the accumulated | |
51 // elapsed time a thread blocked on synchronization. | |
52 // | |
53 class ThreadService : public AllStatic { | |
54 private: | |
55 // These counters could be moved to Threads class | |
56 static PerfCounter* _total_threads_count; | |
57 static PerfVariable* _live_threads_count; | |
58 static PerfVariable* _peak_threads_count; | |
59 static PerfVariable* _daemon_threads_count; | |
60 | |
61 // These 2 counters are atomically incremented once the thread is exiting. | |
62 // They will be atomically decremented when ThreadService::remove_thread is called. | |
63 static volatile int _exiting_threads_count; | |
64 static volatile int _exiting_daemon_threads_count; | |
65 | |
66 static bool _thread_monitoring_contention_enabled; | |
67 static bool _thread_cpu_time_enabled; | |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
68 static bool _thread_allocated_memory_enabled; |
0 | 69 |
70 // Need to keep the list of thread dump result that | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
71 // keep references to Method* since thread dump can be |
0 | 72 // requested by multiple threads concurrently. |
73 static ThreadDumpResult* _threaddump_list; | |
74 | |
75 public: | |
76 static void init(); | |
77 static void add_thread(JavaThread* thread, bool daemon); | |
78 static void remove_thread(JavaThread* thread, bool daemon); | |
79 static void current_thread_exiting(JavaThread* jt); | |
80 | |
81 static bool set_thread_monitoring_contention(bool flag); | |
82 static bool is_thread_monitoring_contention() { return _thread_monitoring_contention_enabled; } | |
83 | |
84 static bool set_thread_cpu_time_enabled(bool flag); | |
85 static bool is_thread_cpu_time_enabled() { return _thread_cpu_time_enabled; } | |
86 | |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
87 static bool set_thread_allocated_memory_enabled(bool flag); |
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
88 static bool is_thread_allocated_memory_enabled() { return _thread_cpu_time_enabled; } |
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
89 |
0 | 90 static jlong get_total_thread_count() { return _total_threads_count->get_value(); } |
91 static jlong get_peak_thread_count() { return _peak_threads_count->get_value(); } | |
92 static jlong get_live_thread_count() { return _live_threads_count->get_value() - _exiting_threads_count; } | |
93 static jlong get_daemon_thread_count() { return _daemon_threads_count->get_value() - _exiting_daemon_threads_count; } | |
94 | |
95 static int exiting_threads_count() { return _exiting_threads_count; } | |
96 static int exiting_daemon_threads_count() { return _exiting_daemon_threads_count; } | |
97 | |
98 // Support for thread dump | |
99 static void add_thread_dump(ThreadDumpResult* dump); | |
100 static void remove_thread_dump(ThreadDumpResult* dump); | |
101 | |
102 static Handle get_current_contended_monitor(JavaThread* thread); | |
103 | |
104 // This function is called by JVM_DumpThreads. | |
105 static Handle dump_stack_traces(GrowableArray<instanceHandle>* threads, | |
106 int num_threads, TRAPS); | |
107 | |
108 static void reset_peak_thread_count(); | |
109 static void reset_contention_count_stat(JavaThread* thread); | |
110 static void reset_contention_time_stat(JavaThread* thread); | |
111 | |
112 static DeadlockCycle* find_deadlocks_at_safepoint(bool object_monitors_only); | |
113 | |
114 // GC support | |
115 static void oops_do(OopClosure* f); | |
116 }; | |
117 | |
118 // Per-thread Statistics for synchronization | |
6197 | 119 class ThreadStatistics : public CHeapObj<mtInternal> { |
0 | 120 private: |
121 // The following contention statistics are only updated by | |
122 // the thread owning these statistics when contention occurs. | |
123 | |
124 jlong _contended_enter_count; | |
125 elapsedTimer _contended_enter_timer; | |
126 jlong _monitor_wait_count; | |
127 elapsedTimer _monitor_wait_timer; | |
128 jlong _sleep_count; | |
129 elapsedTimer _sleep_timer; | |
130 | |
131 | |
132 // These two reset flags are set to true when another thread | |
133 // requests to reset the statistics. The actual statistics | |
134 // are reset when the thread contention occurs and attempts | |
135 // to update the statistics. | |
136 bool _count_pending_reset; | |
137 bool _timer_pending_reset; | |
138 | |
139 // Keep accurate times for potentially recursive class operations | |
875
6a93908f268f
6857194: Add hotspot perf counters to aid class loading performance measurement
mchung
parents:
470
diff
changeset
|
140 int _perf_recursion_counts[6]; |
6a93908f268f
6857194: Add hotspot perf counters to aid class loading performance measurement
mchung
parents:
470
diff
changeset
|
141 elapsedTimer _perf_timers[6]; |
0 | 142 |
143 // utility functions | |
144 void check_and_reset_count() { | |
145 if (!_count_pending_reset) return; | |
146 _contended_enter_count = 0; | |
147 _monitor_wait_count = 0; | |
148 _sleep_count = 0; | |
149 _count_pending_reset = 0; | |
150 } | |
151 void check_and_reset_timer() { | |
152 if (!_timer_pending_reset) return; | |
153 _contended_enter_timer.reset(); | |
154 _monitor_wait_timer.reset(); | |
155 _sleep_timer.reset(); | |
156 _timer_pending_reset = 0; | |
157 } | |
158 | |
159 public: | |
160 ThreadStatistics(); | |
161 | |
162 jlong contended_enter_count() { return (_count_pending_reset ? 0 : _contended_enter_count); } | |
163 jlong contended_enter_ticks() { return (_timer_pending_reset ? 0 : _contended_enter_timer.active_ticks()); } | |
164 jlong monitor_wait_count() { return (_count_pending_reset ? 0 : _monitor_wait_count); } | |
165 jlong monitor_wait_ticks() { return (_timer_pending_reset ? 0 : _monitor_wait_timer.active_ticks()); } | |
166 jlong sleep_count() { return (_count_pending_reset ? 0 : _sleep_count); } | |
167 jlong sleep_ticks() { return (_timer_pending_reset ? 0 : _sleep_timer.active_ticks()); } | |
168 | |
169 void monitor_wait() { check_and_reset_count(); _monitor_wait_count++; } | |
170 void monitor_wait_begin() { check_and_reset_timer(); _monitor_wait_timer.start(); } | |
171 void monitor_wait_end() { _monitor_wait_timer.stop(); check_and_reset_timer(); } | |
172 | |
173 void thread_sleep() { check_and_reset_count(); _sleep_count++; } | |
174 void thread_sleep_begin() { check_and_reset_timer(); _sleep_timer.start(); } | |
175 void thread_sleep_end() { _sleep_timer.stop(); check_and_reset_timer(); } | |
176 | |
177 void contended_enter() { check_and_reset_count(); _contended_enter_count++; } | |
178 void contended_enter_begin() { check_and_reset_timer(); _contended_enter_timer.start(); } | |
179 void contended_enter_end() { _contended_enter_timer.stop(); check_and_reset_timer(); } | |
180 | |
181 void reset_count_stat() { _count_pending_reset = true; } | |
182 void reset_time_stat() { _timer_pending_reset = true; } | |
183 | |
875
6a93908f268f
6857194: Add hotspot perf counters to aid class loading performance measurement
mchung
parents:
470
diff
changeset
|
184 int* perf_recursion_counts_addr() { return _perf_recursion_counts; } |
6a93908f268f
6857194: Add hotspot perf counters to aid class loading performance measurement
mchung
parents:
470
diff
changeset
|
185 elapsedTimer* perf_timers_addr() { return _perf_timers; } |
0 | 186 }; |
187 | |
188 // Thread snapshot to represent the thread state and statistics | |
6197 | 189 class ThreadSnapshot : public CHeapObj<mtInternal> { |
0 | 190 private: |
191 JavaThread* _thread; | |
192 oop _threadObj; | |
193 java_lang_Thread::ThreadStatus _thread_status; | |
194 | |
195 bool _is_ext_suspended; | |
196 bool _is_in_native; | |
197 | |
198 jlong _contended_enter_ticks; | |
199 jlong _contended_enter_count; | |
200 jlong _monitor_wait_ticks; | |
201 jlong _monitor_wait_count; | |
202 jlong _sleep_ticks; | |
203 jlong _sleep_count; | |
204 oop _blocker_object; | |
205 oop _blocker_object_owner; | |
206 | |
207 ThreadStackTrace* _stack_trace; | |
208 ThreadConcurrentLocks* _concurrent_locks; | |
209 ThreadSnapshot* _next; | |
210 | |
211 public: | |
212 // Dummy snapshot | |
213 ThreadSnapshot() : _thread(NULL), _threadObj(NULL), _stack_trace(NULL), _concurrent_locks(NULL), _next(NULL), | |
214 _blocker_object(NULL), _blocker_object_owner(NULL) {}; | |
215 ThreadSnapshot(JavaThread* thread); | |
216 ~ThreadSnapshot(); | |
217 | |
218 java_lang_Thread::ThreadStatus thread_status() { return _thread_status; } | |
219 | |
220 oop threadObj() const { return _threadObj; } | |
221 | |
222 void set_next(ThreadSnapshot* n) { _next = n; } | |
223 | |
224 bool is_ext_suspended() { return _is_ext_suspended; } | |
225 bool is_in_native() { return _is_in_native; } | |
226 | |
227 jlong contended_enter_count() { return _contended_enter_count; } | |
228 jlong contended_enter_ticks() { return _contended_enter_ticks; } | |
229 jlong monitor_wait_count() { return _monitor_wait_count; } | |
230 jlong monitor_wait_ticks() { return _monitor_wait_ticks; } | |
231 jlong sleep_count() { return _sleep_count; } | |
232 jlong sleep_ticks() { return _sleep_ticks; } | |
233 | |
234 | |
235 oop blocker_object() { return _blocker_object; } | |
236 oop blocker_object_owner() { return _blocker_object_owner; } | |
237 | |
238 ThreadSnapshot* next() const { return _next; } | |
239 ThreadStackTrace* get_stack_trace() { return _stack_trace; } | |
240 ThreadConcurrentLocks* get_concurrent_locks() { return _concurrent_locks; } | |
241 | |
242 void dump_stack_at_safepoint(int max_depth, bool with_locked_monitors); | |
243 void set_concurrent_locks(ThreadConcurrentLocks* l) { _concurrent_locks = l; } | |
244 void oops_do(OopClosure* f); | |
245 }; | |
246 | |
6197 | 247 class ThreadStackTrace : public CHeapObj<mtInternal> { |
0 | 248 private: |
249 JavaThread* _thread; | |
250 int _depth; // number of stack frames added | |
251 bool _with_locked_monitors; | |
252 GrowableArray<StackFrameInfo*>* _frames; | |
253 GrowableArray<oop>* _jni_locked_monitors; | |
254 | |
255 public: | |
256 | |
257 ThreadStackTrace(JavaThread* thread, bool with_locked_monitors); | |
258 ~ThreadStackTrace(); | |
259 | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
0
diff
changeset
|
260 JavaThread* thread() { return _thread; } |
0 | 261 StackFrameInfo* stack_frame_at(int i) { return _frames->at(i); } |
262 int get_stack_depth() { return _depth; } | |
263 | |
264 void add_stack_frame(javaVFrame* jvf); | |
265 void dump_stack_at_safepoint(int max_depth); | |
266 Handle allocate_fill_stack_trace_element_array(TRAPS); | |
267 void oops_do(OopClosure* f); | |
268 GrowableArray<oop>* jni_locked_monitors() { return _jni_locked_monitors; } | |
269 int num_jni_locked_monitors() { return (_jni_locked_monitors != NULL ? _jni_locked_monitors->length() : 0); } | |
270 | |
271 bool is_owned_monitor_on_stack(oop object); | |
272 void add_jni_locked_monitor(oop object) { _jni_locked_monitors->append(object); } | |
273 }; | |
274 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
275 // StackFrameInfo for keeping Method* and bci during |
0 | 276 // stack walking for later construction of StackTraceElement[] |
277 // Java instances | |
6197 | 278 class StackFrameInfo : public CHeapObj<mtInternal> { |
0 | 279 private: |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
280 Method* _method; |
0 | 281 int _bci; |
282 GrowableArray<oop>* _locked_monitors; // list of object monitors locked by this frame | |
283 | |
284 public: | |
285 | |
286 StackFrameInfo(javaVFrame* jvf, bool with_locked_monitors); | |
287 ~StackFrameInfo() { | |
288 if (_locked_monitors != NULL) { | |
289 delete _locked_monitors; | |
290 } | |
291 }; | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
292 Method* method() const { return _method; } |
0 | 293 int bci() const { return _bci; } |
294 void oops_do(OopClosure* f); | |
295 | |
296 int num_locked_monitors() { return (_locked_monitors != NULL ? _locked_monitors->length() : 0); } | |
297 GrowableArray<oop>* locked_monitors() { return _locked_monitors; } | |
298 | |
299 void print_on(outputStream* st) const; | |
300 }; | |
301 | |
6197 | 302 class ThreadConcurrentLocks : public CHeapObj<mtInternal> { |
0 | 303 private: |
304 GrowableArray<instanceOop>* _owned_locks; | |
305 ThreadConcurrentLocks* _next; | |
306 JavaThread* _thread; | |
307 public: | |
308 ThreadConcurrentLocks(JavaThread* thread); | |
309 ~ThreadConcurrentLocks(); | |
310 | |
311 void add_lock(instanceOop o); | |
312 void set_next(ThreadConcurrentLocks* n) { _next = n; } | |
313 ThreadConcurrentLocks* next() { return _next; } | |
314 JavaThread* java_thread() { return _thread; } | |
315 GrowableArray<instanceOop>* owned_locks() { return _owned_locks; } | |
316 void oops_do(OopClosure* f); | |
317 }; | |
318 | |
319 class ConcurrentLocksDump : public StackObj { | |
320 private: | |
321 ThreadConcurrentLocks* _map; | |
322 ThreadConcurrentLocks* _last; // Last ThreadConcurrentLocks in the map | |
323 bool _retain_map_on_free; | |
324 | |
325 void build_map(GrowableArray<oop>* aos_objects); | |
326 void add_lock(JavaThread* thread, instanceOop o); | |
327 | |
328 public: | |
329 ConcurrentLocksDump(bool retain_map_on_free) : _map(NULL), _last(NULL), _retain_map_on_free(retain_map_on_free) {}; | |
330 ConcurrentLocksDump() : _map(NULL), _last(NULL), _retain_map_on_free(false) {}; | |
331 ~ConcurrentLocksDump(); | |
332 | |
333 void dump_at_safepoint(); | |
334 ThreadConcurrentLocks* thread_concurrent_locks(JavaThread* thread); | |
335 void print_locks_on(JavaThread* t, outputStream* st); | |
336 }; | |
337 | |
338 class ThreadDumpResult : public StackObj { | |
339 private: | |
340 int _num_threads; | |
341 int _num_snapshots; | |
342 ThreadSnapshot* _snapshots; | |
343 ThreadSnapshot* _last; | |
344 ThreadDumpResult* _next; | |
345 public: | |
346 ThreadDumpResult(); | |
347 ThreadDumpResult(int num_threads); | |
348 ~ThreadDumpResult(); | |
349 | |
350 void add_thread_snapshot(ThreadSnapshot* ts); | |
351 void set_next(ThreadDumpResult* next) { _next = next; } | |
352 ThreadDumpResult* next() { return _next; } | |
353 int num_threads() { return _num_threads; } | |
354 int num_snapshots() { return _num_snapshots; } | |
355 ThreadSnapshot* snapshots() { return _snapshots; } | |
356 void oops_do(OopClosure* f); | |
357 }; | |
358 | |
6197 | 359 class DeadlockCycle : public CHeapObj<mtInternal> { |
0 | 360 private: |
361 bool _is_deadlock; | |
362 GrowableArray<JavaThread*>* _threads; | |
363 DeadlockCycle* _next; | |
364 public: | |
365 DeadlockCycle(); | |
366 ~DeadlockCycle(); | |
367 | |
368 DeadlockCycle* next() { return _next; } | |
369 void set_next(DeadlockCycle* d) { _next = d; } | |
370 void add_thread(JavaThread* t) { _threads->append(t); } | |
371 void reset() { _is_deadlock = false; _threads->clear(); } | |
372 void set_deadlock(bool value) { _is_deadlock = value; } | |
373 bool is_deadlock() { return _is_deadlock; } | |
374 int num_threads() { return _threads->length(); } | |
375 GrowableArray<JavaThread*>* threads() { return _threads; } | |
376 void print_on(outputStream* st) const; | |
377 }; | |
378 | |
379 // Utility class to get list of java threads. | |
380 class ThreadsListEnumerator : public StackObj { | |
381 private: | |
382 GrowableArray<instanceHandle>* _threads_array; | |
383 public: | |
384 ThreadsListEnumerator(Thread* cur_thread, | |
385 bool include_jvmti_agent_threads = false, | |
386 bool include_jni_attaching_threads = true); | |
387 int num_threads() { return _threads_array->length(); } | |
388 instanceHandle get_threadObj(int index) { return _threads_array->at(index); } | |
389 }; | |
390 | |
391 | |
392 // abstract utility class to set new thread states, and restore previous after the block exits | |
393 class JavaThreadStatusChanger : public StackObj { | |
394 private: | |
395 java_lang_Thread::ThreadStatus _old_state; | |
396 JavaThread* _java_thread; | |
397 bool _is_alive; | |
398 | |
399 void save_old_state(JavaThread* java_thread) { | |
400 _java_thread = java_thread; | |
401 _is_alive = is_alive(java_thread); | |
402 if (is_alive()) { | |
403 _old_state = java_lang_Thread::get_thread_status(_java_thread->threadObj()); | |
404 } | |
405 } | |
406 | |
407 public: | |
408 static void set_thread_status(JavaThread* java_thread, | |
409 java_lang_Thread::ThreadStatus state) { | |
410 java_lang_Thread::set_thread_status(java_thread->threadObj(), state); | |
411 } | |
412 | |
413 void set_thread_status(java_lang_Thread::ThreadStatus state) { | |
414 if (is_alive()) { | |
415 set_thread_status(_java_thread, state); | |
416 } | |
417 } | |
418 | |
419 JavaThreadStatusChanger(JavaThread* java_thread, | |
420 java_lang_Thread::ThreadStatus state) { | |
421 save_old_state(java_thread); | |
422 set_thread_status(state); | |
423 } | |
424 | |
425 JavaThreadStatusChanger(JavaThread* java_thread) { | |
426 save_old_state(java_thread); | |
427 } | |
428 | |
429 ~JavaThreadStatusChanger() { | |
430 set_thread_status(_old_state); | |
431 } | |
432 | |
433 static bool is_alive(JavaThread* java_thread) { | |
434 return java_thread != NULL && java_thread->threadObj() != NULL; | |
435 } | |
436 | |
437 bool is_alive() { | |
438 return _is_alive; | |
439 } | |
440 }; | |
441 | |
442 // Change status to waiting on an object (timed or indefinite) | |
443 class JavaThreadInObjectWaitState : public JavaThreadStatusChanger { | |
444 private: | |
445 ThreadStatistics* _stat; | |
446 bool _active; | |
447 | |
448 public: | |
449 JavaThreadInObjectWaitState(JavaThread *java_thread, bool timed) : | |
450 JavaThreadStatusChanger(java_thread, | |
451 timed ? java_lang_Thread::IN_OBJECT_WAIT_TIMED : java_lang_Thread::IN_OBJECT_WAIT) { | |
452 if (is_alive()) { | |
453 _stat = java_thread->get_thread_stat(); | |
454 _active = ThreadService::is_thread_monitoring_contention(); | |
455 _stat->monitor_wait(); | |
456 if (_active) { | |
457 _stat->monitor_wait_begin(); | |
458 } | |
459 } else { | |
460 _active = false; | |
461 } | |
462 } | |
463 | |
464 ~JavaThreadInObjectWaitState() { | |
465 if (_active) { | |
466 _stat->monitor_wait_end(); | |
467 } | |
468 } | |
469 }; | |
470 | |
471 // Change status to parked (timed or indefinite) | |
472 class JavaThreadParkedState : public JavaThreadStatusChanger { | |
473 private: | |
474 ThreadStatistics* _stat; | |
475 bool _active; | |
476 | |
477 public: | |
478 JavaThreadParkedState(JavaThread *java_thread, bool timed) : | |
479 JavaThreadStatusChanger(java_thread, | |
480 timed ? java_lang_Thread::PARKED_TIMED : java_lang_Thread::PARKED) { | |
481 if (is_alive()) { | |
482 _stat = java_thread->get_thread_stat(); | |
483 _active = ThreadService::is_thread_monitoring_contention(); | |
484 _stat->monitor_wait(); | |
485 if (_active) { | |
486 _stat->monitor_wait_begin(); | |
487 } | |
488 } else { | |
489 _active = false; | |
490 } | |
491 } | |
492 | |
493 ~JavaThreadParkedState() { | |
494 if (_active) { | |
495 _stat->monitor_wait_end(); | |
496 } | |
497 } | |
498 }; | |
499 | |
500 // Change status to blocked on (re-)entering a synchronization block | |
501 class JavaThreadBlockedOnMonitorEnterState : public JavaThreadStatusChanger { | |
502 private: | |
503 ThreadStatistics* _stat; | |
504 bool _active; | |
505 | |
506 static bool contended_enter_begin(JavaThread *java_thread) { | |
507 set_thread_status(java_thread, java_lang_Thread::BLOCKED_ON_MONITOR_ENTER); | |
508 ThreadStatistics* stat = java_thread->get_thread_stat(); | |
509 stat->contended_enter(); | |
510 bool active = ThreadService::is_thread_monitoring_contention(); | |
511 if (active) { | |
512 stat->contended_enter_begin(); | |
513 } | |
514 return active; | |
515 } | |
516 | |
517 public: | |
518 // java_thread is waiting thread being blocked on monitor reenter. | |
519 // Current thread is the notifying thread which holds the monitor. | |
520 static bool wait_reenter_begin(JavaThread *java_thread, ObjectMonitor *obj_m) { | |
521 assert((java_thread != NULL), "Java thread should not be null here"); | |
522 bool active = false; | |
523 if (is_alive(java_thread) && ServiceUtil::visible_oop((oop)obj_m->object())) { | |
524 active = contended_enter_begin(java_thread); | |
525 } | |
526 return active; | |
527 } | |
528 | |
529 static void wait_reenter_end(JavaThread *java_thread, bool active) { | |
530 if (active) { | |
531 java_thread->get_thread_stat()->contended_enter_end(); | |
532 } | |
533 set_thread_status(java_thread, java_lang_Thread::RUNNABLE); | |
534 } | |
535 | |
536 JavaThreadBlockedOnMonitorEnterState(JavaThread *java_thread, ObjectMonitor *obj_m) : | |
537 JavaThreadStatusChanger(java_thread) { | |
538 assert((java_thread != NULL), "Java thread should not be null here"); | |
539 // Change thread status and collect contended enter stats for monitor contended | |
540 // enter done for external java world objects and it is contended. All other cases | |
541 // like for vm internal objects and for external objects which are not contended | |
542 // thread status is not changed and contended enter stat is not collected. | |
543 _active = false; | |
544 if (is_alive() && ServiceUtil::visible_oop((oop)obj_m->object()) && obj_m->contentions() > 0) { | |
545 _stat = java_thread->get_thread_stat(); | |
546 _active = contended_enter_begin(java_thread); | |
547 } | |
548 } | |
549 | |
550 ~JavaThreadBlockedOnMonitorEnterState() { | |
551 if (_active) { | |
552 _stat->contended_enter_end(); | |
553 } | |
554 } | |
555 }; | |
556 | |
557 // Change status to sleeping | |
558 class JavaThreadSleepState : public JavaThreadStatusChanger { | |
559 private: | |
560 ThreadStatistics* _stat; | |
561 bool _active; | |
562 public: | |
563 JavaThreadSleepState(JavaThread *java_thread) : | |
564 JavaThreadStatusChanger(java_thread, java_lang_Thread::SLEEPING) { | |
565 if (is_alive()) { | |
566 _stat = java_thread->get_thread_stat(); | |
567 _active = ThreadService::is_thread_monitoring_contention(); | |
568 _stat->thread_sleep(); | |
569 if (_active) { | |
570 _stat->thread_sleep_begin(); | |
571 } | |
572 } else { | |
573 _active = false; | |
574 } | |
575 } | |
576 | |
577 ~JavaThreadSleepState() { | |
578 if (_active) { | |
579 _stat->thread_sleep_end(); | |
580 } | |
581 } | |
582 }; | |
1972 | 583 |
584 #endif // SHARE_VM_SERVICES_THREADSERVICE_HPP |