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;
492 }
493 }
494 delete this;
495 }
496
497
498 void JfrThreadSampler::task_stacktrace(JfrSampleType type, JavaThread** last_thread) {
499 ResourceMark rm;
500 EventExecutionSample samples[MAX_NR_OF_JAVA_SAMPLES];
501 EventNativeMethodSample samples_native[MAX_NR_OF_NATIVE_SAMPLES];
502 JfrThreadSampleClosure sample_task(samples, samples_native);
503
504 const uint sample_limit = JAVA_SAMPLE == type ? MAX_NR_OF_JAVA_SAMPLES : MAX_NR_OF_NATIVE_SAMPLES;
505 uint num_sample_attempts = 0;
506 JavaThread* start = NULL;
507
508 {
509 elapsedTimer sample_time;
510 sample_time.start();
511 {
512 // MonitorLockerEx tlock(Threads_lock, Mutex::_allow_vm_block_flag);
513 // ThreadsListHandle tlh;
514 // // Resolve a sample session relative start position index into the thread list array.
515 // // In cases where the last sampled thread is NULL or not-NULL but stale, find_index() returns -1.
516 // _cur_index = tlh.list()->find_index_of_JavaThread(*last_thread);
517 // JavaThread* current = _cur_index != -1 ? *last_thread : NULL;
518 //
519 // while (num_sample_attempts < sample_limit) {
520 // current = next_thread(tlh.list(), start, current);
521 // if (current == NULL) {
522 // break;
523 // }
524 // if (start == NULL) {
525 // start = current; // remember the thread where we started to attempt sampling
526 // }
527 // if (current->is_Compiler_thread()) {
528 // continue;
529 // }
530 // sample_task.do_sample_thread(current, _frames, _max_frames, type);
531 // num_sample_attempts++;
532 // }
533 // *last_thread = current; // remember the thread we last attempted to sample
534 }
535 sample_time.stop();
536 if (LogJFR && Verbose) tty->print_cr("JFR thread sampling done in %3.7f secs with %d java %d native samples",
537 sample_time.seconds(), sample_task.java_entries(), sample_task.native_entries());
538 }
539 if (num_sample_attempts > 0) {
540 sample_task.commit_events(type);
541 }
542 }
543
544 static JfrThreadSampling* _instance = NULL;
545
546 JfrThreadSampling& JfrThreadSampling::instance() {
547 return *_instance;
548 }
549
550 JfrThreadSampling* JfrThreadSampling::create() {
551 assert(_instance == NULL, "invariant");
552 _instance = new JfrThreadSampling();
553 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;
517 }
518 }
519 delete this;
520 }
521
522
523 void JfrThreadSampler::task_stacktrace(JfrSampleType type, JavaThread** last_thread) {
524 ResourceMark rm;
525 EventExecutionSample samples[MAX_NR_OF_JAVA_SAMPLES];
526 EventNativeMethodSample samples_native[MAX_NR_OF_NATIVE_SAMPLES];
527 JfrThreadSampleClosure sample_task(samples, samples_native);
528
529 const uint sample_limit = JAVA_SAMPLE == type ? MAX_NR_OF_JAVA_SAMPLES : MAX_NR_OF_NATIVE_SAMPLES;
530 uint num_sample_attempts = 0;
531 JavaThread* start = NULL;
532
533 {
534 elapsedTimer sample_time;
535 sample_time.start();
536 {
537 MonitorLockerEx tlock(Threads_lock, Mutex::_allow_vm_block_flag);
538 int max_threads = Threads::number_of_threads();
539 assert(max_threads >= 0, "Threads list is empty");
540 uint index = 0;
541 JavaThread** threads_list = NEW_C_HEAP_ARRAY(JavaThread *, max_threads, mtInternal);
542 for (JavaThread* tp = Threads::first(); tp != NULL; tp = tp->next()) {
543 threads_list[index++] = tp;
544 }
545 JavaThread* current = Threads::includes(*last_thread) ? *last_thread : NULL;
546 JavaThread* start = NULL;
547
548 while (num_sample_attempts < sample_limit) {
549 current = next_thread(threads_list, index, start, current);
550 if (current == NULL) {
551 break;
552 }
553 if (start == NULL) {
554 start = current; // remember the thread where we started to attempt sampling
555 }
556 if (current->is_Compiler_thread()) {
557 continue;
558 }
559 sample_task.do_sample_thread(current, _frames, _max_frames, type);
560 num_sample_attempts++;
561 }
562 *last_thread = current; // remember the thread we last attempted to sample
563 FREE_C_HEAP_ARRAY(JavaThread *, threads_list, mtInternal);
564 }
565 sample_time.stop();
566 if (LogJFR && Verbose) tty->print_cr("JFR thread sampling done in %3.7f secs with %d java %d native samples",
567 sample_time.seconds(), sample_task.java_entries(), sample_task.native_entries());
568 }
569 if (num_sample_attempts > 0) {
570 sample_task.commit_events(type);
571 }
572 }
573
574 static JfrThreadSampling* _instance = NULL;
575
576 JfrThreadSampling& JfrThreadSampling::instance() {
577 return *_instance;
578 }
579
580 JfrThreadSampling* JfrThreadSampling::create() {
581 assert(_instance == NULL, "invariant");
582 _instance = new JfrThreadSampling();
583 return _instance;
|