40 #include "runtime/vframe.hpp"
41 #include "runtime/vmThread.hpp"
42 #include "runtime/vm_operations.hpp"
43 #include "services/threadService.hpp"
44
45 // TODO: we need to define a naming convention for perf counters
46 // to distinguish counters for:
47 // - standard JSR174 use
48 // - Hotspot extension (public and committed)
49 // - Hotspot extension (private/internal and uncommitted)
50
51 // Default is disabled.
52 bool ThreadService::_thread_monitoring_contention_enabled = false;
53 bool ThreadService::_thread_cpu_time_enabled = false;
54 bool ThreadService::_thread_allocated_memory_enabled = false;
55
56 PerfCounter* ThreadService::_total_threads_count = NULL;
57 PerfVariable* ThreadService::_live_threads_count = NULL;
58 PerfVariable* ThreadService::_peak_threads_count = NULL;
59 PerfVariable* ThreadService::_daemon_threads_count = NULL;
60 volatile int ThreadService::_exiting_threads_count = 0;
61 volatile int ThreadService::_exiting_daemon_threads_count = 0;
62
63 ThreadDumpResult* ThreadService::_threaddump_list = NULL;
64
65 static const int INITIAL_ARRAY_SIZE = 10;
66
67 void ThreadService::init() {
68 EXCEPTION_MARK;
69
70 // These counters are for java.lang.management API support.
71 // They are created even if -XX:-UsePerfData is set and in
72 // that case, they will be allocated on C heap.
73
74 _total_threads_count =
75 PerfDataManager::create_counter(JAVA_THREADS, "started",
76 PerfData::U_Events, CHECK);
77
78 _live_threads_count =
79 PerfDataManager::create_variable(JAVA_THREADS, "live",
80 PerfData::U_None, CHECK);
81
85
86 _daemon_threads_count =
87 PerfDataManager::create_variable(JAVA_THREADS, "daemon",
88 PerfData::U_None, CHECK);
89
90 if (os::is_thread_cpu_time_supported()) {
91 _thread_cpu_time_enabled = true;
92 }
93
94 _thread_allocated_memory_enabled = true; // Always on, so enable it
95 }
96
97 void ThreadService::reset_peak_thread_count() {
98 // Acquire the lock to update the peak thread count
99 // to synchronize with thread addition and removal.
100 MutexLockerEx mu(Threads_lock);
101 _peak_threads_count->set_value(get_live_thread_count());
102 }
103
104 void ThreadService::add_thread(JavaThread* thread, bool daemon) {
105 // Do not count VM internal or JVMTI agent threads
106 if (thread->is_hidden_from_external_view() ||
107 thread->is_jvmti_agent_thread()) {
108 return;
109 }
110
111 _total_threads_count->inc();
112 _live_threads_count->inc();
113
114 if (_live_threads_count->get_value() > _peak_threads_count->get_value()) {
115 _peak_threads_count->set_value(_live_threads_count->get_value());
116 }
117
118 if (daemon) {
119 _daemon_threads_count->inc();
120 }
121 }
122
123 void ThreadService::remove_thread(JavaThread* thread, bool daemon) {
124 Atomic::dec(&_exiting_threads_count);
125 if (daemon) {
126 Atomic::dec(&_exiting_daemon_threads_count);
127 }
128
129 if (thread->is_hidden_from_external_view() ||
130 thread->is_jvmti_agent_thread()) {
131 return;
132 }
133
134 _live_threads_count->set_value(_live_threads_count->get_value() - 1);
135 if (daemon) {
136 _daemon_threads_count->set_value(_daemon_threads_count->get_value() - 1);
137 }
138 }
139
140 void ThreadService::current_thread_exiting(JavaThread* jt) {
141 assert(jt == JavaThread::current(), "Called by current thread");
142 Atomic::inc(&_exiting_threads_count);
143
144 oop threadObj = jt->threadObj();
145 if (threadObj != NULL && java_lang_Thread::is_daemon(threadObj)) {
146 Atomic::inc(&_exiting_daemon_threads_count);
147 }
148 }
149
150 // FIXME: JVMTI should call this function
151 Handle ThreadService::get_current_contended_monitor(JavaThread* thread) {
152 assert(thread != NULL, "should be non-NULL");
153 debug_only(Thread::check_for_dangling_thread_pointer(thread);)
154
155 ObjectMonitor *wait_obj = thread->current_waiting_monitor();
156
157 oop obj = NULL;
158 if (wait_obj != NULL) {
159 // thread is doing an Object.wait() call
160 obj = (oop) wait_obj->object();
161 assert(obj != NULL, "Object.wait() should have an object");
162 } else {
163 ObjectMonitor *enter_obj = thread->current_pending_monitor();
164 if (enter_obj != NULL) {
165 // thread is trying to enter() or raw_enter() an ObjectMonitor.
166 obj = (oop) enter_obj->object();
167 }
|
40 #include "runtime/vframe.hpp"
41 #include "runtime/vmThread.hpp"
42 #include "runtime/vm_operations.hpp"
43 #include "services/threadService.hpp"
44
45 // TODO: we need to define a naming convention for perf counters
46 // to distinguish counters for:
47 // - standard JSR174 use
48 // - Hotspot extension (public and committed)
49 // - Hotspot extension (private/internal and uncommitted)
50
51 // Default is disabled.
52 bool ThreadService::_thread_monitoring_contention_enabled = false;
53 bool ThreadService::_thread_cpu_time_enabled = false;
54 bool ThreadService::_thread_allocated_memory_enabled = false;
55
56 PerfCounter* ThreadService::_total_threads_count = NULL;
57 PerfVariable* ThreadService::_live_threads_count = NULL;
58 PerfVariable* ThreadService::_peak_threads_count = NULL;
59 PerfVariable* ThreadService::_daemon_threads_count = NULL;
60 volatile int ThreadService::_atomic_threads_count = 0;
61 volatile int ThreadService::_atomic_daemon_threads_count = 0;
62
63 ThreadDumpResult* ThreadService::_threaddump_list = NULL;
64
65 static const int INITIAL_ARRAY_SIZE = 10;
66
67 void ThreadService::init() {
68 EXCEPTION_MARK;
69
70 // These counters are for java.lang.management API support.
71 // They are created even if -XX:-UsePerfData is set and in
72 // that case, they will be allocated on C heap.
73
74 _total_threads_count =
75 PerfDataManager::create_counter(JAVA_THREADS, "started",
76 PerfData::U_Events, CHECK);
77
78 _live_threads_count =
79 PerfDataManager::create_variable(JAVA_THREADS, "live",
80 PerfData::U_None, CHECK);
81
85
86 _daemon_threads_count =
87 PerfDataManager::create_variable(JAVA_THREADS, "daemon",
88 PerfData::U_None, CHECK);
89
90 if (os::is_thread_cpu_time_supported()) {
91 _thread_cpu_time_enabled = true;
92 }
93
94 _thread_allocated_memory_enabled = true; // Always on, so enable it
95 }
96
97 void ThreadService::reset_peak_thread_count() {
98 // Acquire the lock to update the peak thread count
99 // to synchronize with thread addition and removal.
100 MutexLockerEx mu(Threads_lock);
101 _peak_threads_count->set_value(get_live_thread_count());
102 }
103
104 void ThreadService::add_thread(JavaThread* thread, bool daemon) {
105 assert(Threads_lock->owned_by_self(), "must have threads lock");
106
107 // Do not count VM internal or JVMTI agent threads
108 if (thread->is_hidden_from_external_view() ||
109 thread->is_jvmti_agent_thread()) {
110 return;
111 }
112
113 _total_threads_count->inc();
114 _live_threads_count->inc();
115 Atomic::inc(&_atomic_threads_count);
116
117 if (_atomic_threads_count > _peak_threads_count->get_value()) {
118 _peak_threads_count->set_value(_atomic_threads_count);
119 }
120
121 if (daemon) {
122 _daemon_threads_count->inc();
123 Atomic::inc(&_atomic_daemon_threads_count);
124 }
125 }
126
127 void ThreadService::decrement_thread_counts(JavaThread* jt) {
128 Atomic::dec(&_atomic_threads_count);
129
130 oop threadObj = jt->threadObj();
131 if (threadObj != NULL && java_lang_Thread::is_daemon(threadObj)) {
132 Atomic::dec(&_atomic_daemon_threads_count);
133 }
134 }
135
136 void ThreadService::remove_thread(JavaThread* thread, bool daemon) {
137 assert(Threads_lock->owned_by_self(), "must have threads lock");
138 if (thread->is_hidden_from_external_view() ||
139 thread->is_jvmti_agent_thread()) {
140 return;
141 }
142
143 assert(!thread->is_terminated(), "must not be terminated");
144 if (!thread->is_exiting()) {
145 // JavaThread::exit() skipped calling current_thread_exiting()
146 decrement_thread_counts(thread);
147 }
148
149 int daemon_count = _atomic_daemon_threads_count;
150 int count = _atomic_threads_count;
151
152 // Counts are incremented at the same time, but atomic counts are
153 // decremented earlier than perf counts.
154 assert(_live_threads_count->get_value() > count,
155 "thread count mismatch %d : %d",
156 (int)_live_threads_count->get_value(), count);
157
158 _live_threads_count->dec(1);
159 if (daemon) {
160 assert(_daemon_threads_count->get_value() > daemon_count,
161 "thread count mismatch %d : %d",
162 (int)_daemon_threads_count->get_value(), daemon_count);
163
164 _daemon_threads_count->dec(1);
165 }
166
167 // Counts are incremented at the same time, but atomic counts are
168 // decremented earlier than perf counts.
169 assert(_daemon_threads_count->get_value() >= daemon_count,
170 "thread count mismatch %d : %d",
171 (int)_daemon_threads_count->get_value(), daemon_count);
172 assert(_live_threads_count->get_value() >= count,
173 "thread count mismatch %d : %d",
174 (int)_live_threads_count->get_value(), count);
175 assert(_live_threads_count->get_value() > 0 ||
176 (_live_threads_count->get_value() == 0 && count == 0 &&
177 _daemon_threads_count->get_value() == 0 && daemon_count == 0),
178 "thread counts should reach 0 at the same time, live %d,%d daemon %d,%d",
179 (int)_live_threads_count->get_value(), count,
180 (int)_daemon_threads_count->get_value(), daemon_count);
181 assert(_daemon_threads_count->get_value() > 0 ||
182 (_daemon_threads_count->get_value() == 0 && daemon_count == 0),
183 "thread counts should reach 0 at the same time, daemon %d,%d",
184 (int)_daemon_threads_count->get_value(), daemon_count);
185 }
186
187 void ThreadService::current_thread_exiting(JavaThread* jt) {
188 if (jt->is_hidden_from_external_view() ||
189 jt->is_jvmti_agent_thread()) {
190 return;
191 }
192
193 assert(jt == JavaThread::current(), "Called by current thread");
194 assert(!jt->is_terminated() && jt->is_exiting(), "must be exiting");
195
196 decrement_thread_counts(jt);
197 }
198
199 // FIXME: JVMTI should call this function
200 Handle ThreadService::get_current_contended_monitor(JavaThread* thread) {
201 assert(thread != NULL, "should be non-NULL");
202 debug_only(Thread::check_for_dangling_thread_pointer(thread);)
203
204 ObjectMonitor *wait_obj = thread->current_waiting_monitor();
205
206 oop obj = NULL;
207 if (wait_obj != NULL) {
208 // thread is doing an Object.wait() call
209 obj = (oop) wait_obj->object();
210 assert(obj != NULL, "Object.wait() should have an object");
211 } else {
212 ObjectMonitor *enter_obj = thread->current_pending_monitor();
213 if (enter_obj != NULL) {
214 // thread is trying to enter() or raw_enter() an ObjectMonitor.
215 obj = (oop) enter_obj->object();
216 }
|