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