< prev index next >

src/share/vm/jfr/periodic/sampling/jfrThreadSampler.cpp

Print this page
rev 9031 : 8223689: Add JFR Thread Sampling Support

*** 319,329 **** int _cur_index; const u4 _max_frames; volatile bool _disenrolled; static Monitor* _transition_block_lock; ! // JavaThread* next_thread(ThreadsList* t_list, JavaThread* first_sampled, JavaThread* current); void task_stacktrace(JfrSampleType type, JavaThread** last_thread); JfrThreadSampler(size_t interval_java, size_t interval_native, u4 max_frames); ~JfrThreadSampler(); void start_thread(); --- 319,330 ---- int _cur_index; const u4 _max_frames; volatile bool _disenrolled; static Monitor* _transition_block_lock; ! int find_index_of_JavaThread(JavaThread** t_list, uint length, JavaThread *target); ! JavaThread* next_thread(JavaThread** t_list, uint length, JavaThread* first_sampled, JavaThread* current); void task_stacktrace(JfrSampleType type, JavaThread** last_thread); JfrThreadSampler(size_t interval_java, size_t interval_native, u4 max_frames); ~JfrThreadSampler(); void start_thread();
*** 342,352 **** }; Monitor* JfrThreadSampler::_transition_block_lock = new Monitor(Mutex::leaf, "Trace block", true); static void clear_transition_block(JavaThread* jt) { ! // jt->clear_trace_flag(); JfrThreadLocal* const tl = jt->jfr_thread_local(); if (tl->is_trace_block()) { MutexLockerEx ml(JfrThreadSampler::transition_block(), Mutex::_no_safepoint_check_flag); JfrThreadSampler::transition_block()->notify_all(); } --- 343,353 ---- }; Monitor* JfrThreadSampler::_transition_block_lock = new Monitor(Mutex::leaf, "Trace block", true); static void clear_transition_block(JavaThread* jt) { ! jt->clear_trace_flag(); JfrThreadLocal* const tl = jt->jfr_thread_local(); if (tl->is_trace_block()) { MutexLockerEx ml(JfrThreadSampler::transition_block(), Mutex::_no_safepoint_check_flag); JfrThreadSampler::transition_block()->notify_all(); }
*** 357,367 **** if (thread->is_hidden_from_external_view() || thread->in_deopt_handler()) { return false; } bool ret = false; ! // thread->set_trace_flag(); if (!UseMembar) { os::serialize_thread_states(); } if (JAVA_SAMPLE == type) { if (thread_state_in_java(thread)) { --- 358,368 ---- if (thread->is_hidden_from_external_view() || thread->in_deopt_handler()) { return false; } bool ret = false; ! thread->set_trace_flag(); if (!UseMembar) { os::serialize_thread_states(); } if (JAVA_SAMPLE == type) { if (thread_state_in_java(thread)) {
*** 396,436 **** void JfrThreadSampler::on_javathread_suspend(JavaThread* thread) { JfrThreadLocal* const tl = thread->jfr_thread_local(); tl->set_trace_block(); { ! // MutexLockerEx ml(transition_block(), Mutex::_no_safepoint_check_flag); ! // while (thread->is_trace_suspend()) { ! // transition_block()->wait(true); ! // } ! // tl->clear_trace_block(); } } ! //JavaThread* JfrThreadSampler::next_thread(ThreadsList* t_list, JavaThread* first_sampled, JavaThread* current) { ! // assert(t_list != NULL, "invariant"); ! // assert(Threads_lock->owned_by_self(), "Holding the thread table lock."); ! // assert(_cur_index >= -1 && (uint)_cur_index + 1 <= t_list->length(), "invariant"); ! // assert((current == NULL && -1 == _cur_index) || (t_list->find_index_of_JavaThread(current) == _cur_index), "invariant"); ! // if ((uint)_cur_index + 1 == t_list->length()) { ! // // wrap ! // _cur_index = 0; ! // } else { ! // _cur_index++; ! // } ! // assert(_cur_index >= 0 && (uint)_cur_index < t_list->length(), "invariant"); ! // JavaThread* const next = t_list->thread_at(_cur_index); ! // return next != first_sampled ? next : NULL; ! //} void JfrThreadSampler::start_thread() { ! // XXX TODO implement sampling ! // if (os::create_thread(this, os::os_thread)) { ! // os::start_thread(this); ! // } else { ! // if (true) tty->print_cr("Failed to create thread for thread sampling"); ! // } } void JfrThreadSampler::enroll() { if (_disenrolled) { if (LogJFR) tty->print_cr("Enrolling thread sampler"); --- 397,461 ---- void JfrThreadSampler::on_javathread_suspend(JavaThread* thread) { JfrThreadLocal* const tl = thread->jfr_thread_local(); tl->set_trace_block(); { ! MutexLockerEx ml(transition_block(), Mutex::_no_safepoint_check_flag); ! while (thread->is_trace_suspend()) { ! transition_block()->wait(true); } + tl->clear_trace_block(); + } + } + + int JfrThreadSampler::find_index_of_JavaThread(JavaThread** t_list, uint length, JavaThread *target) { + assert(Threads_lock->owned_by_self(), "Holding the thread table lock."); + if (target == NULL) { + return -1; + } + for (uint i = 0; i < length; i++) { + if (target == t_list[i]) { + return (int)i; + } + } + return -1; } ! JavaThread* JfrThreadSampler::next_thread(JavaThread** t_list, uint length, JavaThread* first_sampled, JavaThread* current) { ! assert(Threads_lock->owned_by_self(), "Holding the thread table lock."); ! if (current == NULL) { ! _cur_index = 0; ! return t_list[_cur_index]; ! } ! ! if (_cur_index == -1 || t_list[_cur_index] != current) { ! // 'current' is not at '_cur_index' so find it: ! _cur_index = find_index_of_JavaThread(t_list, length, current); ! assert(_cur_index != -1, "current JavaThread should be findable."); ! } ! _cur_index++; ! ! JavaThread* next = NULL; ! // wrap ! if ((uint)_cur_index >= length) { ! _cur_index = 0; ! } ! next = t_list[_cur_index]; ! ! // sample wrap ! if (next == first_sampled) { ! return NULL; ! } ! return next; ! } void JfrThreadSampler::start_thread() { ! if (os::create_thread(this, os::os_thread)) { ! os::start_thread(this); ! } else { ! tty->print_cr("Failed to create thread for thread sampling"); ! } } void JfrThreadSampler::enroll() { if (_disenrolled) { if (LogJFR) tty->print_cr("Enrolling thread sampler");
*** 508,539 **** { elapsedTimer sample_time; sample_time.start(); { ! // MonitorLockerEx tlock(Threads_lock, Mutex::_allow_vm_block_flag); ! // ThreadsListHandle tlh; ! // // Resolve a sample session relative start position index into the thread list array. ! // // In cases where the last sampled thread is NULL or not-NULL but stale, find_index() returns -1. ! // _cur_index = tlh.list()->find_index_of_JavaThread(*last_thread); ! // JavaThread* current = _cur_index != -1 ? *last_thread : NULL; ! // ! // while (num_sample_attempts < sample_limit) { ! // current = next_thread(tlh.list(), start, current); ! // if (current == NULL) { ! // break; ! // } ! // if (start == NULL) { ! // start = current; // remember the thread where we started to attempt sampling ! // } ! // if (current->is_Compiler_thread()) { ! // continue; ! // } ! // sample_task.do_sample_thread(current, _frames, _max_frames, type); ! // num_sample_attempts++; ! // } ! // *last_thread = current; // remember the thread we last attempted to sample } sample_time.stop(); if (LogJFR && Verbose) tty->print_cr("JFR thread sampling done in %3.7f secs with %d java %d native samples", sample_time.seconds(), sample_task.java_entries(), sample_task.native_entries()); } --- 533,569 ---- { elapsedTimer sample_time; sample_time.start(); { ! MonitorLockerEx tlock(Threads_lock, Mutex::_allow_vm_block_flag); ! int max_threads = Threads::number_of_threads(); ! assert(max_threads >= 0, "Threads list is empty"); ! uint index = 0; ! JavaThread** threads_list = NEW_C_HEAP_ARRAY(JavaThread *, max_threads, mtInternal); ! for (JavaThread* tp = Threads::first(); tp != NULL; tp = tp->next()) { ! threads_list[index++] = tp; ! } ! JavaThread* current = Threads::includes(*last_thread) ? *last_thread : NULL; ! JavaThread* start = NULL; ! ! while (num_sample_attempts < sample_limit) { ! current = next_thread(threads_list, index, start, current); ! if (current == NULL) { ! break; ! } ! if (start == NULL) { ! start = current; // remember the thread where we started to attempt sampling ! } ! if (current->is_Compiler_thread()) { ! continue; ! } ! sample_task.do_sample_thread(current, _frames, _max_frames, type); ! num_sample_attempts++; ! } ! *last_thread = current; // remember the thread we last attempted to sample ! FREE_C_HEAP_ARRAY(JavaThread *, threads_list, mtInternal); } sample_time.stop(); if (LogJFR && Verbose) tty->print_cr("JFR thread sampling done in %3.7f secs with %d java %d native samples", sample_time.seconds(), sample_task.java_entries(), sample_task.native_entries()); }
< prev index next >