1 /*
   2  * Copyright (c) 2012, 2019, 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::ThreadCrashProtection 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::ThreadCrashProtection 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   initialize_thread_local_storage();
 483   record_stack_base_and_size();
 484 
 485   _sampler_thread = this;
 486 
 487   jlong last_java_ms = get_monotonic_ms();
 488   jlong last_native_ms = last_java_ms;
 489   while (true) {
 490     if (!_sample.trywait()) {
 491       // disenrolled
 492       _sample.wait();
 493       last_java_ms = get_monotonic_ms();
 494       last_native_ms = last_java_ms;
 495     }
 496     _sample.signal();
 497     jlong java_interval = _interval_java == 0 ? max_jlong : MAX2<jlong>(_interval_java, 10);
 498     jlong native_interval = _interval_native == 0 ? max_jlong : MAX2<jlong>(_interval_native, 10);
 499 
 500     jlong now_ms = get_monotonic_ms();
 501 
 502     /*
 503      * Let I be java_interval or native_interval.
 504      * Let L be last_java_ms or last_native_ms.
 505      * Let N be now_ms.
 506      *
 507      * Interval, I, might be max_jlong so the addition
 508      * could potentially overflow without parenthesis (UB). Also note that
 509      * L - N < 0. Avoid UB, by adding parenthesis.
 510      */
 511     jlong next_j = java_interval + (last_java_ms - now_ms);
 512     jlong next_n = native_interval + (last_native_ms - now_ms);
 513 
 514     jlong sleep_to_next = MIN2<jlong>(next_j, next_n);
 515 
 516     if (sleep_to_next > 0) {
 517       os::naked_short_sleep(sleep_to_next);
 518     }
 519 
 520     if ((next_j - sleep_to_next) <= 0) {
 521       task_stacktrace(JAVA_SAMPLE, &_last_thread_java);
 522       last_java_ms = get_monotonic_ms();
 523     }
 524     if ((next_n - sleep_to_next) <= 0) {
 525       task_stacktrace(NATIVE_SAMPLE, &_last_thread_native);
 526       last_native_ms = get_monotonic_ms();
 527     }
 528   }
 529   delete this;
 530 }
 531 
 532 
 533 void JfrThreadSampler::task_stacktrace(JfrSampleType type, JavaThread** last_thread) {
 534   ResourceMark rm;
 535   EventExecutionSample samples[MAX_NR_OF_JAVA_SAMPLES];
 536   EventNativeMethodSample samples_native[MAX_NR_OF_NATIVE_SAMPLES];
 537   JfrThreadSampleClosure sample_task(samples, samples_native);
 538 
 539   const uint sample_limit = JAVA_SAMPLE == type ? MAX_NR_OF_JAVA_SAMPLES : MAX_NR_OF_NATIVE_SAMPLES;
 540   uint num_sample_attempts = 0;
 541   JavaThread* start = NULL;
 542 
 543   {
 544     elapsedTimer sample_time;
 545     sample_time.start();
 546     {
 547       MonitorLockerEx tlock(Threads_lock, Mutex::_allow_vm_block_flag);
 548       int max_threads = Threads::number_of_threads();
 549       assert(max_threads >= 0, "Threads list is empty");
 550       uint index = 0;
 551       JavaThread** threads_list = NEW_C_HEAP_ARRAY(JavaThread *, max_threads, mtInternal);
 552       for (JavaThread* tp = Threads::first(); tp != NULL; tp = tp->next()) {
 553         threads_list[index++] = tp;
 554       }
 555       JavaThread* current = Threads::includes(*last_thread) ? *last_thread : NULL;
 556       JavaThread* start = NULL;
 557 
 558       while (num_sample_attempts < sample_limit) {
 559         current = next_thread(threads_list, index, start, current);
 560         if (current == NULL) {
 561           break;
 562         }
 563         if (start == NULL) {
 564           start = current;  // remember the thread where we started to attempt sampling
 565         }
 566         if (current->is_Compiler_thread()) {
 567           continue;
 568         }
 569         sample_task.do_sample_thread(current, _frames, _max_frames, type);
 570         num_sample_attempts++;
 571       }
 572       *last_thread = current;  // remember the thread we last attempted to sample
 573       FREE_C_HEAP_ARRAY(JavaThread *, threads_list, mtInternal);
 574     }
 575     sample_time.stop();
 576     if (LogJFR && Verbose) tty->print_cr("JFR thread sampling done in %3.7f secs with %d java %d native samples",
 577                    sample_time.seconds(), sample_task.java_entries(), sample_task.native_entries());
 578   }
 579   if (num_sample_attempts > 0) {
 580     sample_task.commit_events(type);
 581   }
 582 }
 583 
 584 static JfrThreadSampling* _instance = NULL;
 585 
 586 JfrThreadSampling& JfrThreadSampling::instance() {
 587   return *_instance;
 588 }
 589 
 590 JfrThreadSampling* JfrThreadSampling::create() {
 591   assert(_instance == NULL, "invariant");
 592   _instance = new JfrThreadSampling();
 593   return _instance;
 594 }
 595 
 596 void JfrThreadSampling::destroy() {
 597   if (_instance != NULL) {
 598     delete _instance;
 599     _instance = NULL;
 600   }
 601 }
 602 
 603 JfrThreadSampling::JfrThreadSampling() : _sampler(NULL) {}
 604 
 605 JfrThreadSampling::~JfrThreadSampling() {
 606   if (_sampler != NULL) {
 607     _sampler->disenroll();
 608   }
 609 }
 610 
 611 static void log(size_t interval_java, size_t interval_native) {
 612   if (LogJFR) tty->print_cr("Updated thread sampler for java: " SIZE_FORMAT "  ms, native " SIZE_FORMAT " ms", interval_java, interval_native);
 613 }
 614 
 615 void JfrThreadSampling::start_sampler(size_t interval_java, size_t interval_native) {
 616   assert(_sampler == NULL, "invariant");
 617   if (LogJFR) tty->print_cr("Enrolling thread sampler");
 618   _sampler = new JfrThreadSampler(interval_java, interval_native, JfrOptionSet::stackdepth());
 619   _sampler->start_thread();
 620   _sampler->enroll();
 621 }
 622 
 623 void JfrThreadSampling::set_sampling_interval(bool java_interval, size_t period) {
 624   size_t interval_java = 0;
 625   size_t interval_native = 0;
 626   if (_sampler != NULL) {
 627     interval_java = _sampler->get_java_interval();
 628     interval_native = _sampler->get_native_interval();
 629   }
 630   if (java_interval) {
 631     interval_java = period;
 632   } else {
 633     interval_native = period;
 634   }
 635   if (interval_java > 0 || interval_native > 0) {
 636     if (_sampler == NULL) {
 637       if (LogJFR) tty->print_cr("Creating thread sampler for java:%zu ms, native %zu ms", interval_java, interval_native);
 638       start_sampler(interval_java, interval_native);
 639     } else {
 640       _sampler->set_java_interval(interval_java);
 641       _sampler->set_native_interval(interval_native);
 642       _sampler->enroll();
 643     }
 644     assert(_sampler != NULL, "invariant");
 645     log(interval_java, interval_native);
 646   } else if (_sampler != NULL) {
 647     _sampler->disenroll();
 648   }
 649 }
 650 
 651 void JfrThreadSampling::set_java_sample_interval(size_t period) {
 652   if (_instance == NULL && 0 == period) {
 653     return;
 654   }
 655   instance().set_sampling_interval(true, period);
 656 }
 657 
 658 void JfrThreadSampling::set_native_sample_interval(size_t period) {
 659   if (_instance == NULL && 0 == period) {
 660     return;
 661   }
 662   instance().set_sampling_interval(false, period);
 663 }
 664 
 665 void JfrThreadSampling::on_javathread_suspend(JavaThread* thread) {
 666   JfrThreadSampler::on_javathread_suspend(thread);
 667 }
 668 
 669 Thread* JfrThreadSampling::sampler_thread() {
 670   if (_instance == NULL) {
 671     return NULL;
 672   }
 673   return _instance->_sampler != NULL ? _instance->_sampler->_sampler_thread : NULL;
 674 }