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 // JavaThread* next_thread(ThreadsList* t_list, JavaThread* first_sampled, JavaThread* current);
325 void task_stacktrace(JfrSampleType type, JavaThread** last_thread);
326 JfrThreadSampler(size_t interval_java, size_t interval_native, u4 max_frames);
327 ~JfrThreadSampler();
328
329 void start_thread();
330
331 void enroll();
332 void disenroll();
333 void set_java_interval(size_t interval) { _interval_java = interval; };
334 void set_native_interval(size_t interval) { _interval_native = interval; };
335 size_t get_java_interval() { return _interval_java; };
336 size_t get_native_interval() { return _interval_native; };
337
338 public:
339 void run();
340 static Monitor* transition_block() { return _transition_block_lock; }
341 static void on_javathread_suspend(JavaThread* thread);
342 };
343
344 Monitor* JfrThreadSampler::_transition_block_lock = new Monitor(Mutex::leaf, "Trace block", true);
345
346 static void clear_transition_block(JavaThread* jt) {
347 // jt->clear_trace_flag();
348 JfrThreadLocal* const tl = jt->jfr_thread_local();
349 if (tl->is_trace_block()) {
350 MutexLockerEx ml(JfrThreadSampler::transition_block(), Mutex::_no_safepoint_check_flag);
351 JfrThreadSampler::transition_block()->notify_all();
352 }
353 }
354
355 bool JfrThreadSampleClosure::do_sample_thread(JavaThread* thread, JfrStackFrame* frames, u4 max_frames, JfrSampleType type) {
356 assert(Threads_lock->owned_by_self(), "Holding the thread table lock.");
357 if (thread->is_hidden_from_external_view() || thread->in_deopt_handler()) {
358 return false;
359 }
360
361 bool ret = false;
362 // thread->set_trace_flag();
363 if (!UseMembar) {
364 os::serialize_thread_states();
365 }
366 if (JAVA_SAMPLE == type) {
367 if (thread_state_in_java(thread)) {
368 ret = sample_thread_in_java(thread, frames, max_frames);
369 }
370 } else {
371 assert(NATIVE_SAMPLE == type, "invariant");
372 if (thread_state_in_native(thread)) {
373 ret = sample_thread_in_native(thread, frames, max_frames);
374 }
375 }
376 clear_transition_block(thread);
377 return ret;
378 }
379
380 JfrThreadSampler::JfrThreadSampler(size_t interval_java, size_t interval_native, u4 max_frames) :
381 _sample(),
382 _sampler_thread(NULL),
383 _frames(JfrCHeapObj::new_array<JfrStackFrame>(max_frames)),
384 _last_thread_java(NULL),
385 _last_thread_native(NULL),
386 _interval_java(interval_java),
387 _interval_native(interval_native),
388 _cur_index(-1),
389 _max_frames(max_frames),
390 _disenrolled(true) {
391 }
392
393 JfrThreadSampler::~JfrThreadSampler() {
394 JfrCHeapObj::free(_frames, sizeof(JfrStackFrame) * _max_frames);
395 }
396
397 void JfrThreadSampler::on_javathread_suspend(JavaThread* thread) {
398 JfrThreadLocal* const tl = thread->jfr_thread_local();
399 tl->set_trace_block();
400 {
401 // MutexLockerEx ml(transition_block(), Mutex::_no_safepoint_check_flag);
402 // while (thread->is_trace_suspend()) {
403 // transition_block()->wait(true);
404 // }
405 // tl->clear_trace_block();
406 }
407 }
408
409 //JavaThread* JfrThreadSampler::next_thread(ThreadsList* t_list, JavaThread* first_sampled, JavaThread* current) {
410 // assert(t_list != NULL, "invariant");
411 // assert(Threads_lock->owned_by_self(), "Holding the thread table lock.");
412 // assert(_cur_index >= -1 && (uint)_cur_index + 1 <= t_list->length(), "invariant");
413 // assert((current == NULL && -1 == _cur_index) || (t_list->find_index_of_JavaThread(current) == _cur_index), "invariant");
414 // if ((uint)_cur_index + 1 == t_list->length()) {
415 // // wrap
416 // _cur_index = 0;
417 // } else {
418 // _cur_index++;
419 // }
420 // assert(_cur_index >= 0 && (uint)_cur_index < t_list->length(), "invariant");
421 // JavaThread* const next = t_list->thread_at(_cur_index);
422 // return next != first_sampled ? next : NULL;
423 //}
424
425 void JfrThreadSampler::start_thread() {
426 // XXX TODO implement sampling
427 // if (os::create_thread(this, os::os_thread)) {
428 // os::start_thread(this);
429 // } else {
430 // if (true) tty->print_cr("Failed to create thread for thread sampling");
431 // }
432 }
433
434 void JfrThreadSampler::enroll() {
435 if (_disenrolled) {
436 if (LogJFR) tty->print_cr("Enrolling thread sampler");
437 _sample.signal();
438 _disenrolled = false;
439 }
440 }
441
442 void JfrThreadSampler::disenroll() {
443 if (!_disenrolled) {
444 _sample.wait();
445 _disenrolled = true;
446 if (LogJFR) tty->print_cr("Disenrolling thread sampler");
447 }
448 }
449
450 static jlong get_monotonic_ms() {
451 return os::javaTimeNanos() / 1000000;
493 }
494 }
495 delete this;
496 }
497
498
499 void JfrThreadSampler::task_stacktrace(JfrSampleType type, JavaThread** last_thread) {
500 ResourceMark rm;
501 EventExecutionSample samples[MAX_NR_OF_JAVA_SAMPLES];
502 EventNativeMethodSample samples_native[MAX_NR_OF_NATIVE_SAMPLES];
503 JfrThreadSampleClosure sample_task(samples, samples_native);
504
505 const uint sample_limit = JAVA_SAMPLE == type ? MAX_NR_OF_JAVA_SAMPLES : MAX_NR_OF_NATIVE_SAMPLES;
506 uint num_sample_attempts = 0;
507 JavaThread* start = NULL;
508
509 {
510 elapsedTimer sample_time;
511 sample_time.start();
512 {
513 // MonitorLockerEx tlock(Threads_lock, Mutex::_allow_vm_block_flag);
514 // ThreadsListHandle tlh;
515 // // Resolve a sample session relative start position index into the thread list array.
516 // // In cases where the last sampled thread is NULL or not-NULL but stale, find_index() returns -1.
517 // _cur_index = tlh.list()->find_index_of_JavaThread(*last_thread);
518 // JavaThread* current = _cur_index != -1 ? *last_thread : NULL;
519 //
520 // while (num_sample_attempts < sample_limit) {
521 // current = next_thread(tlh.list(), start, current);
522 // if (current == NULL) {
523 // break;
524 // }
525 // if (start == NULL) {
526 // start = current; // remember the thread where we started to attempt sampling
527 // }
528 // if (current->is_Compiler_thread()) {
529 // continue;
530 // }
531 // sample_task.do_sample_thread(current, _frames, _max_frames, type);
532 // num_sample_attempts++;
533 // }
534 // *last_thread = current; // remember the thread we last attempted to sample
535 }
536 sample_time.stop();
537 if (LogJFR && Verbose) tty->print_cr("JFR thread sampling done in %3.7f secs with %d java %d native samples",
538 sample_time.seconds(), sample_task.java_entries(), sample_task.native_entries());
539 }
540 if (num_sample_attempts > 0) {
541 sample_task.commit_events(type);
542 }
543 }
544
545 static JfrThreadSampling* _instance = NULL;
546
547 JfrThreadSampling& JfrThreadSampling::instance() {
548 return *_instance;
549 }
550
551 JfrThreadSampling* JfrThreadSampling::create() {
552 assert(_instance == NULL, "invariant");
553 _instance = new JfrThreadSampling();
554 return _instance;
|
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;
518 }
519 }
520 delete this;
521 }
522
523
524 void JfrThreadSampler::task_stacktrace(JfrSampleType type, JavaThread** last_thread) {
525 ResourceMark rm;
526 EventExecutionSample samples[MAX_NR_OF_JAVA_SAMPLES];
527 EventNativeMethodSample samples_native[MAX_NR_OF_NATIVE_SAMPLES];
528 JfrThreadSampleClosure sample_task(samples, samples_native);
529
530 const uint sample_limit = JAVA_SAMPLE == type ? MAX_NR_OF_JAVA_SAMPLES : MAX_NR_OF_NATIVE_SAMPLES;
531 uint num_sample_attempts = 0;
532 JavaThread* start = NULL;
533
534 {
535 elapsedTimer sample_time;
536 sample_time.start();
537 {
538 MonitorLockerEx tlock(Threads_lock, Mutex::_allow_vm_block_flag);
539 int max_threads = Threads::number_of_threads();
540 assert(max_threads >= 0, "Threads list is empty");
541 uint index = 0;
542 JavaThread** threads_list = NEW_C_HEAP_ARRAY(JavaThread *, max_threads, mtInternal);
543 for (JavaThread* tp = Threads::first(); tp != NULL; tp = tp->next()) {
544 threads_list[index++] = tp;
545 }
546 JavaThread* current = Threads::includes(*last_thread) ? *last_thread : NULL;
547 JavaThread* start = NULL;
548
549 while (num_sample_attempts < sample_limit) {
550 current = next_thread(threads_list, index, start, current);
551 if (current == NULL) {
552 break;
553 }
554 if (start == NULL) {
555 start = current; // remember the thread where we started to attempt sampling
556 }
557 if (current->is_Compiler_thread()) {
558 continue;
559 }
560 sample_task.do_sample_thread(current, _frames, _max_frames, type);
561 num_sample_attempts++;
562 }
563 *last_thread = current; // remember the thread we last attempted to sample
564 FREE_C_HEAP_ARRAY(JavaThread *, threads_list, mtInternal);
565 }
566 sample_time.stop();
567 if (LogJFR && Verbose) tty->print_cr("JFR thread sampling done in %3.7f secs with %d java %d native samples",
568 sample_time.seconds(), sample_task.java_entries(), sample_task.native_entries());
569 }
570 if (num_sample_attempts > 0) {
571 sample_task.commit_events(type);
572 }
573 }
574
575 static JfrThreadSampling* _instance = NULL;
576
577 JfrThreadSampling& JfrThreadSampling::instance() {
578 return *_instance;
579 }
580
581 JfrThreadSampling* JfrThreadSampling::create() {
582 assert(_instance == NULL, "invariant");
583 _instance = new JfrThreadSampling();
584 return _instance;
|