1 /* 2 * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. 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 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "jfr/jfrEvents.hpp" 27 #include "jfr/recorder/jfrRecorder.hpp" 28 #include "jfr/periodic/sampling/jfrCallTrace.hpp" 29 #include "jfr/periodic/sampling/jfrThreadSampler.hpp" 30 #include "jfr/recorder/service/jfrOptionSet.hpp" 31 #include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp" 32 #include "jfr/support/jfrThreadId.hpp" 33 #include "jfr/utilities/jfrTime.hpp" 34 #include "runtime/frame.inline.hpp" 35 #include "runtime/os.hpp" 36 #include "runtime/semaphore.hpp" 37 #include "runtime/thread.inline.hpp" 38 39 enum JfrSampleType { 40 NO_SAMPLE = 0, 41 JAVA_SAMPLE = 1, 42 NATIVE_SAMPLE = 2 43 }; 44 45 static bool thread_state_in_java(JavaThread* thread) { 46 assert(thread != NULL, "invariant"); 47 switch(thread->thread_state()) { 48 case _thread_new: 49 case _thread_uninitialized: 50 case _thread_new_trans: 51 case _thread_in_vm_trans: 52 case _thread_blocked_trans: 53 case _thread_in_native_trans: 54 case _thread_blocked: 55 case _thread_in_vm: 56 case _thread_in_native: 57 case _thread_in_Java_trans: 58 break; 59 case _thread_in_Java: 60 return true; 61 default: 62 ShouldNotReachHere(); 63 break; 64 } 65 return false; 66 } 67 68 static bool thread_state_in_native(JavaThread* thread) { 69 assert(thread != NULL, "invariant"); 70 switch(thread->thread_state()) { 71 case _thread_new: 72 case _thread_uninitialized: 73 case _thread_new_trans: 74 case _thread_blocked_trans: 75 case _thread_blocked: 76 case _thread_in_vm: 77 case _thread_in_vm_trans: 78 case _thread_in_Java_trans: 79 case _thread_in_Java: 80 case _thread_in_native_trans: 81 break; 82 case _thread_in_native: 83 return true; 84 default: 85 ShouldNotReachHere(); 86 break; 87 } 88 return false; 89 } 90 91 class JfrThreadSampleClosure { 92 public: 93 JfrThreadSampleClosure(EventExecutionSample* events, EventNativeMethodSample* events_native); 94 ~JfrThreadSampleClosure() {} 95 EventExecutionSample* next_event() { return &_events[_added_java++]; } 96 EventNativeMethodSample* next_event_native() { return &_events_native[_added_native++]; } 97 void commit_events(JfrSampleType type); 98 bool do_sample_thread(JavaThread* thread, JfrStackFrame* frames, u4 max_frames, JfrSampleType type); 99 uint java_entries() { return _added_java; } 100 uint native_entries() { return _added_native; } 101 102 private: 103 bool sample_thread_in_java(JavaThread* thread, JfrStackFrame* frames, u4 max_frames); 104 bool sample_thread_in_native(JavaThread* thread, JfrStackFrame* frames, u4 max_frames); 105 EventExecutionSample* _events; 106 EventNativeMethodSample* _events_native; 107 Thread* _self; 108 uint _added_java; 109 uint _added_native; 110 }; 111 112 class OSThreadSampler : public os::SuspendedThreadTask { 113 public: 114 OSThreadSampler(JavaThread* thread, 115 JfrThreadSampleClosure& closure, 116 JfrStackFrame *frames, 117 u4 max_frames) : os::SuspendedThreadTask((Thread*)thread), 118 _success(false), 119 _stacktrace(frames, max_frames), 120 _closure(closure), 121 _suspend_time() {} 122 123 void take_sample(); 124 void do_task(const os::SuspendedThreadTaskContext& context); 125 void protected_task(const os::SuspendedThreadTaskContext& context); 126 bool success() const { return _success; } 127 const JfrStackTrace& stacktrace() const { return _stacktrace; } 128 129 private: 130 bool _success; 131 JfrStackTrace _stacktrace; 132 JfrThreadSampleClosure& _closure; 133 JfrTicks _suspend_time; 134 }; 135 136 class OSThreadSamplerCallback : public os::CrashProtectionCallback { 137 public: 138 OSThreadSamplerCallback(OSThreadSampler& sampler, const os::SuspendedThreadTaskContext &context) : 139 _sampler(sampler), _context(context) { 140 } 141 virtual void call() { 142 _sampler.protected_task(_context); 143 } 144 private: 145 OSThreadSampler& _sampler; 146 const os::SuspendedThreadTaskContext& _context; 147 }; 148 149 void OSThreadSampler::do_task(const os::SuspendedThreadTaskContext& context) { 150 #ifndef ASSERT 151 guarantee(JfrOptionSet::sample_protection(), "Sample Protection should be on in product builds"); 152 #endif 153 assert(_suspend_time.value() == 0, "already timestamped!"); 154 _suspend_time = JfrTicks::now(); 155 156 if (JfrOptionSet::sample_protection()) { 157 OSThreadSamplerCallback cb(*this, context); 158 os::WatcherThreadCrashProtection crash_protection; 159 if (!crash_protection.call(cb)) { 160 if (true) tty->print_cr("Thread method sampler crashed"); 161 } 162 } else { 163 protected_task(context); 164 } 165 } 166 167 /* 168 * From this method and down the call tree we attempt to protect against crashes 169 * using a signal handler / __try block. Don't take locks, rely on destructors or 170 * leave memory (in case of signal / exception) in an inconsistent state. */ 171 void OSThreadSampler::protected_task(const os::SuspendedThreadTaskContext& context) { 172 JavaThread* jth = (JavaThread*)context.thread(); 173 // Skip sample if we signaled a thread that moved to other state 174 if (!thread_state_in_java(jth)) { 175 return; 176 } 177 JfrGetCallTrace trace(true, jth); 178 frame topframe; 179 if (trace.get_topframe(context.ucontext(), topframe)) { 180 if (_stacktrace.record_thread(*jth, topframe)) { 181 /* If we managed to get a topframe and a stacktrace, create an event 182 * and put it into our array. We can't call Jfr::_stacktraces.add() 183 * here since it would allocate memory using malloc. Doing so while 184 * the stopped thread is inside malloc would deadlock. */ 185 _success = true; 186 EventExecutionSample *ev = _closure.next_event(); 187 ev->set_starttime(_suspend_time); 188 ev->set_endtime(_suspend_time); // fake to not take an end time 189 ev->set_sampledThread(JFR_THREAD_ID(jth)); 190 ev->set_state(java_lang_Thread::get_thread_status(jth->threadObj())); 191 } 192 } 193 } 194 195 void OSThreadSampler::take_sample() { 196 run(); 197 } 198 199 class JfrNativeSamplerCallback : public os::CrashProtectionCallback { 200 public: 201 JfrNativeSamplerCallback(JfrThreadSampleClosure& closure, JavaThread* jt, JfrStackFrame* frames, u4 max_frames) : 202 _closure(closure), _jt(jt), _stacktrace(frames, max_frames), _success(false) { 203 } 204 virtual void call(); 205 bool success() { return _success; } 206 JfrStackTrace& stacktrace() { return _stacktrace; } 207 208 private: 209 JfrThreadSampleClosure& _closure; 210 JavaThread* _jt; 211 JfrStackTrace _stacktrace; 212 bool _success; 213 }; 214 215 static void write_native_event(JfrThreadSampleClosure& closure, JavaThread* jt) { 216 EventNativeMethodSample *ev = closure.next_event_native(); 217 ev->set_starttime(JfrTicks::now()); 218 ev->set_sampledThread(JFR_THREAD_ID(jt)); 219 ev->set_state(java_lang_Thread::get_thread_status(jt->threadObj())); 220 } 221 222 void JfrNativeSamplerCallback::call() { 223 // When a thread is only attach it will be native without a last java frame 224 if (!_jt->has_last_Java_frame()) { 225 return; 226 } 227 228 frame topframe = _jt->last_frame(); 229 frame first_java_frame; 230 Method* method = NULL; 231 JfrGetCallTrace gct(false, _jt); 232 if (!gct.find_top_frame(topframe, &method, first_java_frame)) { 233 return; 234 } 235 if (method == NULL) { 236 return; 237 } 238 topframe = first_java_frame; 239 _success = _stacktrace.record_thread(*_jt, topframe); 240 if (_success) { 241 write_native_event(_closure, _jt); 242 } 243 } 244 245 bool JfrThreadSampleClosure::sample_thread_in_java(JavaThread* thread, JfrStackFrame* frames, u4 max_frames) { 246 OSThreadSampler sampler(thread, *this, frames, max_frames); 247 sampler.take_sample(); 248 /* We don't want to allocate any memory using malloc/etc while the thread 249 * is stopped, so everything is stored in stack allocated memory until this 250 * point where the thread has been resumed again, if the sampling was a success 251 * we need to store the stacktrace in the stacktrace repository and update 252 * the event with the id that was returned. */ 253 if (!sampler.success()) { 254 return false; 255 } 256 EventExecutionSample *event = &_events[_added_java - 1]; 257 traceid id = JfrStackTraceRepository::add(sampler.stacktrace()); 258 assert(id != 0, "Stacktrace id should not be 0"); 259 event->set_stackTrace(id); 260 return true; 261 } 262 263 bool JfrThreadSampleClosure::sample_thread_in_native(JavaThread* thread, JfrStackFrame* frames, u4 max_frames) { 264 JfrNativeSamplerCallback cb(*this, thread, frames, max_frames); 265 if (JfrOptionSet::sample_protection()) { 266 os::WatcherThreadCrashProtection crash_protection; 267 if (!crash_protection.call(cb)) { 268 if (true) tty->print_cr("Thread method sampler crashed for native"); 269 } 270 } else { 271 cb.call(); 272 } 273 if (!cb.success()) { 274 return false; 275 } 276 EventNativeMethodSample *event = &_events_native[_added_native - 1]; 277 traceid id = JfrStackTraceRepository::add(cb.stacktrace()); 278 assert(id != 0, "Stacktrace id should not be 0"); 279 event->set_stackTrace(id); 280 return true; 281 } 282 283 static const uint MAX_NR_OF_JAVA_SAMPLES = 5; 284 static const uint MAX_NR_OF_NATIVE_SAMPLES = 1; 285 286 void JfrThreadSampleClosure::commit_events(JfrSampleType type) { 287 if (JAVA_SAMPLE == type) { 288 assert(_added_java <= MAX_NR_OF_JAVA_SAMPLES, "invariant"); 289 for (uint i = 0; i < _added_java; ++i) { 290 _events[i].commit(); 291 } 292 } else { 293 assert(NATIVE_SAMPLE == type, "invariant"); 294 assert(_added_native <= MAX_NR_OF_NATIVE_SAMPLES, "invariant"); 295 for (uint i = 0; i < _added_native; ++i) { 296 _events_native[i].commit(); 297 } 298 } 299 } 300 301 JfrThreadSampleClosure::JfrThreadSampleClosure(EventExecutionSample* events, EventNativeMethodSample* events_native) : 302 _events(events), 303 _events_native(events_native), 304 _self(Thread::current()), 305 _added_java(0), 306 _added_native(0) { 307 } 308 309 class JfrThreadSampler : public Thread { 310 friend class JfrThreadSampling; 311 private: 312 Semaphore _sample; 313 Thread* _sampler_thread; 314 JfrStackFrame* const _frames; 315 JavaThread* _last_thread_java; 316 JavaThread* _last_thread_native; 317 size_t _interval_java; 318 size_t _interval_native; 319 int _cur_index; 320 const u4 _max_frames; 321 volatile bool _disenrolled; 322 static Monitor* _transition_block_lock; 323 324 int find_index_of_JavaThread(JavaThread** t_list, uint length, JavaThread *target); 325 JavaThread* next_thread(JavaThread** t_list, uint length, JavaThread* first_sampled, JavaThread* current); 326 void task_stacktrace(JfrSampleType type, JavaThread** last_thread); 327 JfrThreadSampler(size_t interval_java, size_t interval_native, u4 max_frames); 328 ~JfrThreadSampler(); 329 330 void start_thread(); 331 332 void enroll(); 333 void disenroll(); 334 void set_java_interval(size_t interval) { _interval_java = interval; }; 335 void set_native_interval(size_t interval) { _interval_native = interval; }; 336 size_t get_java_interval() { return _interval_java; }; 337 size_t get_native_interval() { return _interval_native; }; 338 339 public: 340 void run(); 341 static Monitor* transition_block() { return _transition_block_lock; } 342 static void on_javathread_suspend(JavaThread* thread); 343 }; 344 345 Monitor* JfrThreadSampler::_transition_block_lock = new Monitor(Mutex::leaf, "Trace block", true); 346 347 static void clear_transition_block(JavaThread* jt) { 348 jt->clear_trace_flag(); 349 JfrThreadLocal* const tl = jt->jfr_thread_local(); 350 if (tl->is_trace_block()) { 351 MutexLockerEx ml(JfrThreadSampler::transition_block(), Mutex::_no_safepoint_check_flag); 352 JfrThreadSampler::transition_block()->notify_all(); 353 } 354 } 355 356 bool JfrThreadSampleClosure::do_sample_thread(JavaThread* thread, JfrStackFrame* frames, u4 max_frames, JfrSampleType type) { 357 assert(Threads_lock->owned_by_self(), "Holding the thread table lock."); 358 if (thread->is_hidden_from_external_view() || thread->in_deopt_handler()) { 359 return false; 360 } 361 362 bool ret = false; 363 thread->set_trace_flag(); 364 if (!UseMembar) { 365 os::serialize_thread_states(); 366 } 367 if (JAVA_SAMPLE == type) { 368 if (thread_state_in_java(thread)) { 369 ret = sample_thread_in_java(thread, frames, max_frames); 370 } 371 } else { 372 assert(NATIVE_SAMPLE == type, "invariant"); 373 if (thread_state_in_native(thread)) { 374 ret = sample_thread_in_native(thread, frames, max_frames); 375 } 376 } 377 clear_transition_block(thread); 378 return ret; 379 } 380 381 JfrThreadSampler::JfrThreadSampler(size_t interval_java, size_t interval_native, u4 max_frames) : 382 _sample(), 383 _sampler_thread(NULL), 384 _frames(JfrCHeapObj::new_array<JfrStackFrame>(max_frames)), 385 _last_thread_java(NULL), 386 _last_thread_native(NULL), 387 _interval_java(interval_java), 388 _interval_native(interval_native), 389 _cur_index(-1), 390 _max_frames(max_frames), 391 _disenrolled(true) { 392 } 393 394 JfrThreadSampler::~JfrThreadSampler() { 395 JfrCHeapObj::free(_frames, sizeof(JfrStackFrame) * _max_frames); 396 } 397 398 void JfrThreadSampler::on_javathread_suspend(JavaThread* thread) { 399 JfrThreadLocal* const tl = thread->jfr_thread_local(); 400 tl->set_trace_block(); 401 { 402 MutexLockerEx ml(transition_block(), Mutex::_no_safepoint_check_flag); 403 while (thread->is_trace_suspend()) { 404 transition_block()->wait(true); 405 } 406 tl->clear_trace_block(); 407 } 408 } 409 410 int JfrThreadSampler::find_index_of_JavaThread(JavaThread** t_list, uint length, JavaThread *target) { 411 assert(Threads_lock->owned_by_self(), "Holding the thread table lock."); 412 if (target == NULL) { 413 return -1; 414 } 415 for (uint i = 0; i < length; i++) { 416 if (target == t_list[i]) { 417 return (int)i; 418 } 419 } 420 return -1; 421 } 422 423 JavaThread* JfrThreadSampler::next_thread(JavaThread** t_list, uint length, JavaThread* first_sampled, JavaThread* current) { 424 assert(Threads_lock->owned_by_self(), "Holding the thread table lock."); 425 if (current == NULL) { 426 _cur_index = 0; 427 return t_list[_cur_index]; 428 } 429 430 if (_cur_index == -1 || t_list[_cur_index] != current) { 431 // 'current' is not at '_cur_index' so find it: 432 _cur_index = find_index_of_JavaThread(t_list, length, current); 433 assert(_cur_index != -1, "current JavaThread should be findable."); 434 } 435 _cur_index++; 436 437 JavaThread* next = NULL; 438 // wrap 439 if ((uint)_cur_index >= length) { 440 _cur_index = 0; 441 } 442 next = t_list[_cur_index]; 443 444 // sample wrap 445 if (next == first_sampled) { 446 return NULL; 447 } 448 return next; 449 } 450 451 void JfrThreadSampler::start_thread() { 452 if (os::create_thread(this, os::os_thread)) { 453 os::start_thread(this); 454 } else { 455 tty->print_cr("Failed to create thread for thread sampling"); 456 } 457 } 458 459 void JfrThreadSampler::enroll() { 460 if (_disenrolled) { 461 if (LogJFR) tty->print_cr("Enrolling thread sampler"); 462 _sample.signal(); 463 _disenrolled = false; 464 } 465 } 466 467 void JfrThreadSampler::disenroll() { 468 if (!_disenrolled) { 469 _sample.wait(); 470 _disenrolled = true; 471 if (LogJFR) tty->print_cr("Disenrolling thread sampler"); 472 } 473 } 474 475 static jlong get_monotonic_ms() { 476 return os::javaTimeNanos() / 1000000; 477 } 478 479 void JfrThreadSampler::run() { 480 assert(_sampler_thread == NULL, "invariant"); 481 482 record_stack_base_and_size(); 483 484 _sampler_thread = this; 485 486 jlong last_java_ms = get_monotonic_ms(); 487 jlong last_native_ms = last_java_ms; 488 while (true) { 489 if (!_sample.trywait()) { 490 // disenrolled 491 _sample.wait(); 492 last_java_ms = get_monotonic_ms(); 493 last_native_ms = last_java_ms; 494 } 495 _sample.signal(); 496 jlong java_interval = _interval_java == 0 ? max_jlong : MAX2<jlong>(_interval_java, 10); 497 jlong native_interval = _interval_native == 0 ? max_jlong : MAX2<jlong>(_interval_native, 10); 498 499 jlong now_ms = get_monotonic_ms(); 500 501 jlong next_j = java_interval + last_java_ms - now_ms; 502 jlong next_n = native_interval + last_native_ms - now_ms; 503 504 jlong sleep_to_next = MIN2<jlong>(next_j, next_n); 505 506 if (sleep_to_next > 0) { 507 os::naked_short_sleep(sleep_to_next); 508 } 509 510 if ((next_j - sleep_to_next) <= 0) { 511 task_stacktrace(JAVA_SAMPLE, &_last_thread_java); 512 last_java_ms = get_monotonic_ms(); 513 } 514 if ((next_n - sleep_to_next) <= 0) { 515 task_stacktrace(NATIVE_SAMPLE, &_last_thread_native); 516 last_native_ms = get_monotonic_ms(); 517 } 518 } 519 delete this; 520 } 521 522 523 void JfrThreadSampler::task_stacktrace(JfrSampleType type, JavaThread** last_thread) { 524 ResourceMark rm; 525 EventExecutionSample samples[MAX_NR_OF_JAVA_SAMPLES]; 526 EventNativeMethodSample samples_native[MAX_NR_OF_NATIVE_SAMPLES]; 527 JfrThreadSampleClosure sample_task(samples, samples_native); 528 529 const uint sample_limit = JAVA_SAMPLE == type ? MAX_NR_OF_JAVA_SAMPLES : MAX_NR_OF_NATIVE_SAMPLES; 530 uint num_sample_attempts = 0; 531 JavaThread* start = NULL; 532 533 { 534 elapsedTimer sample_time; 535 sample_time.start(); 536 { 537 MonitorLockerEx tlock(Threads_lock, Mutex::_allow_vm_block_flag); 538 int max_threads = Threads::number_of_threads(); 539 assert(max_threads >= 0, "Threads list is empty"); 540 uint index = 0; 541 JavaThread** threads_list = NEW_C_HEAP_ARRAY(JavaThread *, max_threads, mtInternal); 542 for (JavaThread* tp = Threads::first(); tp != NULL; tp = tp->next()) { 543 threads_list[index++] = tp; 544 } 545 JavaThread* current = Threads::includes(*last_thread) ? *last_thread : NULL; 546 JavaThread* start = NULL; 547 548 while (num_sample_attempts < sample_limit) { 549 current = next_thread(threads_list, index, start, current); 550 if (current == NULL) { 551 break; 552 } 553 if (start == NULL) { 554 start = current; // remember the thread where we started to attempt sampling 555 } 556 if (current->is_Compiler_thread()) { 557 continue; 558 } 559 sample_task.do_sample_thread(current, _frames, _max_frames, type); 560 num_sample_attempts++; 561 } 562 *last_thread = current; // remember the thread we last attempted to sample 563 FREE_C_HEAP_ARRAY(JavaThread *, threads_list, mtInternal); 564 } 565 sample_time.stop(); 566 if (LogJFR && Verbose) tty->print_cr("JFR thread sampling done in %3.7f secs with %d java %d native samples", 567 sample_time.seconds(), sample_task.java_entries(), sample_task.native_entries()); 568 } 569 if (num_sample_attempts > 0) { 570 sample_task.commit_events(type); 571 } 572 } 573 574 static JfrThreadSampling* _instance = NULL; 575 576 JfrThreadSampling& JfrThreadSampling::instance() { 577 return *_instance; 578 } 579 580 JfrThreadSampling* JfrThreadSampling::create() { 581 assert(_instance == NULL, "invariant"); 582 _instance = new JfrThreadSampling(); 583 return _instance; 584 } 585 586 void JfrThreadSampling::destroy() { 587 if (_instance != NULL) { 588 delete _instance; 589 _instance = NULL; 590 } 591 } 592 593 JfrThreadSampling::JfrThreadSampling() : _sampler(NULL) {} 594 595 JfrThreadSampling::~JfrThreadSampling() { 596 if (_sampler != NULL) { 597 _sampler->disenroll(); 598 } 599 } 600 601 static void log(size_t interval_java, size_t interval_native) { 602 if (LogJFR) tty->print_cr("Updated thread sampler for java: " SIZE_FORMAT " ms, native " SIZE_FORMAT " ms", interval_java, interval_native); 603 } 604 605 void JfrThreadSampling::start_sampler(size_t interval_java, size_t interval_native) { 606 assert(_sampler == NULL, "invariant"); 607 if (LogJFR) tty->print_cr("Enrolling thread sampler"); 608 _sampler = new JfrThreadSampler(interval_java, interval_native, JfrOptionSet::stackdepth()); 609 _sampler->start_thread(); 610 _sampler->enroll(); 611 } 612 613 void JfrThreadSampling::set_sampling_interval(bool java_interval, size_t period) { 614 size_t interval_java = 0; 615 size_t interval_native = 0; 616 if (_sampler != NULL) { 617 interval_java = _sampler->get_java_interval(); 618 interval_native = _sampler->get_native_interval(); 619 } 620 if (java_interval) { 621 interval_java = period; 622 } else { 623 interval_native = period; 624 } 625 if (interval_java > 0 || interval_native > 0) { 626 if (_sampler == NULL) { 627 if (LogJFR) tty->print_cr("Creating thread sampler for java:%zu ms, native %zu ms", interval_java, interval_native); 628 start_sampler(interval_java, interval_native); 629 } else { 630 _sampler->set_java_interval(interval_java); 631 _sampler->set_native_interval(interval_native); 632 _sampler->enroll(); 633 } 634 assert(_sampler != NULL, "invariant"); 635 log(interval_java, interval_native); 636 } else if (_sampler != NULL) { 637 _sampler->disenroll(); 638 } 639 } 640 641 void JfrThreadSampling::set_java_sample_interval(size_t period) { 642 if (_instance == NULL && 0 == period) { 643 return; 644 } 645 instance().set_sampling_interval(true, period); 646 } 647 648 void JfrThreadSampling::set_native_sample_interval(size_t period) { 649 if (_instance == NULL && 0 == period) { 650 return; 651 } 652 instance().set_sampling_interval(false, period); 653 } 654 655 void JfrThreadSampling::on_javathread_suspend(JavaThread* thread) { 656 JfrThreadSampler::on_javathread_suspend(thread); 657 } 658 659 Thread* JfrThreadSampling::sampler_thread() { 660 if (_instance == NULL) { 661 return NULL; 662 } 663 return _instance->_sampler != NULL ? _instance->_sampler->_sampler_thread : NULL; 664 }