1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/jfr/periodic/sampling/jfrThreadSampler.cpp Mon Aug 12 18:30:40 2019 +0300 1.3 @@ -0,0 +1,635 @@ 1.4 +/* 1.5 + * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "precompiled.hpp" 1.29 +#include "jfr/jfrEvents.hpp" 1.30 +#include "jfr/recorder/jfrRecorder.hpp" 1.31 +#include "jfr/periodic/sampling/jfrCallTrace.hpp" 1.32 +#include "jfr/periodic/sampling/jfrThreadSampler.hpp" 1.33 +#include "jfr/recorder/service/jfrOptionSet.hpp" 1.34 +#include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp" 1.35 +#include "jfr/support/jfrThreadId.hpp" 1.36 +#include "jfr/utilities/jfrTime.hpp" 1.37 +#include "runtime/frame.inline.hpp" 1.38 +#include "runtime/os.hpp" 1.39 +#include "runtime/semaphore.hpp" 1.40 +#include "runtime/thread.inline.hpp" 1.41 + 1.42 +enum JfrSampleType { 1.43 + NO_SAMPLE = 0, 1.44 + JAVA_SAMPLE = 1, 1.45 + NATIVE_SAMPLE = 2 1.46 +}; 1.47 + 1.48 +static bool thread_state_in_java(JavaThread* thread) { 1.49 + assert(thread != NULL, "invariant"); 1.50 + switch(thread->thread_state()) { 1.51 + case _thread_new: 1.52 + case _thread_uninitialized: 1.53 + case _thread_new_trans: 1.54 + case _thread_in_vm_trans: 1.55 + case _thread_blocked_trans: 1.56 + case _thread_in_native_trans: 1.57 + case _thread_blocked: 1.58 + case _thread_in_vm: 1.59 + case _thread_in_native: 1.60 + case _thread_in_Java_trans: 1.61 + break; 1.62 + case _thread_in_Java: 1.63 + return true; 1.64 + default: 1.65 + ShouldNotReachHere(); 1.66 + break; 1.67 + } 1.68 + return false; 1.69 +} 1.70 + 1.71 +static bool thread_state_in_native(JavaThread* thread) { 1.72 + assert(thread != NULL, "invariant"); 1.73 + switch(thread->thread_state()) { 1.74 + case _thread_new: 1.75 + case _thread_uninitialized: 1.76 + case _thread_new_trans: 1.77 + case _thread_blocked_trans: 1.78 + case _thread_blocked: 1.79 + case _thread_in_vm: 1.80 + case _thread_in_vm_trans: 1.81 + case _thread_in_Java_trans: 1.82 + case _thread_in_Java: 1.83 + case _thread_in_native_trans: 1.84 + break; 1.85 + case _thread_in_native: 1.86 + return true; 1.87 + default: 1.88 + ShouldNotReachHere(); 1.89 + break; 1.90 + } 1.91 + return false; 1.92 +} 1.93 + 1.94 +class JfrThreadSampleClosure { 1.95 + public: 1.96 + JfrThreadSampleClosure(EventExecutionSample* events, EventNativeMethodSample* events_native); 1.97 + ~JfrThreadSampleClosure() {} 1.98 + EventExecutionSample* next_event() { return &_events[_added_java++]; } 1.99 + EventNativeMethodSample* next_event_native() { return &_events_native[_added_native++]; } 1.100 + void commit_events(JfrSampleType type); 1.101 + bool do_sample_thread(JavaThread* thread, JfrStackFrame* frames, u4 max_frames, JfrSampleType type); 1.102 + uint java_entries() { return _added_java; } 1.103 + uint native_entries() { return _added_native; } 1.104 + 1.105 + private: 1.106 + bool sample_thread_in_java(JavaThread* thread, JfrStackFrame* frames, u4 max_frames); 1.107 + bool sample_thread_in_native(JavaThread* thread, JfrStackFrame* frames, u4 max_frames); 1.108 + EventExecutionSample* _events; 1.109 + EventNativeMethodSample* _events_native; 1.110 + Thread* _self; 1.111 + uint _added_java; 1.112 + uint _added_native; 1.113 +}; 1.114 + 1.115 +class OSThreadSampler : public os::SuspendedThreadTask { 1.116 + public: 1.117 + OSThreadSampler(JavaThread* thread, 1.118 + JfrThreadSampleClosure& closure, 1.119 + JfrStackFrame *frames, 1.120 + u4 max_frames) : os::SuspendedThreadTask((Thread*)thread), 1.121 + _success(false), 1.122 + _stacktrace(frames, max_frames), 1.123 + _closure(closure), 1.124 + _suspend_time() {} 1.125 + 1.126 + void take_sample(); 1.127 + void do_task(const os::SuspendedThreadTaskContext& context); 1.128 + void protected_task(const os::SuspendedThreadTaskContext& context); 1.129 + bool success() const { return _success; } 1.130 + const JfrStackTrace& stacktrace() const { return _stacktrace; } 1.131 + 1.132 + private: 1.133 + bool _success; 1.134 + JfrStackTrace _stacktrace; 1.135 + JfrThreadSampleClosure& _closure; 1.136 + JfrTicks _suspend_time; 1.137 +}; 1.138 + 1.139 +class OSThreadSamplerCallback : public os::CrashProtectionCallback { 1.140 + public: 1.141 + OSThreadSamplerCallback(OSThreadSampler& sampler, const os::SuspendedThreadTaskContext &context) : 1.142 + _sampler(sampler), _context(context) { 1.143 + } 1.144 + virtual void call() { 1.145 + _sampler.protected_task(_context); 1.146 + } 1.147 + private: 1.148 + OSThreadSampler& _sampler; 1.149 + const os::SuspendedThreadTaskContext& _context; 1.150 +}; 1.151 + 1.152 +void OSThreadSampler::do_task(const os::SuspendedThreadTaskContext& context) { 1.153 +#ifndef ASSERT 1.154 + guarantee(JfrOptionSet::sample_protection(), "Sample Protection should be on in product builds"); 1.155 +#endif 1.156 + assert(_suspend_time.value() == 0, "already timestamped!"); 1.157 + _suspend_time = JfrTicks::now(); 1.158 + 1.159 + if (JfrOptionSet::sample_protection()) { 1.160 + OSThreadSamplerCallback cb(*this, context); 1.161 + os::ThreadCrashProtection crash_protection; 1.162 + if (!crash_protection.call(cb)) { 1.163 + if (true) tty->print_cr("Thread method sampler crashed"); 1.164 + } 1.165 + } else { 1.166 + protected_task(context); 1.167 + } 1.168 +} 1.169 + 1.170 +/* 1.171 +* From this method and down the call tree we attempt to protect against crashes 1.172 +* using a signal handler / __try block. Don't take locks, rely on destructors or 1.173 +* leave memory (in case of signal / exception) in an inconsistent state. */ 1.174 +void OSThreadSampler::protected_task(const os::SuspendedThreadTaskContext& context) { 1.175 + JavaThread* jth = (JavaThread*)context.thread(); 1.176 + // Skip sample if we signaled a thread that moved to other state 1.177 + if (!thread_state_in_java(jth)) { 1.178 + return; 1.179 + } 1.180 + JfrGetCallTrace trace(true, jth); 1.181 + frame topframe; 1.182 + if (trace.get_topframe(context.ucontext(), topframe)) { 1.183 + if (_stacktrace.record_thread(*jth, topframe)) { 1.184 + /* If we managed to get a topframe and a stacktrace, create an event 1.185 + * and put it into our array. We can't call Jfr::_stacktraces.add() 1.186 + * here since it would allocate memory using malloc. Doing so while 1.187 + * the stopped thread is inside malloc would deadlock. */ 1.188 + _success = true; 1.189 + EventExecutionSample *ev = _closure.next_event(); 1.190 + ev->set_starttime(_suspend_time); 1.191 + ev->set_endtime(_suspend_time); // fake to not take an end time 1.192 + ev->set_sampledThread(JFR_THREAD_ID(jth)); 1.193 + ev->set_state(java_lang_Thread::get_thread_status(jth->threadObj())); 1.194 + } 1.195 + } 1.196 +} 1.197 + 1.198 +void OSThreadSampler::take_sample() { 1.199 + run(); 1.200 +} 1.201 + 1.202 +class JfrNativeSamplerCallback : public os::CrashProtectionCallback { 1.203 + public: 1.204 + JfrNativeSamplerCallback(JfrThreadSampleClosure& closure, JavaThread* jt, JfrStackFrame* frames, u4 max_frames) : 1.205 + _closure(closure), _jt(jt), _stacktrace(frames, max_frames), _success(false) { 1.206 + } 1.207 + virtual void call(); 1.208 + bool success() { return _success; } 1.209 + JfrStackTrace& stacktrace() { return _stacktrace; } 1.210 + 1.211 + private: 1.212 + JfrThreadSampleClosure& _closure; 1.213 + JavaThread* _jt; 1.214 + JfrStackTrace _stacktrace; 1.215 + bool _success; 1.216 +}; 1.217 + 1.218 +static void write_native_event(JfrThreadSampleClosure& closure, JavaThread* jt) { 1.219 + EventNativeMethodSample *ev = closure.next_event_native(); 1.220 + ev->set_starttime(JfrTicks::now()); 1.221 + ev->set_sampledThread(JFR_THREAD_ID(jt)); 1.222 + ev->set_state(java_lang_Thread::get_thread_status(jt->threadObj())); 1.223 +} 1.224 + 1.225 +void JfrNativeSamplerCallback::call() { 1.226 + // When a thread is only attach it will be native without a last java frame 1.227 + if (!_jt->has_last_Java_frame()) { 1.228 + return; 1.229 + } 1.230 + 1.231 + frame topframe = _jt->last_frame(); 1.232 + frame first_java_frame; 1.233 + Method* method = NULL; 1.234 + JfrGetCallTrace gct(false, _jt); 1.235 + if (!gct.find_top_frame(topframe, &method, first_java_frame)) { 1.236 + return; 1.237 + } 1.238 + if (method == NULL) { 1.239 + return; 1.240 + } 1.241 + topframe = first_java_frame; 1.242 + _success = _stacktrace.record_thread(*_jt, topframe); 1.243 + if (_success) { 1.244 + write_native_event(_closure, _jt); 1.245 + } 1.246 +} 1.247 + 1.248 +bool JfrThreadSampleClosure::sample_thread_in_java(JavaThread* thread, JfrStackFrame* frames, u4 max_frames) { 1.249 + OSThreadSampler sampler(thread, *this, frames, max_frames); 1.250 + sampler.take_sample(); 1.251 + /* We don't want to allocate any memory using malloc/etc while the thread 1.252 + * is stopped, so everything is stored in stack allocated memory until this 1.253 + * point where the thread has been resumed again, if the sampling was a success 1.254 + * we need to store the stacktrace in the stacktrace repository and update 1.255 + * the event with the id that was returned. */ 1.256 + if (!sampler.success()) { 1.257 + return false; 1.258 + } 1.259 + EventExecutionSample *event = &_events[_added_java - 1]; 1.260 + traceid id = JfrStackTraceRepository::add(sampler.stacktrace()); 1.261 + assert(id != 0, "Stacktrace id should not be 0"); 1.262 + event->set_stackTrace(id); 1.263 + return true; 1.264 +} 1.265 + 1.266 +bool JfrThreadSampleClosure::sample_thread_in_native(JavaThread* thread, JfrStackFrame* frames, u4 max_frames) { 1.267 + JfrNativeSamplerCallback cb(*this, thread, frames, max_frames); 1.268 + if (JfrOptionSet::sample_protection()) { 1.269 + os::ThreadCrashProtection crash_protection; 1.270 + if (!crash_protection.call(cb)) { 1.271 + if (true) tty->print_cr("Thread method sampler crashed for native"); 1.272 + } 1.273 + } else { 1.274 + cb.call(); 1.275 + } 1.276 + if (!cb.success()) { 1.277 + return false; 1.278 + } 1.279 + EventNativeMethodSample *event = &_events_native[_added_native - 1]; 1.280 + traceid id = JfrStackTraceRepository::add(cb.stacktrace()); 1.281 + assert(id != 0, "Stacktrace id should not be 0"); 1.282 + event->set_stackTrace(id); 1.283 + return true; 1.284 +} 1.285 + 1.286 +static const uint MAX_NR_OF_JAVA_SAMPLES = 5; 1.287 +static const uint MAX_NR_OF_NATIVE_SAMPLES = 1; 1.288 + 1.289 +void JfrThreadSampleClosure::commit_events(JfrSampleType type) { 1.290 + if (JAVA_SAMPLE == type) { 1.291 + assert(_added_java <= MAX_NR_OF_JAVA_SAMPLES, "invariant"); 1.292 + for (uint i = 0; i < _added_java; ++i) { 1.293 + _events[i].commit(); 1.294 + } 1.295 + } else { 1.296 + assert(NATIVE_SAMPLE == type, "invariant"); 1.297 + assert(_added_native <= MAX_NR_OF_NATIVE_SAMPLES, "invariant"); 1.298 + for (uint i = 0; i < _added_native; ++i) { 1.299 + _events_native[i].commit(); 1.300 + } 1.301 + } 1.302 +} 1.303 + 1.304 +JfrThreadSampleClosure::JfrThreadSampleClosure(EventExecutionSample* events, EventNativeMethodSample* events_native) : 1.305 + _events(events), 1.306 + _events_native(events_native), 1.307 + _self(Thread::current()), 1.308 + _added_java(0), 1.309 + _added_native(0) { 1.310 +} 1.311 + 1.312 +class JfrThreadSampler : public Thread { 1.313 + friend class JfrThreadSampling; 1.314 + private: 1.315 + Semaphore _sample; 1.316 + Thread* _sampler_thread; 1.317 + JfrStackFrame* const _frames; 1.318 + JavaThread* _last_thread_java; 1.319 + JavaThread* _last_thread_native; 1.320 + size_t _interval_java; 1.321 + size_t _interval_native; 1.322 + int _cur_index; 1.323 + const u4 _max_frames; 1.324 + volatile bool _disenrolled; 1.325 + static Monitor* _transition_block_lock; 1.326 + 1.327 +// JavaThread* next_thread(ThreadsList* t_list, JavaThread* first_sampled, JavaThread* current); 1.328 + void task_stacktrace(JfrSampleType type, JavaThread** last_thread); 1.329 + JfrThreadSampler(size_t interval_java, size_t interval_native, u4 max_frames); 1.330 + ~JfrThreadSampler(); 1.331 + 1.332 + void start_thread(); 1.333 + 1.334 + void enroll(); 1.335 + void disenroll(); 1.336 + void set_java_interval(size_t interval) { _interval_java = interval; }; 1.337 + void set_native_interval(size_t interval) { _interval_native = interval; }; 1.338 + size_t get_java_interval() { return _interval_java; }; 1.339 + size_t get_native_interval() { return _interval_native; }; 1.340 + 1.341 + public: 1.342 + void run(); 1.343 + static Monitor* transition_block() { return _transition_block_lock; } 1.344 + static void on_javathread_suspend(JavaThread* thread); 1.345 +}; 1.346 + 1.347 +Monitor* JfrThreadSampler::_transition_block_lock = new Monitor(Mutex::leaf, "Trace block", true); 1.348 + 1.349 +static void clear_transition_block(JavaThread* jt) { 1.350 +// jt->clear_trace_flag(); 1.351 + JfrThreadLocal* const tl = jt->jfr_thread_local(); 1.352 + if (tl->is_trace_block()) { 1.353 + MutexLockerEx ml(JfrThreadSampler::transition_block(), Mutex::_no_safepoint_check_flag); 1.354 + JfrThreadSampler::transition_block()->notify_all(); 1.355 + } 1.356 +} 1.357 + 1.358 +bool JfrThreadSampleClosure::do_sample_thread(JavaThread* thread, JfrStackFrame* frames, u4 max_frames, JfrSampleType type) { 1.359 + assert(Threads_lock->owned_by_self(), "Holding the thread table lock."); 1.360 + if (thread->is_hidden_from_external_view() || thread->in_deopt_handler()) { 1.361 + return false; 1.362 + } 1.363 + 1.364 + bool ret = false; 1.365 +// thread->set_trace_flag(); 1.366 + if (!UseMembar) { 1.367 + os::serialize_thread_states(); 1.368 + } 1.369 + if (JAVA_SAMPLE == type) { 1.370 + if (thread_state_in_java(thread)) { 1.371 + ret = sample_thread_in_java(thread, frames, max_frames); 1.372 + } 1.373 + } else { 1.374 + assert(NATIVE_SAMPLE == type, "invariant"); 1.375 + if (thread_state_in_native(thread)) { 1.376 + ret = sample_thread_in_native(thread, frames, max_frames); 1.377 + } 1.378 + } 1.379 + clear_transition_block(thread); 1.380 + return ret; 1.381 +} 1.382 + 1.383 +JfrThreadSampler::JfrThreadSampler(size_t interval_java, size_t interval_native, u4 max_frames) : 1.384 + _sample(), 1.385 + _sampler_thread(NULL), 1.386 + _frames(JfrCHeapObj::new_array<JfrStackFrame>(max_frames)), 1.387 + _last_thread_java(NULL), 1.388 + _last_thread_native(NULL), 1.389 + _interval_java(interval_java), 1.390 + _interval_native(interval_native), 1.391 + _cur_index(-1), 1.392 + _max_frames(max_frames), 1.393 + _disenrolled(true) { 1.394 +} 1.395 + 1.396 +JfrThreadSampler::~JfrThreadSampler() { 1.397 + JfrCHeapObj::free(_frames, sizeof(JfrStackFrame) * _max_frames); 1.398 +} 1.399 + 1.400 +void JfrThreadSampler::on_javathread_suspend(JavaThread* thread) { 1.401 + JfrThreadLocal* const tl = thread->jfr_thread_local(); 1.402 + tl->set_trace_block(); 1.403 + { 1.404 +// MutexLockerEx ml(transition_block(), Mutex::_no_safepoint_check_flag); 1.405 +// while (thread->is_trace_suspend()) { 1.406 +// transition_block()->wait(true); 1.407 +// } 1.408 +// tl->clear_trace_block(); 1.409 + } 1.410 +} 1.411 + 1.412 +//JavaThread* JfrThreadSampler::next_thread(ThreadsList* t_list, JavaThread* first_sampled, JavaThread* current) { 1.413 +// assert(t_list != NULL, "invariant"); 1.414 +// assert(Threads_lock->owned_by_self(), "Holding the thread table lock."); 1.415 +// assert(_cur_index >= -1 && (uint)_cur_index + 1 <= t_list->length(), "invariant"); 1.416 +// assert((current == NULL && -1 == _cur_index) || (t_list->find_index_of_JavaThread(current) == _cur_index), "invariant"); 1.417 +// if ((uint)_cur_index + 1 == t_list->length()) { 1.418 +// // wrap 1.419 +// _cur_index = 0; 1.420 +// } else { 1.421 +// _cur_index++; 1.422 +// } 1.423 +// assert(_cur_index >= 0 && (uint)_cur_index < t_list->length(), "invariant"); 1.424 +// JavaThread* const next = t_list->thread_at(_cur_index); 1.425 +// return next != first_sampled ? next : NULL; 1.426 +//} 1.427 + 1.428 +void JfrThreadSampler::start_thread() { 1.429 + // XXX TODO implement sampling 1.430 +// if (os::create_thread(this, os::os_thread)) { 1.431 +// os::start_thread(this); 1.432 +// } else { 1.433 +// if (true) tty->print_cr("Failed to create thread for thread sampling"); 1.434 +// } 1.435 +} 1.436 + 1.437 +void JfrThreadSampler::enroll() { 1.438 + if (_disenrolled) { 1.439 + if (LogJFR) tty->print_cr("Enrolling thread sampler"); 1.440 + _sample.signal(); 1.441 + _disenrolled = false; 1.442 + } 1.443 +} 1.444 + 1.445 +void JfrThreadSampler::disenroll() { 1.446 + if (!_disenrolled) { 1.447 + _sample.wait(); 1.448 + _disenrolled = true; 1.449 + if (LogJFR) tty->print_cr("Disenrolling thread sampler"); 1.450 + } 1.451 +} 1.452 + 1.453 +static jlong get_monotonic_ms() { 1.454 + return os::javaTimeNanos() / 1000000; 1.455 +} 1.456 + 1.457 +void JfrThreadSampler::run() { 1.458 + assert(_sampler_thread == NULL, "invariant"); 1.459 + 1.460 + initialize_thread_local_storage(); 1.461 + record_stack_base_and_size(); 1.462 + 1.463 + _sampler_thread = this; 1.464 + 1.465 + jlong last_java_ms = get_monotonic_ms(); 1.466 + jlong last_native_ms = last_java_ms; 1.467 + while (true) { 1.468 + if (!_sample.trywait()) { 1.469 + // disenrolled 1.470 + _sample.wait(); 1.471 + last_java_ms = get_monotonic_ms(); 1.472 + last_native_ms = last_java_ms; 1.473 + } 1.474 + _sample.signal(); 1.475 + jlong java_interval = _interval_java == 0 ? max_jlong : MAX2<jlong>(_interval_java, 10); 1.476 + jlong native_interval = _interval_native == 0 ? max_jlong : MAX2<jlong>(_interval_native, 10); 1.477 + 1.478 + jlong now_ms = get_monotonic_ms(); 1.479 + 1.480 + jlong next_j = java_interval + last_java_ms - now_ms; 1.481 + jlong next_n = native_interval + last_native_ms - now_ms; 1.482 + 1.483 + jlong sleep_to_next = MIN2<jlong>(next_j, next_n); 1.484 + 1.485 + if (sleep_to_next > 0) { 1.486 + os::naked_short_sleep(sleep_to_next); 1.487 + } 1.488 + 1.489 + if ((next_j - sleep_to_next) <= 0) { 1.490 + task_stacktrace(JAVA_SAMPLE, &_last_thread_java); 1.491 + last_java_ms = get_monotonic_ms(); 1.492 + } 1.493 + if ((next_n - sleep_to_next) <= 0) { 1.494 + task_stacktrace(NATIVE_SAMPLE, &_last_thread_native); 1.495 + last_native_ms = get_monotonic_ms(); 1.496 + } 1.497 + } 1.498 + delete this; 1.499 +} 1.500 + 1.501 + 1.502 +void JfrThreadSampler::task_stacktrace(JfrSampleType type, JavaThread** last_thread) { 1.503 + ResourceMark rm; 1.504 + EventExecutionSample samples[MAX_NR_OF_JAVA_SAMPLES]; 1.505 + EventNativeMethodSample samples_native[MAX_NR_OF_NATIVE_SAMPLES]; 1.506 + JfrThreadSampleClosure sample_task(samples, samples_native); 1.507 + 1.508 + const uint sample_limit = JAVA_SAMPLE == type ? MAX_NR_OF_JAVA_SAMPLES : MAX_NR_OF_NATIVE_SAMPLES; 1.509 + uint num_sample_attempts = 0; 1.510 + JavaThread* start = NULL; 1.511 + 1.512 + { 1.513 + elapsedTimer sample_time; 1.514 + sample_time.start(); 1.515 + { 1.516 +// MonitorLockerEx tlock(Threads_lock, Mutex::_allow_vm_block_flag); 1.517 +// ThreadsListHandle tlh; 1.518 +// // Resolve a sample session relative start position index into the thread list array. 1.519 +// // In cases where the last sampled thread is NULL or not-NULL but stale, find_index() returns -1. 1.520 +// _cur_index = tlh.list()->find_index_of_JavaThread(*last_thread); 1.521 +// JavaThread* current = _cur_index != -1 ? *last_thread : NULL; 1.522 +// 1.523 +// while (num_sample_attempts < sample_limit) { 1.524 +// current = next_thread(tlh.list(), start, current); 1.525 +// if (current == NULL) { 1.526 +// break; 1.527 +// } 1.528 +// if (start == NULL) { 1.529 +// start = current; // remember the thread where we started to attempt sampling 1.530 +// } 1.531 +// if (current->is_Compiler_thread()) { 1.532 +// continue; 1.533 +// } 1.534 +// sample_task.do_sample_thread(current, _frames, _max_frames, type); 1.535 +// num_sample_attempts++; 1.536 +// } 1.537 +// *last_thread = current; // remember the thread we last attempted to sample 1.538 + } 1.539 + sample_time.stop(); 1.540 + if (LogJFR && Verbose) tty->print_cr("JFR thread sampling done in %3.7f secs with %d java %d native samples", 1.541 + sample_time.seconds(), sample_task.java_entries(), sample_task.native_entries()); 1.542 + } 1.543 + if (num_sample_attempts > 0) { 1.544 + sample_task.commit_events(type); 1.545 + } 1.546 +} 1.547 + 1.548 +static JfrThreadSampling* _instance = NULL; 1.549 + 1.550 +JfrThreadSampling& JfrThreadSampling::instance() { 1.551 + return *_instance; 1.552 +} 1.553 + 1.554 +JfrThreadSampling* JfrThreadSampling::create() { 1.555 + assert(_instance == NULL, "invariant"); 1.556 + _instance = new JfrThreadSampling(); 1.557 + return _instance; 1.558 +} 1.559 + 1.560 +void JfrThreadSampling::destroy() { 1.561 + if (_instance != NULL) { 1.562 + delete _instance; 1.563 + _instance = NULL; 1.564 + } 1.565 +} 1.566 + 1.567 +JfrThreadSampling::JfrThreadSampling() : _sampler(NULL) {} 1.568 + 1.569 +JfrThreadSampling::~JfrThreadSampling() { 1.570 + if (_sampler != NULL) { 1.571 + _sampler->disenroll(); 1.572 + } 1.573 +} 1.574 + 1.575 +static void log(size_t interval_java, size_t interval_native) { 1.576 + if (LogJFR) tty->print_cr("Updated thread sampler for java: " SIZE_FORMAT " ms, native " SIZE_FORMAT " ms", interval_java, interval_native); 1.577 +} 1.578 + 1.579 +void JfrThreadSampling::start_sampler(size_t interval_java, size_t interval_native) { 1.580 + assert(_sampler == NULL, "invariant"); 1.581 + if (LogJFR) tty->print_cr("Enrolling thread sampler"); 1.582 + _sampler = new JfrThreadSampler(interval_java, interval_native, JfrOptionSet::stackdepth()); 1.583 + _sampler->start_thread(); 1.584 + _sampler->enroll(); 1.585 +} 1.586 + 1.587 +void JfrThreadSampling::set_sampling_interval(bool java_interval, size_t period) { 1.588 + size_t interval_java = 0; 1.589 + size_t interval_native = 0; 1.590 + if (_sampler != NULL) { 1.591 + interval_java = _sampler->get_java_interval(); 1.592 + interval_native = _sampler->get_native_interval(); 1.593 + } 1.594 + if (java_interval) { 1.595 + interval_java = period; 1.596 + } else { 1.597 + interval_native = period; 1.598 + } 1.599 + if (interval_java > 0 || interval_native > 0) { 1.600 + if (_sampler == NULL) { 1.601 + if (LogJFR) tty->print_cr("Creating thread sampler for java:%zu ms, native %zu ms", interval_java, interval_native); 1.602 + start_sampler(interval_java, interval_native); 1.603 + } else { 1.604 + _sampler->set_java_interval(interval_java); 1.605 + _sampler->set_native_interval(interval_native); 1.606 + _sampler->enroll(); 1.607 + } 1.608 + assert(_sampler != NULL, "invariant"); 1.609 + log(interval_java, interval_native); 1.610 + } else if (_sampler != NULL) { 1.611 + _sampler->disenroll(); 1.612 + } 1.613 +} 1.614 + 1.615 +void JfrThreadSampling::set_java_sample_interval(size_t period) { 1.616 + if (_instance == NULL && 0 == period) { 1.617 + return; 1.618 + } 1.619 + instance().set_sampling_interval(true, period); 1.620 +} 1.621 + 1.622 +void JfrThreadSampling::set_native_sample_interval(size_t period) { 1.623 + if (_instance == NULL && 0 == period) { 1.624 + return; 1.625 + } 1.626 + instance().set_sampling_interval(false, period); 1.627 +} 1.628 + 1.629 +void JfrThreadSampling::on_javathread_suspend(JavaThread* thread) { 1.630 + JfrThreadSampler::on_javathread_suspend(thread); 1.631 +} 1.632 + 1.633 +Thread* JfrThreadSampling::sampler_thread() { 1.634 + if (_instance == NULL) { 1.635 + return NULL; 1.636 + } 1.637 + return _instance->_sampler != NULL ? _instance->_sampler->_sampler_thread : NULL; 1.638 +}