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 
thread_state_in_java(JavaThread * thread)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 
thread_state_in_native(JavaThread * thread)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);
~JfrThreadSampleClosure()94   ~JfrThreadSampleClosure() {}
next_event()95   EventExecutionSample* next_event() { return &_events[_added_java++]; }
next_event_native()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);
java_entries()99   uint java_entries() { return _added_java; }
native_entries()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:
OSThreadSampler(JavaThread * thread,JfrThreadSampleClosure & closure,JfrStackFrame * frames,u4 max_frames)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);
success() const126   bool success() const { return _success; }
stacktrace() const127   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:
OSThreadSamplerCallback(OSThreadSampler & sampler,const os::SuspendedThreadTaskContext & context)138   OSThreadSamplerCallback(OSThreadSampler& sampler, const os::SuspendedThreadTaskContext &context) :
139     _sampler(sampler), _context(context) {
140   }
call()141   virtual void call() {
142     _sampler.protected_task(_context);
143   }
144  private:
145   OSThreadSampler& _sampler;
146   const os::SuspendedThreadTaskContext& _context;
147 };
148 
do_task(const os::SuspendedThreadTaskContext & context)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. */
protected_task(const os::SuspendedThreadTaskContext & context)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 
take_sample()195 void OSThreadSampler::take_sample() {
196   run();
197 }
198 
199 class JfrNativeSamplerCallback : public os::CrashProtectionCallback {
200  public:
JfrNativeSamplerCallback(JfrThreadSampleClosure & closure,JavaThread * jt,JfrStackFrame * frames,u4 max_frames)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();
success()205   bool success() { return _success; }
stacktrace()206   JfrStackTrace& stacktrace() { return _stacktrace; }
207 
208  private:
209   JfrThreadSampleClosure& _closure;
210   JavaThread* _jt;
211   JfrStackTrace _stacktrace;
212   bool _success;
213 };
214 
write_native_event(JfrThreadSampleClosure & closure,JavaThread * jt)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 
call()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 
sample_thread_in_java(JavaThread * thread,JfrStackFrame * frames,u4 max_frames)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 
sample_thread_in_native(JavaThread * thread,JfrStackFrame * frames,u4 max_frames)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 
commit_events(JfrSampleType type)286 void JfrThreadSampleClosure::commit_events(JfrSampleType type) {
287   if (JAVA_SAMPLE == type) {
288     assert(_added_java > 0 && _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 > 0 && _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 
JfrThreadSampleClosure(EventExecutionSample * events,EventNativeMethodSample * events_native)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();
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 _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 
clear_transition_block(JavaThread * jt)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 
do_sample_thread(JavaThread * thread,JfrStackFrame * frames,u4 max_frames,JfrSampleType type)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 
JfrThreadSampler(size_t interval_java,size_t interval_native,u4 max_frames)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 
~JfrThreadSampler()394 JfrThreadSampler::~JfrThreadSampler() {
395   JfrCHeapObj::free(_frames, sizeof(JfrStackFrame) * _max_frames);
396 }
397 
on_javathread_suspend(JavaThread * thread)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 
find_index_of_JavaThread(JavaThread ** t_list,uint length,JavaThread * target)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 
next_thread(JavaThread ** t_list,uint length,JavaThread * first_sampled,JavaThread * current)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 
start_thread()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 
enroll()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 
disenroll()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 
get_monotonic_ms()475 static jlong get_monotonic_ms() {
476   return os::javaTimeNanos() / 1000000;
477 }
478 
run()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, 1);
498     jlong native_interval = _interval_native == 0 ? max_jlong : MAX2<jlong>(_interval_native, 1);
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 
task_stacktrace(JfrSampleType type,JavaThread ** last_thread)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_samples = 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_samples < 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         if (sample_task.do_sample_thread(current, _frames, _max_frames, type)) {
570           num_samples++;
571         }
572       }
573       *last_thread = current;  // remember the thread we last attempted to sample
574       FREE_C_HEAP_ARRAY(JavaThread *, threads_list, mtInternal);
575     }
576     sample_time.stop();
577     if (LogJFR && Verbose) tty->print_cr("JFR thread sampling done in %3.7f secs with %d java %d native samples",
578                    sample_time.seconds(), sample_task.java_entries(), sample_task.native_entries());
579   }
580   if (num_samples > 0) {
581     sample_task.commit_events(type);
582   }
583 }
584 
585 static JfrThreadSampling* _instance = NULL;
586 
instance()587 JfrThreadSampling& JfrThreadSampling::instance() {
588   return *_instance;
589 }
590 
create()591 JfrThreadSampling* JfrThreadSampling::create() {
592   assert(_instance == NULL, "invariant");
593   _instance = new JfrThreadSampling();
594   return _instance;
595 }
596 
destroy()597 void JfrThreadSampling::destroy() {
598   if (_instance != NULL) {
599     delete _instance;
600     _instance = NULL;
601   }
602 }
603 
JfrThreadSampling()604 JfrThreadSampling::JfrThreadSampling() : _sampler(NULL) {}
605 
~JfrThreadSampling()606 JfrThreadSampling::~JfrThreadSampling() {
607   if (_sampler != NULL) {
608     _sampler->disenroll();
609   }
610 }
611 
log(size_t interval_java,size_t interval_native)612 static void log(size_t interval_java, size_t interval_native) {
613   if (LogJFR) tty->print_cr("Updated thread sampler for java: " SIZE_FORMAT "  ms, native " SIZE_FORMAT " ms", interval_java, interval_native);
614 }
615 
start_sampler(size_t interval_java,size_t interval_native)616 void JfrThreadSampling::start_sampler(size_t interval_java, size_t interval_native) {
617   assert(_sampler == NULL, "invariant");
618   if (LogJFR) tty->print_cr("Enrolling thread sampler");
619   _sampler = new JfrThreadSampler(interval_java, interval_native, JfrOptionSet::stackdepth());
620   _sampler->start_thread();
621   _sampler->enroll();
622 }
623 
set_sampling_interval(bool java_interval,size_t period)624 void JfrThreadSampling::set_sampling_interval(bool java_interval, size_t period) {
625   size_t interval_java = 0;
626   size_t interval_native = 0;
627   if (_sampler != NULL) {
628     interval_java = _sampler->get_java_interval();
629     interval_native = _sampler->get_native_interval();
630   }
631   if (java_interval) {
632     interval_java = period;
633   } else {
634     interval_native = period;
635   }
636   if (interval_java > 0 || interval_native > 0) {
637     if (_sampler == NULL) {
638       if (LogJFR) tty->print_cr("Creating thread sampler for java:%zu ms, native %zu ms", interval_java, interval_native);
639       start_sampler(interval_java, interval_native);
640     } else {
641       _sampler->set_java_interval(interval_java);
642       _sampler->set_native_interval(interval_native);
643       _sampler->enroll();
644     }
645     assert(_sampler != NULL, "invariant");
646     log(interval_java, interval_native);
647   } else if (_sampler != NULL) {
648     _sampler->disenroll();
649   }
650 }
651 
set_java_sample_interval(size_t period)652 void JfrThreadSampling::set_java_sample_interval(size_t period) {
653   if (_instance == NULL && 0 == period) {
654     return;
655   }
656   instance().set_sampling_interval(true, period);
657 }
658 
set_native_sample_interval(size_t period)659 void JfrThreadSampling::set_native_sample_interval(size_t period) {
660   if (_instance == NULL && 0 == period) {
661     return;
662   }
663   instance().set_sampling_interval(false, period);
664 }
665 
on_javathread_suspend(JavaThread * thread)666 void JfrThreadSampling::on_javathread_suspend(JavaThread* thread) {
667   JfrThreadSampler::on_javathread_suspend(thread);
668 }
669 
sampler_thread()670 Thread* JfrThreadSampling::sampler_thread() {
671   if (_instance == NULL) {
672     return NULL;
673   }
674   return _instance->_sampler != NULL ? _instance->_sampler->_sampler_thread : NULL;
675 }
676