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