threadService.hpp revision 5776:de6a9e811145
1164640Sflz/*
298186Sgordon * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
378344Sobrien * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4157473Sflz *
578344Sobrien * This code is free software; you can redistribute it and/or modify it
678344Sobrien * under the terms of the GNU General Public License version 2 only, as
778344Sobrien * published by the Free Software Foundation.
878344Sobrien *
978344Sobrien * This code is distributed in the hope that it will be useful, but WITHOUT
1078344Sobrien * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1178344Sobrien * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1278344Sobrien * version 2 for more details (a copy is included in the LICENSE file that
1378344Sobrien * accompanied this code).
1478344Sobrien *
1578344Sobrien * You should have received a copy of the GNU General Public License version
1678344Sobrien * 2 along with this work; if not, write to the Free Software Foundation,
1778344Sobrien * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1878344Sobrien *
1978344Sobrien * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2078344Sobrien * or visit www.oracle.com if you need additional information or have any
2178344Sobrien * questions.
2278344Sobrien *
2378344Sobrien */
2478344Sobrien
2578344Sobrien#ifndef SHARE_VM_SERVICES_THREADSERVICE_HPP
2678344Sobrien#define SHARE_VM_SERVICES_THREADSERVICE_HPP
2778344Sobrien
2878344Sobrien#include "classfile/javaClasses.hpp"
2978344Sobrien#include "runtime/handles.hpp"
3078344Sobrien#include "runtime/init.hpp"
3178344Sobrien#include "runtime/jniHandles.hpp"
3278344Sobrien#include "runtime/objectMonitor.hpp"
3378344Sobrien#include "runtime/objectMonitor.inline.hpp"
3478344Sobrien#include "runtime/perfData.hpp"
35169668Smtm#include "services/management.hpp"
36157473Sflz#include "services/serviceUtil.hpp"
3778344Sobrien
3898186Sgordonclass OopClosure;
3998186Sgordonclass ThreadDumpResult;
4098186Sgordonclass ThreadStackTrace;
41131550Scpercivaclass ThreadSnapshot;
42131550Scpercivaclass StackFrameInfo;
43131550Scpercivaclass ThreadConcurrentLocks;
44131550Scpercivaclass DeadlockCycle;
4598186Sgordon
4698186Sgordon// VM monitoring and management support for the thread and
47202988Semaste// synchronization subsystem
48295949Saraujo//
49124832Smtm// Thread contention monitoring is disabled by default.
50124832Smtm// When enabled, the VM will begin measuring the accumulated
51161435Syar// elapsed time a thread blocked on synchronization.
52161435Syar//
5398186Sgordonclass ThreadService : public AllStatic {
5498186Sgordonprivate:
5578344Sobrien  // These counters could be moved to Threads class
5678344Sobrien  static PerfCounter*  _total_threads_count;
5778344Sobrien  static PerfVariable* _live_threads_count;
58264243Sdteske  static PerfVariable* _peak_threads_count;
59264243Sdteske  static PerfVariable* _daemon_threads_count;
60264243Sdteske
61264243Sdteske  // These 2 counters are atomically incremented once the thread is exiting.
62264243Sdteske  // They will be atomically decremented when ThreadService::remove_thread is called.
63264243Sdteske  static volatile int  _exiting_threads_count;
64264243Sdteske  static volatile int  _exiting_daemon_threads_count;
65264243Sdteske
66264243Sdteske  static bool          _thread_monitoring_contention_enabled;
67264243Sdteske  static bool          _thread_cpu_time_enabled;
68264243Sdteske  static bool          _thread_allocated_memory_enabled;
69264243Sdteske
70264243Sdteske  // Need to keep the list of thread dump result that
71264243Sdteske  // keep references to Method* since thread dump can be
72272393Shrs  // requested by multiple threads concurrently.
73272393Shrs  static ThreadDumpResult* _threaddump_list;
74272393Shrs
75272393Shrspublic:
76272393Shrs  static void init();
77272393Shrs  static void add_thread(JavaThread* thread, bool daemon);
78272393Shrs  static void remove_thread(JavaThread* thread, bool daemon);
79272393Shrs  static void current_thread_exiting(JavaThread* jt);
80272393Shrs
81272393Shrs  static bool set_thread_monitoring_contention(bool flag);
82272393Shrs  static bool is_thread_monitoring_contention() { return _thread_monitoring_contention_enabled; }
83272393Shrs
84272393Shrs  static bool set_thread_cpu_time_enabled(bool flag);
85272393Shrs  static bool is_thread_cpu_time_enabled()    { return _thread_cpu_time_enabled; }
86272393Shrs
87272393Shrs  static bool set_thread_allocated_memory_enabled(bool flag);
88272393Shrs  static bool is_thread_allocated_memory_enabled() { return _thread_cpu_time_enabled; }
89272393Shrs
90272393Shrs  static jlong get_total_thread_count()       { return _total_threads_count->get_value(); }
91272393Shrs  static jlong get_peak_thread_count()        { return _peak_threads_count->get_value(); }
92272393Shrs  static jlong get_live_thread_count()        { return _live_threads_count->get_value() - _exiting_threads_count; }
93272393Shrs  static jlong get_daemon_thread_count()      { return _daemon_threads_count->get_value() - _exiting_daemon_threads_count; }
94272393Shrs
95272393Shrs  static int   exiting_threads_count()        { return _exiting_threads_count; }
96272393Shrs  static int   exiting_daemon_threads_count() { return _exiting_daemon_threads_count; }
97272393Shrs
98272393Shrs  // Support for thread dump
99272393Shrs  static void   add_thread_dump(ThreadDumpResult* dump);
100272393Shrs  static void   remove_thread_dump(ThreadDumpResult* dump);
101272393Shrs
102272393Shrs  static Handle get_current_contended_monitor(JavaThread* thread);
103272393Shrs
104272393Shrs  // This function is called by JVM_DumpThreads.
105197144Shrs  static Handle dump_stack_traces(GrowableArray<instanceHandle>* threads,
106197144Shrs                                  int num_threads, TRAPS);
107197144Shrs
10898186Sgordon  static void   reset_peak_thread_count();
109197144Shrs  static void   reset_contention_count_stat(JavaThread* thread);
110197144Shrs  static void   reset_contention_time_stat(JavaThread* thread);
111197144Shrs
112197144Shrs  static DeadlockCycle*       find_deadlocks_at_safepoint(bool object_monitors_only);
113272393Shrs
114197144Shrs  // GC support
115197144Shrs  static void   oops_do(OopClosure* f);
116197144Shrs  static void   metadata_do(void f(Metadata*));
117197144Shrs};
118197144Shrs
119197144Shrs// Per-thread Statistics for synchronization
120197144Shrsclass ThreadStatistics : public CHeapObj<mtInternal> {
121197144Shrsprivate:
122231667Sdougb  // The following contention statistics are only updated by
12398186Sgordon  // the thread owning these statistics when contention occurs.
124231667Sdougb
12598186Sgordon  jlong        _contended_enter_count;
126231667Sdougb  elapsedTimer _contended_enter_timer;
12798186Sgordon  jlong        _monitor_wait_count;
12898186Sgordon  elapsedTimer _monitor_wait_timer;
12998186Sgordon  jlong        _sleep_count;
130231667Sdougb  elapsedTimer _sleep_timer;
131231667Sdougb
13298186Sgordon
133231667Sdougb  // These two reset flags are set to true when another thread
13498186Sgordon  // requests to reset the statistics.  The actual statistics
135231667Sdougb  // are reset when the thread contention occurs and attempts
136231667Sdougb  // to update the statistics.
137231667Sdougb  bool         _count_pending_reset;
138231667Sdougb  bool         _timer_pending_reset;
139231667Sdougb
14098186Sgordon  // Keep accurate times for potentially recursive class operations
141146490Sschweikh  int           _perf_recursion_counts[6];
14298186Sgordon  elapsedTimer  _perf_timers[6];
14398186Sgordon
14498186Sgordon  // utility functions
14598186Sgordon  void  check_and_reset_count()            {
14698186Sgordon                                             if (!_count_pending_reset) return;
14798186Sgordon                                             _contended_enter_count = 0;
14878344Sobrien                                             _monitor_wait_count = 0;
14978344Sobrien                                             _sleep_count = 0;
15078344Sobrien                                             _count_pending_reset = 0;
15178344Sobrien                                           }
15278344Sobrien  void  check_and_reset_timer()            {
15378344Sobrien                                             if (!_timer_pending_reset) return;
15478344Sobrien                                             _contended_enter_timer.reset();
15598186Sgordon                                             _monitor_wait_timer.reset();
15678344Sobrien                                             _sleep_timer.reset();
15778344Sobrien                                             _timer_pending_reset = 0;
15878344Sobrien                                           }
15978344Sobrien
16078344Sobrienpublic:
16178344Sobrien  ThreadStatistics();
16278344Sobrien
16378344Sobrien  jlong contended_enter_count()            { return (_count_pending_reset ? 0 : _contended_enter_count); }
16478344Sobrien  jlong contended_enter_ticks()            { return (_timer_pending_reset ? 0 : _contended_enter_timer.active_ticks()); }
16578344Sobrien  jlong monitor_wait_count()               { return (_count_pending_reset ? 0 : _monitor_wait_count); }
16678344Sobrien  jlong monitor_wait_ticks()               { return (_timer_pending_reset ? 0 : _monitor_wait_timer.active_ticks()); }
16778344Sobrien  jlong sleep_count()                      { return (_count_pending_reset ? 0 : _sleep_count); }
168229822Sdougb  jlong sleep_ticks()                      { return (_timer_pending_reset ? 0 : _sleep_timer.active_ticks()); }
16978344Sobrien
17078344Sobrien  void monitor_wait()                      { check_and_reset_count(); _monitor_wait_count++; }
17178344Sobrien  void monitor_wait_begin()                { check_and_reset_timer(); _monitor_wait_timer.start(); }
17278344Sobrien  void monitor_wait_end()                  { _monitor_wait_timer.stop(); check_and_reset_timer(); }
17378344Sobrien
174157473Sflz  void thread_sleep()                      { check_and_reset_count(); _sleep_count++; }
17598186Sgordon  void thread_sleep_begin()                { check_and_reset_timer(); _sleep_timer.start(); }
17698186Sgordon  void thread_sleep_end()                  { _sleep_timer.stop(); check_and_reset_timer(); }
17778344Sobrien
17898186Sgordon  void contended_enter()                   { check_and_reset_count(); _contended_enter_count++; }
17998186Sgordon  void contended_enter_begin()             { check_and_reset_timer(); _contended_enter_timer.start(); }
18098186Sgordon  void contended_enter_end()               { _contended_enter_timer.stop(); check_and_reset_timer(); }
181126286Smtm
18298186Sgordon  void reset_count_stat()                  { _count_pending_reset = true; }
18398186Sgordon  void reset_time_stat()                   { _timer_pending_reset = true; }
18498186Sgordon
18598186Sgordon  int* perf_recursion_counts_addr()        { return _perf_recursion_counts; }
18698186Sgordon  elapsedTimer* perf_timers_addr()         { return _perf_timers; }
187169668Smtm};
188169668Smtm
189169668Smtm// Thread snapshot to represent the thread state and statistics
190169668Smtmclass ThreadSnapshot : public CHeapObj<mtInternal> {
19178344Sobrienprivate:
192169668Smtm  JavaThread* _thread;
193169668Smtm  oop         _threadObj;
194169668Smtm  java_lang_Thread::ThreadStatus _thread_status;
195169668Smtm
196178776Smaxim  bool    _is_ext_suspended;
197178776Smaxim  bool    _is_in_native;
198178770Smtm
199169668Smtm  jlong   _contended_enter_ticks;
200178770Smtm  jlong   _contended_enter_count;
201178770Smtm  jlong   _monitor_wait_ticks;
202169668Smtm  jlong   _monitor_wait_count;
203178770Smtm  jlong   _sleep_ticks;
204178775Smaxim  jlong   _sleep_count;
205169668Smtm  oop     _blocker_object;
206169668Smtm  oop     _blocker_object_owner;
207169668Smtm
208169668Smtm  ThreadStackTrace*      _stack_trace;
209169668Smtm  ThreadConcurrentLocks* _concurrent_locks;
210169668Smtm  ThreadSnapshot*        _next;
211169668Smtm
212169668Smtmpublic:
21398186Sgordon  // Dummy snapshot
21498186Sgordon  ThreadSnapshot() : _thread(NULL), _threadObj(NULL), _stack_trace(NULL), _concurrent_locks(NULL), _next(NULL),
21598186Sgordon                     _blocker_object(NULL), _blocker_object_owner(NULL) {};
21698186Sgordon  ThreadSnapshot(JavaThread* thread);
21798186Sgordon  ~ThreadSnapshot();
21878344Sobrien
21978344Sobrien  java_lang_Thread::ThreadStatus thread_status() { return _thread_status; }
22098186Sgordon
22178344Sobrien  oop         threadObj() const           { return _threadObj; }
22278344Sobrien
223126285Smtm  void        set_next(ThreadSnapshot* n) { _next = n; }
22478344Sobrien
22578344Sobrien  bool        is_ext_suspended()          { return _is_ext_suspended; }
226126285Smtm  bool        is_in_native()              { return _is_in_native; }
22778344Sobrien
22878344Sobrien  jlong       contended_enter_count()     { return _contended_enter_count; }
229126285Smtm  jlong       contended_enter_ticks()     { return _contended_enter_ticks; }
230126285Smtm  jlong       monitor_wait_count()        { return _monitor_wait_count; }
231126285Smtm  jlong       monitor_wait_ticks()        { return _monitor_wait_ticks; }
23278344Sobrien  jlong       sleep_count()               { return _sleep_count; }
23378344Sobrien  jlong       sleep_ticks()               { return _sleep_ticks; }
23498186Sgordon
23578344Sobrien
23678344Sobrien  oop         blocker_object()            { return _blocker_object; }
23778344Sobrien  oop         blocker_object_owner()      { return _blocker_object_owner; }
23878344Sobrien
23998186Sgordon  ThreadSnapshot*   next() const          { return _next; }
24098186Sgordon  ThreadStackTrace* get_stack_trace()     { return _stack_trace; }
24178344Sobrien  ThreadConcurrentLocks* get_concurrent_locks()     { return _concurrent_locks; }
24298186Sgordon
24398186Sgordon  void        dump_stack_at_safepoint(int max_depth, bool with_locked_monitors);
24478344Sobrien  void        set_concurrent_locks(ThreadConcurrentLocks* l) { _concurrent_locks = l; }
24578344Sobrien  void        oops_do(OopClosure* f);
24678344Sobrien  void        metadata_do(void f(Metadata*));
24778344Sobrien};
24878344Sobrien
24998186Sgordonclass ThreadStackTrace : public CHeapObj<mtInternal> {
25078344Sobrien private:
25198186Sgordon  JavaThread*                     _thread;
25278344Sobrien  int                             _depth;  // number of stack frames added
25378344Sobrien  bool                            _with_locked_monitors;
254131061Smtm  GrowableArray<StackFrameInfo*>* _frames;
25578344Sobrien  GrowableArray<oop>*             _jni_locked_monitors;
25678344Sobrien
25778344Sobrien public:
25878344Sobrien
259139949Skeramida  ThreadStackTrace(JavaThread* thread, bool with_locked_monitors);
26078344Sobrien  ~ThreadStackTrace();
26178344Sobrien
26298186Sgordon  JavaThread*     thread()              { return _thread; }
26378344Sobrien  StackFrameInfo* stack_frame_at(int i) { return _frames->at(i); }
26478344Sobrien  int             get_stack_depth()     { return _depth; }
26578344Sobrien
26698186Sgordon  void            add_stack_frame(javaVFrame* jvf);
26778344Sobrien  void            dump_stack_at_safepoint(int max_depth);
26898186Sgordon  Handle          allocate_fill_stack_trace_element_array(TRAPS);
26998186Sgordon  void            oops_do(OopClosure* f);
27078344Sobrien  void            metadata_do(void f(Metadata*));
27178344Sobrien  GrowableArray<oop>* jni_locked_monitors() { return _jni_locked_monitors; }
27278344Sobrien  int             num_jni_locked_monitors() { return (_jni_locked_monitors != NULL ? _jni_locked_monitors->length() : 0); }
27378344Sobrien
27498186Sgordon  bool            is_owned_monitor_on_stack(oop object);
27578344Sobrien  void            add_jni_locked_monitor(oop object) { _jni_locked_monitors->append(object); }
27698186Sgordon};
27778344Sobrien
27898186Sgordon// StackFrameInfo for keeping Method* and bci during
27998186Sgordon// stack walking for later construction of StackTraceElement[]
28098186Sgordon// Java instances
28198186Sgordonclass StackFrameInfo : public CHeapObj<mtInternal> {
28298186Sgordon private:
28398186Sgordon  Method*             _method;
28498186Sgordon  int                 _bci;
28598186Sgordon  GrowableArray<oop>* _locked_monitors; // list of object monitors locked by this frame
28698186Sgordon  // We need to save the mirrors in the backtrace to keep the class
28798186Sgordon  // from being unloaded while we still have this stack trace.
28898186Sgordon  oop                 _class_holder;
28998186Sgordon
29098186Sgordon public:
29198186Sgordon
292155719Sceri  StackFrameInfo(javaVFrame* jvf, bool with_locked_monitors);
29398186Sgordon  ~StackFrameInfo() {
29498186Sgordon    if (_locked_monitors != NULL) {
29598186Sgordon      delete _locked_monitors;
29698186Sgordon    }
297157841Sflz  };
298157841Sflz  Method*   method() const       { return _method; }
299157841Sflz  int       bci()    const       { return _bci; }
30098186Sgordon  void      oops_do(OopClosure* f);
30198186Sgordon  void      metadata_do(void f(Metadata*));
30298186Sgordon
30398186Sgordon  int       num_locked_monitors()       { return (_locked_monitors != NULL ? _locked_monitors->length() : 0); }
30498186Sgordon  GrowableArray<oop>* locked_monitors() { return _locked_monitors; }
30598186Sgordon
30698186Sgordon  void      print_on(outputStream* st) const;
30798186Sgordon};
30898186Sgordon
30998186Sgordonclass ThreadConcurrentLocks : public CHeapObj<mtInternal> {
31078344Sobrienprivate:
31198186Sgordon  GrowableArray<instanceOop>* _owned_locks;
312242183Screes  ThreadConcurrentLocks*      _next;
313242183Screes  JavaThread*                 _thread;
314170282Syar public:
315170282Syar  ThreadConcurrentLocks(JavaThread* thread);
316170282Syar  ~ThreadConcurrentLocks();
317170282Syar
318170282Syar  void                        add_lock(instanceOop o);
319170282Syar  void                        set_next(ThreadConcurrentLocks* n) { _next = n; }
320170282Syar  ThreadConcurrentLocks*      next() { return _next; }
321170282Syar  JavaThread*                 java_thread()                      { return _thread; }
322170282Syar  GrowableArray<instanceOop>* owned_locks()                      { return _owned_locks; }
323170282Syar  void                        oops_do(OopClosure* f);
324170282Syar};
325170282Syar
326170282Syarclass ConcurrentLocksDump : public StackObj {
327170282Syar private:
328170282Syar  ThreadConcurrentLocks* _map;
329170282Syar  ThreadConcurrentLocks* _last;   // Last ThreadConcurrentLocks in the map
330170282Syar  bool                   _retain_map_on_free;
331170282Syar
332170282Syar  void build_map(GrowableArray<oop>* aos_objects);
333170282Syar  void add_lock(JavaThread* thread, instanceOop o);
334170282Syar
335170282Syar public:
33678344Sobrien  ConcurrentLocksDump(bool retain_map_on_free) : _map(NULL), _last(NULL), _retain_map_on_free(retain_map_on_free) {};
33798186Sgordon  ConcurrentLocksDump() : _map(NULL), _last(NULL), _retain_map_on_free(false) {};
338157841Sflz  ~ConcurrentLocksDump();
33998186Sgordon
34098186Sgordon  void                        dump_at_safepoint();
341245250Ssmh  ThreadConcurrentLocks*      thread_concurrent_locks(JavaThread* thread);
34298186Sgordon  void                        print_locks_on(JavaThread* t, outputStream* st);
34398186Sgordon};
34498186Sgordon
34598186Sgordonclass ThreadDumpResult : public StackObj {
346151426Sjhb private:
34798186Sgordon  int                  _num_threads;
34898186Sgordon  int                  _num_snapshots;
349161435Syar  ThreadSnapshot*      _snapshots;
350161436Syar  ThreadSnapshot*      _last;
351157657Sflz  ThreadDumpResult*    _next;
352161436Syar public:
353157657Sflz  ThreadDumpResult();
354157657Sflz  ThreadDumpResult(int num_threads);
355157657Sflz  ~ThreadDumpResult();
356157657Sflz
35798186Sgordon  void                 add_thread_snapshot(ThreadSnapshot* ts);
35898186Sgordon  void                 set_next(ThreadDumpResult* next) { _next = next; }
35998186Sgordon  ThreadDumpResult*    next()                           { return _next; }
36098186Sgordon  int                  num_threads()                    { return _num_threads; }
361114272Smtm  int                  num_snapshots()                  { return _num_snapshots; }
36298186Sgordon  ThreadSnapshot*      snapshots()                      { return _snapshots; }
36398186Sgordon  void                 oops_do(OopClosure* f);
36498186Sgordon  void                 metadata_do(void f(Metadata*));
365264243Sdteske};
366264243Sdteske
367264243Sdteskeclass DeadlockCycle : public CHeapObj<mtInternal> {
368264243Sdteske private:
36998186Sgordon  bool _is_deadlock;
370264243Sdteske  GrowableArray<JavaThread*>* _threads;
371264243Sdteske  DeadlockCycle*              _next;
372264243Sdteske public:
373264243Sdteske  DeadlockCycle();
374264243Sdteske  ~DeadlockCycle();
375264243Sdteske
376264243Sdteske  DeadlockCycle* next()                     { return _next; }
377264243Sdteske  void           set_next(DeadlockCycle* d) { _next = d; }
378264243Sdteske  void           add_thread(JavaThread* t)  { _threads->append(t); }
379264243Sdteske  void           reset()                    { _is_deadlock = false; _threads->clear(); }
380264243Sdteske  void           set_deadlock(bool value)   { _is_deadlock = value; }
381264243Sdteske  bool           is_deadlock()              { return _is_deadlock; }
382264243Sdteske  int            num_threads()              { return _threads->length(); }
383264243Sdteske  GrowableArray<JavaThread*>* threads()     { return _threads; }
384264243Sdteske  void           print_on(outputStream* st) const;
385264243Sdteske};
386264243Sdteske
387264243Sdteske// Utility class to get list of java threads.
388264243Sdteskeclass ThreadsListEnumerator : public StackObj {
389264243Sdteskeprivate:
390264243Sdteske  GrowableArray<instanceHandle>* _threads_array;
391264243Sdteskepublic:
392264243Sdteske  ThreadsListEnumerator(Thread* cur_thread,
393264243Sdteske                        bool include_jvmti_agent_threads = false,
394264243Sdteske                        bool include_jni_attaching_threads = true);
395264243Sdteske  int            num_threads()            { return _threads_array->length(); }
396264243Sdteske  instanceHandle get_threadObj(int index) { return _threads_array->at(index); }
397264243Sdteske};
398264243Sdteske
399264243Sdteske
400264243Sdteske// abstract utility class to set new thread states, and restore previous after the block exits
401264243Sdteskeclass JavaThreadStatusChanger : public StackObj {
402264243Sdteske private:
403264243Sdteske  java_lang_Thread::ThreadStatus _old_state;
404264243Sdteske  JavaThread*  _java_thread;
405264243Sdteske  bool _is_alive;
406264243Sdteske
407264243Sdteske  void save_old_state(JavaThread* java_thread) {
408264243Sdteske    _java_thread  = java_thread;
409264243Sdteske    _is_alive = is_alive(java_thread);
410264243Sdteske    if (is_alive()) {
411264243Sdteske      _old_state = java_lang_Thread::get_thread_status(_java_thread->threadObj());
412264243Sdteske    }
413264243Sdteske  }
414264243Sdteske
415264243Sdteske public:
416264243Sdteske  static void set_thread_status(JavaThread* java_thread,
417264243Sdteske                                java_lang_Thread::ThreadStatus state) {
418264243Sdteske    java_lang_Thread::set_thread_status(java_thread->threadObj(), state);
419264243Sdteske  }
420264243Sdteske
421264243Sdteske  void set_thread_status(java_lang_Thread::ThreadStatus state) {
422264243Sdteske    if (is_alive()) {
423264243Sdteske      set_thread_status(_java_thread, state);
424264243Sdteske    }
425264243Sdteske  }
426264243Sdteske
427264243Sdteske  JavaThreadStatusChanger(JavaThread* java_thread,
428264243Sdteske                          java_lang_Thread::ThreadStatus state) {
429264243Sdteske    save_old_state(java_thread);
430264243Sdteske    set_thread_status(state);
431264243Sdteske  }
432264243Sdteske
433264243Sdteske  JavaThreadStatusChanger(JavaThread* java_thread) {
434264243Sdteske    save_old_state(java_thread);
435264243Sdteske  }
436264243Sdteske
437264243Sdteske  ~JavaThreadStatusChanger() {
438264243Sdteske    set_thread_status(_old_state);
439264243Sdteske  }
440264243Sdteske
441264243Sdteske  static bool is_alive(JavaThread* java_thread) {
442264243Sdteske    return java_thread != NULL && java_thread->threadObj() != NULL;
443264243Sdteske  }
444264243Sdteske
445264243Sdteske  bool is_alive() {
446264243Sdteske    return _is_alive;
447264243Sdteske  }
448264243Sdteske};
449264243Sdteske
450264243Sdteske// Change status to waiting on an object  (timed or indefinite)
451264243Sdteskeclass JavaThreadInObjectWaitState : public JavaThreadStatusChanger {
452264243Sdteske private:
453264243Sdteske  ThreadStatistics* _stat;
454264243Sdteske  bool _active;
455264243Sdteske
456264243Sdteske public:
457264243Sdteske  JavaThreadInObjectWaitState(JavaThread *java_thread, bool timed) :
458264243Sdteske    JavaThreadStatusChanger(java_thread,
459264243Sdteske                            timed ? java_lang_Thread::IN_OBJECT_WAIT_TIMED : java_lang_Thread::IN_OBJECT_WAIT) {
460264243Sdteske    if (is_alive()) {
461264243Sdteske      _stat = java_thread->get_thread_stat();
462264243Sdteske      _active = ThreadService::is_thread_monitoring_contention();
463264243Sdteske      _stat->monitor_wait();
464264243Sdteske      if (_active) {
465264243Sdteske        _stat->monitor_wait_begin();
466264243Sdteske      }
467264243Sdteske    } else {
468264243Sdteske      _active = false;
469264243Sdteske    }
470264243Sdteske  }
471264243Sdteske
472264243Sdteske  ~JavaThreadInObjectWaitState() {
473264243Sdteske    if (_active) {
474264243Sdteske      _stat->monitor_wait_end();
475264243Sdteske    }
476264243Sdteske  }
477264243Sdteske};
478264243Sdteske
479264243Sdteske// Change status to parked (timed or indefinite)
480264243Sdteskeclass JavaThreadParkedState : public JavaThreadStatusChanger {
481264243Sdteske private:
482264243Sdteske  ThreadStatistics* _stat;
483264243Sdteske  bool _active;
484264243Sdteske
485264243Sdteske public:
486264243Sdteske  JavaThreadParkedState(JavaThread *java_thread, bool timed) :
487264243Sdteske    JavaThreadStatusChanger(java_thread,
488264243Sdteske                            timed ? java_lang_Thread::PARKED_TIMED : java_lang_Thread::PARKED) {
489264243Sdteske    if (is_alive()) {
490264243Sdteske      _stat = java_thread->get_thread_stat();
491264243Sdteske      _active = ThreadService::is_thread_monitoring_contention();
492264243Sdteske      _stat->monitor_wait();
493264243Sdteske      if (_active) {
494264243Sdteske        _stat->monitor_wait_begin();
495264243Sdteske      }
496264243Sdteske    } else {
497264243Sdteske      _active = false;
498264243Sdteske    }
499264243Sdteske  }
500264243Sdteske
501264243Sdteske  ~JavaThreadParkedState() {
502264243Sdteske    if (_active) {
503264243Sdteske      _stat->monitor_wait_end();
504264243Sdteske    }
505264243Sdteske  }
506264243Sdteske};
507264243Sdteske
508264243Sdteske// Change status to blocked on (re-)entering a synchronization block
509264243Sdteskeclass JavaThreadBlockedOnMonitorEnterState : public JavaThreadStatusChanger {
510264243Sdteske private:
511264243Sdteske  ThreadStatistics* _stat;
512264243Sdteske  bool _active;
513264243Sdteske
514264243Sdteske  static bool contended_enter_begin(JavaThread *java_thread) {
515264243Sdteske    set_thread_status(java_thread, java_lang_Thread::BLOCKED_ON_MONITOR_ENTER);
516264243Sdteske    ThreadStatistics* stat = java_thread->get_thread_stat();
517264243Sdteske    stat->contended_enter();
518264243Sdteske    bool active = ThreadService::is_thread_monitoring_contention();
519264243Sdteske    if (active) {
520264243Sdteske      stat->contended_enter_begin();
521264243Sdteske    }
522264243Sdteske    return active;
523264243Sdteske  }
524264243Sdteske
525264243Sdteske public:
526264243Sdteske  // java_thread is waiting thread being blocked on monitor reenter.
527264243Sdteske  // Current thread is the notifying thread which holds the monitor.
528264243Sdteske  static bool wait_reenter_begin(JavaThread *java_thread, ObjectMonitor *obj_m) {
529264243Sdteske    assert((java_thread != NULL), "Java thread should not be null here");
530264243Sdteske    bool active  = false;
531264243Sdteske    if (is_alive(java_thread) && ServiceUtil::visible_oop((oop)obj_m->object())) {
532264243Sdteske      active = contended_enter_begin(java_thread);
533264243Sdteske    }
534264243Sdteske    return active;
535264243Sdteske  }
536264243Sdteske
537264243Sdteske  static void wait_reenter_end(JavaThread *java_thread, bool active) {
538264243Sdteske    if (active) {
539264243Sdteske      java_thread->get_thread_stat()->contended_enter_end();
540264243Sdteske    }
541264243Sdteske    set_thread_status(java_thread, java_lang_Thread::RUNNABLE);
542264243Sdteske  }
543264243Sdteske
544264243Sdteske  JavaThreadBlockedOnMonitorEnterState(JavaThread *java_thread, ObjectMonitor *obj_m) :
545264243Sdteske    JavaThreadStatusChanger(java_thread) {
546264243Sdteske    assert((java_thread != NULL), "Java thread should not be null here");
547264243Sdteske    // Change thread status and collect contended enter stats for monitor contended
548264243Sdteske    // enter done for external java world objects and it is contended. All other cases
549264243Sdteske    // like for vm internal objects and for external objects which are not contended
550264243Sdteske    // thread status is not changed and contended enter stat is not collected.
551264243Sdteske    _active = false;
552264243Sdteske    if (is_alive() && ServiceUtil::visible_oop((oop)obj_m->object()) && obj_m->contentions() > 0) {
553264243Sdteske      _stat = java_thread->get_thread_stat();
554264243Sdteske      _active = contended_enter_begin(java_thread);
555264243Sdteske    }
556264243Sdteske  }
557264243Sdteske
558264243Sdteske  ~JavaThreadBlockedOnMonitorEnterState() {
559264243Sdteske    if (_active) {
560264243Sdteske      _stat->contended_enter_end();
561264243Sdteske    }
562264243Sdteske  }
563264243Sdteske};
564264243Sdteske
565264243Sdteske// Change status to sleeping
566264243Sdteskeclass JavaThreadSleepState : public JavaThreadStatusChanger {
567264243Sdteske private:
568264243Sdteske  ThreadStatistics* _stat;
569264243Sdteske  bool _active;
570264243Sdteske public:
571264243Sdteske  JavaThreadSleepState(JavaThread *java_thread) :
572264243Sdteske    JavaThreadStatusChanger(java_thread, java_lang_Thread::SLEEPING) {
573264243Sdteske    if (is_alive()) {
574264243Sdteske      _stat = java_thread->get_thread_stat();
575264243Sdteske      _active = ThreadService::is_thread_monitoring_contention();
576264243Sdteske      _stat->thread_sleep();
577264243Sdteske      if (_active) {
578264243Sdteske        _stat->thread_sleep_begin();
579264243Sdteske      }
580264243Sdteske    } else {
581264243Sdteske      _active = false;
582264243Sdteske    }
583264243Sdteske  }
584264243Sdteske
585264243Sdteske  ~JavaThreadSleepState() {
586264243Sdteske    if (_active) {
587264243Sdteske      _stat->thread_sleep_end();
588264243Sdteske    }
589264243Sdteske  }
590264243Sdteske};
591264243Sdteske
592264243Sdteske#endif // SHARE_VM_SERVICES_THREADSERVICE_HPP
593264243Sdteske