< prev index next >

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

Print this page
rev 8911 : [jfr] enable thread sampling

@@ -319,11 +319,12 @@
   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);
+  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,11 +343,11 @@
 };
 
 Monitor* JfrThreadSampler::_transition_block_lock = new Monitor(Mutex::leaf, "Trace block", true);
 
 static void clear_transition_block(JavaThread* jt) {
-//  jt->clear_trace_flag();
+  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,11 +358,11 @@
   if (thread->is_hidden_from_external_view() || thread->in_deopt_handler()) {
     return false;
   }
 
   bool ret = false;
-//  thread->set_trace_flag();
+  thread->set_trace_flag();
   if (!UseMembar) {
     os::serialize_thread_states();
   }
   if (JAVA_SAMPLE == type) {
     if (thread_state_in_java(thread)) {

@@ -396,41 +397,65 @@
 
 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();
+    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(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;
-//}
+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() {
-  // 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");
-//  }
+  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");

@@ -507,32 +532,37 @@
 
   {
     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
+      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 >