< prev index next >

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

Print this page




 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  protected:
 339   virtual void post_run();
 340  public:
 341   void run();
 342   static Monitor* transition_block() { return JfrThreadSampler_lock; }
 343   static void on_javathread_suspend(JavaThread* thread);
 344 };
 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     MutexLocker 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();  // Provides StoreLoad, needed to keep read of thread state from floating up.
 363   if (JAVA_SAMPLE == type) {
 364     if (thread_state_in_java(thread)) {
 365       ret = sample_thread_in_java(thread, frames, max_frames);
 366     }
 367   } else {
 368     assert(NATIVE_SAMPLE == type, "invariant");
 369     if (thread_state_in_native(thread)) {
 370       ret = sample_thread_in_native(thread, frames, max_frames);
 371     }
 372   }
 373   clear_transition_block(thread);
 374   return ret;
 375 }
 376 
 377 JfrThreadSampler::JfrThreadSampler(size_t interval_java, size_t interval_native, u4 max_frames) :
 378   _sample(),
 379   _sampler_thread(NULL),
 380   _frames(JfrCHeapObj::new_array<JfrStackFrame>(max_frames)),
 381   _last_thread_java(NULL),
 382   _last_thread_native(NULL),
 383   _interval_java(interval_java),
 384   _interval_native(interval_native),
 385   _cur_index(-1),
 386   _max_frames(max_frames),
 387   _disenrolled(true) {
 388 }
 389 
 390 JfrThreadSampler::~JfrThreadSampler() {
 391   JfrCHeapObj::free(_frames, sizeof(JfrStackFrame) * _max_frames);
 392 }
 393 
 394 void JfrThreadSampler::on_javathread_suspend(JavaThread* thread) {
 395   JfrThreadLocal* const tl = thread->jfr_thread_local();
 396   tl->set_trace_block();
 397   {
 398     MonitorLocker ml(transition_block(), Mutex::_no_safepoint_check_flag);
 399     while (thread->is_trace_suspend()) {
 400       ml.wait();
 401     }
 402     tl->clear_trace_block();
 403   }
 404 }
 405 
 406 JavaThread* JfrThreadSampler::next_thread(ThreadsList* t_list, JavaThread* first_sampled, JavaThread* current) {
 407   assert(t_list != NULL, "invariant");
 408   assert(Threads_lock->owned_by_self(), "Holding the thread table lock.");
 409   assert(_cur_index >= -1 && (uint)_cur_index + 1 <= t_list->length(), "invariant");
 410   assert((current == NULL && -1 == _cur_index) || (t_list->find_index_of_JavaThread(current) == _cur_index), "invariant");
 411   if ((uint)_cur_index + 1 == t_list->length()) {
 412     // wrap
 413     _cur_index = 0;
 414   } else {
 415     _cur_index++;
 416   }
 417   assert(_cur_index >= 0 && (uint)_cur_index < t_list->length(), "invariant");
 418   JavaThread* const next = t_list->thread_at(_cur_index);
 419   return next != first_sampled ? next : NULL;
 420 }


 499 void JfrThreadSampler::post_run() {
 500   this->NonJavaThread::post_run();
 501   delete this;
 502 }
 503 
 504 
 505 void JfrThreadSampler::task_stacktrace(JfrSampleType type, JavaThread** last_thread) {
 506   ResourceMark rm;
 507   EventExecutionSample samples[MAX_NR_OF_JAVA_SAMPLES];
 508   EventNativeMethodSample samples_native[MAX_NR_OF_NATIVE_SAMPLES];
 509   JfrThreadSampleClosure sample_task(samples, samples_native);
 510 
 511   const uint sample_limit = JAVA_SAMPLE == type ? MAX_NR_OF_JAVA_SAMPLES : MAX_NR_OF_NATIVE_SAMPLES;
 512   uint num_samples = 0;
 513   JavaThread* start = NULL;
 514 
 515   {
 516     elapsedTimer sample_time;
 517     sample_time.start();
 518     {
 519       MutexLocker tlock(Threads_lock, Mutex::_no_safepoint_check_flag);
 520       ThreadsListHandle tlh;
 521       // Resolve a sample session relative start position index into the thread list array.
 522       // In cases where the last sampled thread is NULL or not-NULL but stale, find_index() returns -1.
 523       _cur_index = tlh.list()->find_index_of_JavaThread(*last_thread);
 524       JavaThread* current = _cur_index != -1 ? *last_thread : NULL;
 525 
 526       while (num_samples < sample_limit) {
 527         current = next_thread(tlh.list(), start, current);
 528         if (current == NULL) {
 529           break;
 530         }
 531         if (start == NULL) {
 532           start = current;  // remember the thread where we started to attempt sampling
 533         }
 534         if (current->is_Compiler_thread()) {
 535           continue;
 536         }
 537         if (sample_task.do_sample_thread(current, _frames, _max_frames, type)) {
 538           num_samples++;
 539         }




 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  protected:
 339   virtual void post_run();
 340  public:
 341   void run();
 342   static Monitor* transition_block() { return JfrThreadSampler_lock; }
 343   static void on_javathread_suspend(JavaThread* thread);
 344 };
 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 (JAVA_SAMPLE == type) {
 364     if (thread_state_in_java(thread)) {
 365       ret = sample_thread_in_java(thread, frames, max_frames);
 366     }
 367   } else {
 368     assert(NATIVE_SAMPLE == type, "invariant");
 369     if (thread_state_in_native(thread)) {
 370       ret = sample_thread_in_native(thread, frames, max_frames);
 371     }
 372   }
 373   clear_transition_block(thread);
 374   return ret;
 375 }
 376 
 377 JfrThreadSampler::JfrThreadSampler(size_t interval_java, size_t interval_native, u4 max_frames) :
 378   _sample(),
 379   _sampler_thread(NULL),
 380   _frames(JfrCHeapObj::new_array<JfrStackFrame>(max_frames)),
 381   _last_thread_java(NULL),
 382   _last_thread_native(NULL),
 383   _interval_java(interval_java),
 384   _interval_native(interval_native),
 385   _cur_index(-1),
 386   _max_frames(max_frames),
 387   _disenrolled(true) {
 388 }
 389 
 390 JfrThreadSampler::~JfrThreadSampler() {
 391   JfrCHeapObj::free(_frames, sizeof(JfrStackFrame) * _max_frames);
 392 }
 393 
 394 void JfrThreadSampler::on_javathread_suspend(JavaThread* thread) {
 395   JfrThreadLocal* const tl = thread->jfr_thread_local();
 396   tl->set_trace_block();
 397   {
 398     MutexLockerEx ml(transition_block(), Mutex::_no_safepoint_check_flag);
 399     while (thread->is_trace_suspend()) {
 400       transition_block()->wait(true);
 401     }
 402     tl->clear_trace_block();
 403   }
 404 }
 405 
 406 JavaThread* JfrThreadSampler::next_thread(ThreadsList* t_list, JavaThread* first_sampled, JavaThread* current) {
 407   assert(t_list != NULL, "invariant");
 408   assert(Threads_lock->owned_by_self(), "Holding the thread table lock.");
 409   assert(_cur_index >= -1 && (uint)_cur_index + 1 <= t_list->length(), "invariant");
 410   assert((current == NULL && -1 == _cur_index) || (t_list->find_index_of_JavaThread(current) == _cur_index), "invariant");
 411   if ((uint)_cur_index + 1 == t_list->length()) {
 412     // wrap
 413     _cur_index = 0;
 414   } else {
 415     _cur_index++;
 416   }
 417   assert(_cur_index >= 0 && (uint)_cur_index < t_list->length(), "invariant");
 418   JavaThread* const next = t_list->thread_at(_cur_index);
 419   return next != first_sampled ? next : NULL;
 420 }


 499 void JfrThreadSampler::post_run() {
 500   this->NonJavaThread::post_run();
 501   delete this;
 502 }
 503 
 504 
 505 void JfrThreadSampler::task_stacktrace(JfrSampleType type, JavaThread** last_thread) {
 506   ResourceMark rm;
 507   EventExecutionSample samples[MAX_NR_OF_JAVA_SAMPLES];
 508   EventNativeMethodSample samples_native[MAX_NR_OF_NATIVE_SAMPLES];
 509   JfrThreadSampleClosure sample_task(samples, samples_native);
 510 
 511   const uint sample_limit = JAVA_SAMPLE == type ? MAX_NR_OF_JAVA_SAMPLES : MAX_NR_OF_NATIVE_SAMPLES;
 512   uint num_samples = 0;
 513   JavaThread* start = NULL;
 514 
 515   {
 516     elapsedTimer sample_time;
 517     sample_time.start();
 518     {
 519       MonitorLockerEx tlock(Threads_lock, Mutex::_allow_vm_block_flag);
 520       ThreadsListHandle tlh;
 521       // Resolve a sample session relative start position index into the thread list array.
 522       // In cases where the last sampled thread is NULL or not-NULL but stale, find_index() returns -1.
 523       _cur_index = tlh.list()->find_index_of_JavaThread(*last_thread);
 524       JavaThread* current = _cur_index != -1 ? *last_thread : NULL;
 525 
 526       while (num_samples < sample_limit) {
 527         current = next_thread(tlh.list(), start, current);
 528         if (current == NULL) {
 529           break;
 530         }
 531         if (start == NULL) {
 532           start = current;  // remember the thread where we started to attempt sampling
 533         }
 534         if (current->is_Compiler_thread()) {
 535           continue;
 536         }
 537         if (sample_task.do_sample_thread(current, _frames, _max_frames, type)) {
 538           num_samples++;
 539         }


< prev index next >