src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp
changeset 50373 22f611c395b3
parent 50222 911b913022ef
child 51548 35a6956f4243
equal deleted inserted replaced
50372:7a013fbf6fc3 50373:22f611c395b3
    42   NO_SAMPLE = 0,
    42   NO_SAMPLE = 0,
    43   JAVA_SAMPLE = 1,
    43   JAVA_SAMPLE = 1,
    44   NATIVE_SAMPLE = 2
    44   NATIVE_SAMPLE = 2
    45 };
    45 };
    46 
    46 
    47 static bool in_java_sample(JavaThread* thread) {
    47 static bool thread_state_in_java(JavaThread* thread) {
    48   switch (thread->thread_state()) {
    48   assert(thread != NULL, "invariant");
    49   case _thread_new:
    49   switch(thread->thread_state()) {
    50   case _thread_uninitialized:
    50     case _thread_new:
    51   case _thread_new_trans:
    51     case _thread_uninitialized:
    52   case _thread_in_vm_trans:
    52     case _thread_new_trans:
    53   case _thread_blocked_trans:
    53     case _thread_in_vm_trans:
    54   case _thread_in_native_trans:
    54     case _thread_blocked_trans:
    55   case _thread_blocked:
    55     case _thread_in_native_trans:
    56   case _thread_in_vm:
    56     case _thread_blocked:
    57   case _thread_in_native:
    57     case _thread_in_vm:
    58   case _thread_in_Java_trans:
    58     case _thread_in_native:
    59     break;
    59     case _thread_in_Java_trans:
    60   case _thread_in_Java:
    60       break;
    61     return true;
    61     case _thread_in_Java:
    62   default:
    62       return true;
    63     ShouldNotReachHere();
    63     default:
    64     break;
    64       ShouldNotReachHere();
       
    65       break;
    65   }
    66   }
    66   return false;
    67   return false;
    67 }
    68 }
    68 
    69 
    69 static bool in_native_sample(JavaThread* thread) {
    70 static bool thread_state_in_native(JavaThread* thread) {
    70   switch (thread->thread_state()) {
    71   assert(thread != NULL, "invariant");
    71   case _thread_new:
    72   switch(thread->thread_state()) {
    72   case _thread_uninitialized:
    73     case _thread_new:
    73   case _thread_new_trans:
    74     case _thread_uninitialized:
    74   case _thread_blocked_trans:
    75     case _thread_new_trans:
    75   case _thread_blocked:
    76     case _thread_blocked_trans:
    76   case _thread_in_vm:
    77     case _thread_blocked:
    77   case _thread_in_vm_trans:
    78     case _thread_in_vm:
    78   case _thread_in_Java_trans:
    79     case _thread_in_vm_trans:
    79   case _thread_in_Java:
    80     case _thread_in_Java_trans:
    80   case _thread_in_native_trans:
    81     case _thread_in_Java:
    81     break;
    82     case _thread_in_native_trans:
    82   case _thread_in_native:
    83       break;
    83     return true;
    84     case _thread_in_native:
    84   default:
    85       return true;
    85     ShouldNotReachHere();
    86     default:
    86     break;
    87       ShouldNotReachHere();
       
    88       break;
    87   }
    89   }
    88   return false;
    90   return false;
    89 }
    91 }
    90 
    92 
    91 class JfrThreadSampleClosure {
    93 class JfrThreadSampleClosure {
    92  public:
    94  public:
    93   JfrThreadSampleClosure(EventExecutionSample* events, EventNativeMethodSample* events_native);
    95   JfrThreadSampleClosure(EventExecutionSample* events, EventNativeMethodSample* events_native);
    94   ~JfrThreadSampleClosure() {}
    96   ~JfrThreadSampleClosure() {}
    95   EventExecutionSample* next_event() { return &_events[_added_java++]; }
    97   EventExecutionSample* next_event() { return &_events[_added_java++]; }
    96   EventNativeMethodSample* next_event_native() { return &_events_native[_added_native++]; }
    98   EventNativeMethodSample* next_event_native() { return &_events_native[_added_native++]; }
    97   void commit_events();
    99   void commit_events(JfrSampleType type);
    98   int added() const { return _added_java; }
   100   bool do_sample_thread(JavaThread* thread, JfrStackFrame* frames, u4 max_frames, JfrSampleType type);
    99   JfrSampleType do_sample_thread(JavaThread* thread, JfrStackFrame* frames, u4 max_frames, bool java_sample, bool native_sample);
   101   uint java_entries() { return _added_java; }
   100   int java_entries() { return _added_java; }
   102   uint native_entries() { return _added_native; }
   101   int native_entries() { return _added_native; }
       
   102 
   103 
   103  private:
   104  private:
   104   bool sample_thread_in_java(JavaThread* thread, JfrStackFrame* frames, u4 max_frames);
   105   bool sample_thread_in_java(JavaThread* thread, JfrStackFrame* frames, u4 max_frames);
   105   bool sample_thread_in_native(JavaThread* thread, JfrStackFrame* frames, u4 max_frames);
   106   bool sample_thread_in_native(JavaThread* thread, JfrStackFrame* frames, u4 max_frames);
   106   EventExecutionSample* _events;
   107   EventExecutionSample* _events;
   107   EventNativeMethodSample* _events_native;
   108   EventNativeMethodSample* _events_native;
   108   Thread* _self;
   109   Thread* _self;
   109   int _added_java;
   110   uint _added_java;
   110   int _added_native;
   111   uint _added_native;
   111 };
   112 };
   112 
   113 
   113 class OSThreadSampler : public os::SuspendedThreadTask {
   114 class OSThreadSampler : public os::SuspendedThreadTask {
   114  public:
   115  public:
   115   OSThreadSampler(JavaThread* thread,
   116   OSThreadSampler(JavaThread* thread,
   170 * using a signal handler / __try block. Don't take locks, rely on destructors or
   171 * using a signal handler / __try block. Don't take locks, rely on destructors or
   171 * leave memory (in case of signal / exception) in an inconsistent state. */
   172 * leave memory (in case of signal / exception) in an inconsistent state. */
   172 void OSThreadSampler::protected_task(const os::SuspendedThreadTaskContext& context) {
   173 void OSThreadSampler::protected_task(const os::SuspendedThreadTaskContext& context) {
   173   JavaThread* jth = (JavaThread*)context.thread();
   174   JavaThread* jth = (JavaThread*)context.thread();
   174   // Skip sample if we signaled a thread that moved to other state
   175   // Skip sample if we signaled a thread that moved to other state
   175   if (!in_java_sample(jth)) {
   176   if (!thread_state_in_java(jth)) {
   176     return;
   177     return;
   177   }
   178   }
   178   JfrGetCallTrace trace(true, jth);
   179   JfrGetCallTrace trace(true, jth);
   179   frame topframe;
   180   frame topframe;
   180   if (trace.get_topframe(context.ucontext(), topframe)) {
   181   if (trace.get_topframe(context.ucontext(), topframe)) {
   279   assert(id != 0, "Stacktrace id should not be 0");
   280   assert(id != 0, "Stacktrace id should not be 0");
   280   event->set_stackTrace(id);
   281   event->set_stackTrace(id);
   281   return true;
   282   return true;
   282 }
   283 }
   283 
   284 
   284 void JfrThreadSampleClosure::commit_events() {
   285 static const uint MAX_NR_OF_JAVA_SAMPLES = 5;
   285   for (int i = 0; i < _added_java; ++i) {
   286 static const uint MAX_NR_OF_NATIVE_SAMPLES = 1;
   286     _events[i].commit();
   287 
   287   }
   288 void JfrThreadSampleClosure::commit_events(JfrSampleType type) {
   288   for (int i = 0; i < _added_native; ++i) {
   289   if (JAVA_SAMPLE == type) {
   289     _events_native[i].commit();
   290     assert(_added_java <= MAX_NR_OF_JAVA_SAMPLES, "invariant");
       
   291     for (uint i = 0; i < _added_java; ++i) {
       
   292       _events[i].commit();
       
   293     }
       
   294   } else {
       
   295     assert(NATIVE_SAMPLE == type, "invariant");
       
   296     assert(_added_native <= MAX_NR_OF_NATIVE_SAMPLES, "invariant");
       
   297     for (uint i = 0; i < _added_native; ++i) {
       
   298       _events_native[i].commit();
       
   299     }
   290   }
   300   }
   291 }
   301 }
   292 
   302 
   293 JfrThreadSampleClosure::JfrThreadSampleClosure(EventExecutionSample* events, EventNativeMethodSample* events_native) :
   303 JfrThreadSampleClosure::JfrThreadSampleClosure(EventExecutionSample* events, EventNativeMethodSample* events_native) :
   294   _events(events),
   304   _events(events),
   342     MutexLockerEx ml(JfrThreadSampler::transition_block(), Mutex::_no_safepoint_check_flag);
   352     MutexLockerEx ml(JfrThreadSampler::transition_block(), Mutex::_no_safepoint_check_flag);
   343     JfrThreadSampler::transition_block()->notify_all();
   353     JfrThreadSampler::transition_block()->notify_all();
   344   }
   354   }
   345 }
   355 }
   346 
   356 
   347 JfrSampleType JfrThreadSampleClosure::do_sample_thread(JavaThread* thread, JfrStackFrame* frames, u4 max_frames, bool java_sample, bool native_sample) {
   357 bool JfrThreadSampleClosure::do_sample_thread(JavaThread* thread, JfrStackFrame* frames, u4 max_frames, JfrSampleType type) {
   348   assert(Threads_lock->owned_by_self(), "Holding the thread table lock.");
   358   assert(Threads_lock->owned_by_self(), "Holding the thread table lock.");
   349   if (thread->is_hidden_from_external_view()) {
   359   if (thread->is_hidden_from_external_view() || thread->in_deopt_handler()) {
   350     return NO_SAMPLE;
   360     return false;
   351   }
   361   }
   352   if (thread->in_deopt_handler()) {
   362 
   353     return NO_SAMPLE;
   363   bool ret = false;
   354   }
       
   355   JfrSampleType ret = NO_SAMPLE;
       
   356   thread->set_trace_flag();
   364   thread->set_trace_flag();
   357   if (!UseMembar) {
   365   if (!UseMembar) {
   358     os::serialize_thread_states();
   366     os::serialize_thread_states();
   359   }
   367   }
   360   if (in_java_sample(thread) && java_sample) {
   368   if (JAVA_SAMPLE == type) {
   361     ret = sample_thread_in_java(thread, frames, max_frames) ? JAVA_SAMPLE : NO_SAMPLE;
   369     if (thread_state_in_java(thread)) {
   362   } else if (in_native_sample(thread) && native_sample) {
   370       ret = sample_thread_in_java(thread, frames, max_frames);
   363     ret = sample_thread_in_native(thread, frames, max_frames) ? NATIVE_SAMPLE : NO_SAMPLE;
   371     }
       
   372   } else {
       
   373     assert(NATIVE_SAMPLE == type, "invariant");
       
   374     if (thread_state_in_native(thread)) {
       
   375       ret = sample_thread_in_native(thread, frames, max_frames);
       
   376     }
   364   }
   377   }
   365   clear_transition_block(thread);
   378   clear_transition_block(thread);
   366   return ret;
   379   return ret;
   367 }
   380 }
   368 
   381 
   394     tl->clear_trace_block();
   407     tl->clear_trace_block();
   395   }
   408   }
   396 }
   409 }
   397 
   410 
   398 JavaThread* JfrThreadSampler::next_thread(ThreadsList* t_list, JavaThread* first_sampled, JavaThread* current) {
   411 JavaThread* JfrThreadSampler::next_thread(ThreadsList* t_list, JavaThread* first_sampled, JavaThread* current) {
       
   412   assert(t_list != NULL, "invariant");
   399   assert(Threads_lock->owned_by_self(), "Holding the thread table lock.");
   413   assert(Threads_lock->owned_by_self(), "Holding the thread table lock.");
   400   if (current == NULL) {
   414   assert(_cur_index >= -1 && (uint)_cur_index + 1 <= t_list->length(), "invariant");
       
   415   assert((current == NULL && -1 == _cur_index) || (t_list->find_index_of_JavaThread(current) == _cur_index), "invariant");
       
   416   if ((uint)_cur_index + 1 == t_list->length()) {
       
   417     // wrap
   401     _cur_index = 0;
   418     _cur_index = 0;
   402     return t_list->thread_at(_cur_index);
   419   } else {
   403   }
   420     _cur_index++;
   404 
   421   }
   405   if (_cur_index == -1 || t_list->thread_at(_cur_index) != current) {
   422   assert(_cur_index >= 0 && (uint)_cur_index < t_list->length(), "invariant");
   406     // 'current' is not at '_cur_index' so find it:
   423   JavaThread* const next = t_list->thread_at(_cur_index);
   407     _cur_index = t_list->find_index_of_JavaThread(current);
   424   return next != first_sampled ? next : NULL;
   408     assert(_cur_index != -1, "current JavaThread should be findable.");
       
   409   }
       
   410   _cur_index++;
       
   411 
       
   412   JavaThread* next = NULL;
       
   413   // wrap
       
   414   if ((uint)_cur_index >= t_list->length()) {
       
   415     _cur_index = 0;
       
   416   }
       
   417   next = t_list->thread_at(_cur_index);
       
   418 
       
   419   // sample wrap
       
   420   if (next == first_sampled) {
       
   421     return NULL;
       
   422   }
       
   423   return next;
       
   424 }
   425 }
   425 
   426 
   426 void JfrThreadSampler::start_thread() {
   427 void JfrThreadSampler::start_thread() {
   427   if (os::create_thread(this, os::os_thread)) {
   428   if (os::create_thread(this, os::os_thread)) {
   428     os::start_thread(this);
   429     os::start_thread(this);
   492     }
   493     }
   493   }
   494   }
   494   delete this;
   495   delete this;
   495 }
   496 }
   496 
   497 
   497 static const int MAX_NR_OF_SAMPLES = 5;
       
   498 
   498 
   499 void JfrThreadSampler::task_stacktrace(JfrSampleType type, JavaThread** last_thread) {
   499 void JfrThreadSampler::task_stacktrace(JfrSampleType type, JavaThread** last_thread) {
   500   ResourceMark rm;
   500   ResourceMark rm;
   501   EventExecutionSample samples[MAX_NR_OF_SAMPLES];
   501   EventExecutionSample samples[MAX_NR_OF_JAVA_SAMPLES];
   502   EventNativeMethodSample samples_native[MAX_NR_OF_SAMPLES];
   502   EventNativeMethodSample samples_native[MAX_NR_OF_NATIVE_SAMPLES];
   503   JfrThreadSampleClosure sample_task(samples, samples_native);
   503   JfrThreadSampleClosure sample_task(samples, samples_native);
   504 
   504 
   505   int num_samples = 0;
   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 
   506   {
   509   {
   507     elapsedTimer sample_time;
   510     elapsedTimer sample_time;
   508     sample_time.start();
   511     sample_time.start();
   509 
       
   510     {
   512     {
   511       MonitorLockerEx tlock(Threads_lock, Mutex::_allow_vm_block_flag);
   513       MonitorLockerEx tlock(Threads_lock, Mutex::_allow_vm_block_flag);
   512       ThreadsListHandle tlh;
   514       ThreadsListHandle tlh;
   513       JavaThread* current = tlh.includes(*last_thread) ? *last_thread : NULL;
   515       // Resolve a sample session relative start position index into the thread list array.
   514       JavaThread* start = NULL;
   516       // In cases where the last sampled thread is NULL or not-NULL but stale, find_index() returns -1.
   515 
   517       _cur_index = tlh.list()->find_index_of_JavaThread(*last_thread);
   516       while (num_samples < MAX_NR_OF_SAMPLES) {
   518       JavaThread* current = _cur_index != -1 ? *last_thread : NULL;
       
   519 
       
   520       while (num_sample_attempts < sample_limit) {
   517         current = next_thread(tlh.list(), start, current);
   521         current = next_thread(tlh.list(), start, current);
   518         if (current == NULL) {
   522         if (current == NULL) {
   519           break;
   523           break;
   520         }
   524         }
   521         if (start == NULL) {
   525         if (start == NULL) {
   522           start = current;  // remember thread where we started sampling
   526           start = current;  // remember the thread where we started to attempt sampling
   523         }
   527         }
   524         if (current->is_Compiler_thread()) {
   528         if (current->is_Compiler_thread()) {
   525           continue;
   529           continue;
   526         }
   530         }
   527         *last_thread = current;  // remember thread we last sampled
   531         sample_task.do_sample_thread(current, _frames, _max_frames, type);
   528         JfrSampleType ret = sample_task.do_sample_thread(current, _frames, _max_frames, type == JAVA_SAMPLE, type == NATIVE_SAMPLE);
   532         num_sample_attempts++;
   529         switch (type) {
       
   530         case JAVA_SAMPLE:
       
   531         case NATIVE_SAMPLE:
       
   532           ++num_samples;
       
   533           break;
       
   534         default:
       
   535           break;
       
   536         }
       
   537       }
   533       }
       
   534       *last_thread = current;  // remember the thread we last attempted to sample
   538     }
   535     }
   539     sample_time.stop();
   536     sample_time.stop();
   540     log_trace(jfr)("JFR thread sampling done in %3.7f secs with %d java %d native samples",
   537     log_trace(jfr)("JFR thread sampling done in %3.7f secs with %d java %d native samples",
   541       sample_time.seconds(), sample_task.java_entries(), sample_task.native_entries());
   538                    sample_time.seconds(), sample_task.java_entries(), sample_task.native_entries());
   542   }
   539   }
   543   if (num_samples > 0) {
   540   if (num_sample_attempts > 0) {
   544     sample_task.commit_events();
   541     sample_task.commit_events(type);
   545   }
   542   }
   546 }
   543 }
   547 
   544 
   548 static JfrThreadSampling* _instance = NULL;
   545 static JfrThreadSampling* _instance = NULL;
   549 
   546 
   571     _sampler->disenroll();
   568     _sampler->disenroll();
   572   }
   569   }
   573 }
   570 }
   574 
   571 
   575 static void log(size_t interval_java, size_t interval_native) {
   572 static void log(size_t interval_java, size_t interval_native) {
   576   log_info(jfr)("Updated thread sampler for java: " SIZE_FORMAT"  ms, native " SIZE_FORMAT " ms", interval_java, interval_native);
   573   log_info(jfr)("Updated thread sampler for java: " SIZE_FORMAT "  ms, native " SIZE_FORMAT " ms", interval_java, interval_native);
   577 }
   574 }
   578 
   575 
   579 void JfrThreadSampling::start_sampler(size_t interval_java, size_t interval_native) {
   576 void JfrThreadSampling::start_sampler(size_t interval_java, size_t interval_native) {
   580   assert(_sampler == NULL, "invariant");
   577   assert(_sampler == NULL, "invariant");
   581   log_info(jfr)("Enrolling thread sampler");
   578   log_info(jfr)("Enrolling thread sampler");
   589   size_t interval_native = 0;
   586   size_t interval_native = 0;
   590   if (_sampler != NULL) {
   587   if (_sampler != NULL) {
   591     interval_java = _sampler->get_java_interval();
   588     interval_java = _sampler->get_java_interval();
   592     interval_native = _sampler->get_native_interval();
   589     interval_native = _sampler->get_native_interval();
   593   }
   590   }
   594 
       
   595   if (java_interval) {
   591   if (java_interval) {
   596     interval_java = period;
   592     interval_java = period;
   597   } else {
   593   } else {
   598     interval_native = period;
   594     interval_native = period;
   599   }
   595   }
   600 
       
   601   if (interval_java > 0 || interval_native > 0) {
   596   if (interval_java > 0 || interval_native > 0) {
   602     if (_sampler == NULL) {
   597     if (_sampler == NULL) {
   603       log_info(jfr)("Creating thread sampler for java:%zu ms, native %zu ms", interval_java, interval_native);
   598       log_info(jfr)("Creating thread sampler for java:%zu ms, native %zu ms", interval_java, interval_native);
   604       start_sampler(interval_java, interval_native);
   599       start_sampler(interval_java, interval_native);
   605     } else {
   600     } else {