< prev index next >

src/hotspot/share/jfr/support/jfrThreadLocal.cpp

Print this page
@@ -30,11 +30,13 @@
  #include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp"
  #include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp"
  #include "jfr/recorder/jfrRecorder.hpp"
  #include "jfr/recorder/service/jfrOptionSet.hpp"
  #include "jfr/recorder/storage/jfrStorage.hpp"
+ #include "jfr/support/jfrJavaThread.hpp"
  #include "jfr/support/jfrThreadLocal.hpp"
+ #include "jfr/utilities/jfrSpinlockHelper.hpp"
  #include "memory/allocation.inline.hpp"
  #include "runtime/os.hpp"
  #include "runtime/thread.inline.hpp"
  #include "utilities/sizes.hpp"
  

@@ -43,21 +45,25 @@
    _java_buffer(NULL),
    _native_buffer(NULL),
    _shelved_buffer(NULL),
    _load_barrier_buffer_epoch_0(NULL),
    _load_barrier_buffer_epoch_1(NULL),
+   _checkpoint_buffer_epoch_0(NULL),
+   _checkpoint_buffer_epoch_1(NULL),
    _stackframes(NULL),
-   _trace_id(JfrTraceId::assign_thread_id()),
    _thread(),
+   _thread_id(0),
+   _thread_id_alias(max_julong),
    _data_lost(0),
    _stack_trace_id(max_julong),
    _user_time(0),
    _cpu_time(0),
    _wallclock_time(os::javaTimeNanos()),
    _stack_trace_hash(0),
    _stackdepth(0),
    _entering_suspend_flag(0),
+   _critical_section(0),
    _excluded(false),
    _dead(false) {
    Thread* thread = Thread::current_or_null();
    _parent_trace_id = thread != NULL ? thread->jfr_thread_local()->trace_id() : (traceid)0;
  }

@@ -78,44 +84,39 @@
  
  const JfrBlobHandle& JfrThreadLocal::thread_blob() const {
    return _thread;
  }
  
- static void send_java_thread_start_event(JavaThread* jt) {
-   EventThreadStart event;
-   event.set_thread(jt->jfr_thread_local()->thread_id());
-   event.set_parentThread(jt->jfr_thread_local()->parent_thread_id());
-   event.commit();
+ static void send_java_thread_start_event(JavaThread* jt, jobject vthread) {
+   assert(jt != NULL, "invariant");
+   assert(Thread::current() == jt, "invariant");
+   if (!JfrJavaSupport::on_thread_start(jt, vthread)) {
+     // thread is excluded
+     return;
+   }
+   if (JfrRecorder::is_recording()) {
+     EventThreadStart event;
+     event.set_thread(vthread != NULL ? JfrThreadLocal::virtual_thread_id(jt, JfrJavaSupport::resolve_non_null(vthread)) : JfrThreadLocal::vm_thread_id(jt));
+     event.set_parentThread(jt->jfr_thread_local()->parent_thread_id());
+     event.commit();
+   }
  }
  
  void JfrThreadLocal::on_start(Thread* t) {
-   assert(t != NULL, "invariant");
-   assert(Thread::current() == t, "invariant");
-   JfrJavaSupport::on_thread_start(t);
    if (JfrRecorder::is_recording()) {
-     JfrCheckpointManager::write_thread_checkpoint(t);
-     if (!t->jfr_thread_local()->is_excluded()) {
-       if (t->is_Java_thread()) {
-         send_java_thread_start_event(JavaThread::cast(t));
-       }
+     JfrCheckpointManager::write_checkpoint(t);
+     if (t->is_Java_thread()) {
+       send_java_thread_start_event(JavaThread::cast(t), NULL);
      }
    }
    if (t->jfr_thread_local()->has_cached_stack_trace()) {
      t->jfr_thread_local()->clear_cached_stack_trace();
    }
  }
  
- static void send_java_thread_end_events(traceid id, JavaThread* jt) {
-   assert(jt != NULL, "invariant");
-   assert(Thread::current() == jt, "invariant");
-   assert(jt->jfr_thread_local()->trace_id() == id, "invariant");
-   if (JfrRecorder::is_recording()) {
-     EventThreadEnd event;
-     event.set_thread(id);
-     event.commit();
-     JfrThreadCPULoadEvent::send_event_for_thread(jt);
-   }
+ void JfrThreadLocal::on_vthread_start(JavaThread* jt, jobject vthread) {
+   send_java_thread_start_event(jt, vthread);
  }
  
  void JfrThreadLocal::release(Thread* t) {
    if (has_java_event_writer()) {
      assert(t->is_Java_thread(), "invariant");

@@ -140,10 +141,18 @@
    }
    if (_load_barrier_buffer_epoch_1 != NULL) {
      _load_barrier_buffer_epoch_1->set_retired();
      _load_barrier_buffer_epoch_1 = NULL;
    }
+   if (_checkpoint_buffer_epoch_0 != NULL) {
+     _checkpoint_buffer_epoch_0->set_retired();
+     _checkpoint_buffer_epoch_0 = NULL;
+   }
+   if (_checkpoint_buffer_epoch_1 != NULL) {
+     _checkpoint_buffer_epoch_1->set_retired();
+     _checkpoint_buffer_epoch_1 = NULL;
+   }
  }
  
  void JfrThreadLocal::release(JfrThreadLocal* tl, Thread* t) {
    assert(tl != NULL, "invariant");
    assert(t != NULL, "invariant");

@@ -152,24 +161,42 @@
    assert(tl->shelved_buffer() == NULL, "invariant");
    tl->_dead = true;
    tl->release(t);
  }
  
+ static void send_java_thread_end_event(JavaThread* jt, traceid tid) {
+   assert(jt != NULL, "invariant");
+   assert(Thread::current() == jt, "invariant");
+   assert(tid != 0, "invariant");
+   if (JfrRecorder::is_recording()) {
+     EventThreadEnd event;
+     event.set_thread(tid);
+     event.commit();
+     ObjectSampleCheckpoint::on_thread_exit(tid);
+   }
+ }
+ 
  void JfrThreadLocal::on_exit(Thread* t) {
    assert(t != NULL, "invariant");
    JfrThreadLocal * const tl = t->jfr_thread_local();
    assert(!tl->is_dead(), "invariant");
-   if (JfrRecorder::is_recording()) {
-     if (t->is_Java_thread()) {
-       JavaThread* const jt = JavaThread::cast(t);
-       ObjectSampleCheckpoint::on_thread_exit(jt);
-       send_java_thread_end_events(tl->thread_id(), jt);
-     }
+   if (t->is_Java_thread()) {
+     JavaThread* const jt = JavaThread::cast(t);
+     send_java_thread_end_event(jt, JfrThreadLocal::thread_id(jt));
+     JfrThreadCPULoadEvent::send_event_for_thread(jt);
    }
    release(tl, Thread::current()); // because it could be that Thread::current() != t
  }
  
+ void JfrThreadLocal::on_vthread_exit(JavaThread* jt, jobject vthread) {
+   assert(vthread != NULL, "invariant");
+   const traceid id = JfrJavaThread::virtual_thread_id(JfrJavaSupport::resolve_non_null(vthread), jt);
+   JfrThreadLocal::impersonate(jt, id);
+   send_java_thread_end_event(jt, id);
+   JfrThreadLocal::stop_impersonating(jt);
+ }
+ 
  static JfrBuffer* acquire_buffer(bool excluded) {
    JfrBuffer* const buffer = JfrStorage::acquire_thread_local(Thread::current());
    if (buffer != NULL && excluded) {
      buffer->set_excluded();
    }

@@ -194,11 +221,11 @@
    _stackframes = NEW_C_HEAP_ARRAY(JfrStackFrame, stackdepth(), mtTracing);
    return _stackframes;
  }
  
  ByteSize JfrThreadLocal::trace_id_offset() {
-   return in_ByteSize(offset_of(JfrThreadLocal, _trace_id));
+   return in_ByteSize(offset_of(JfrThreadLocal, _thread_id));
  }
  
  ByteSize JfrThreadLocal::java_event_writer_offset() {
    return in_ByteSize(offset_of(JfrThreadLocal, _java_event_writer));
  }

@@ -216,5 +243,59 @@
  }
  
  u4 JfrThreadLocal::stackdepth() const {
    return _stackdepth != 0 ? _stackdepth : (u4)JfrOptionSet::stackdepth();
  }
+ 
+ bool JfrThreadLocal::is_impersonating(const Thread* t) {
+   return t->jfr_thread_local()->_thread_id_alias != max_julong;
+ }
+ 
+ void JfrThreadLocal::impersonate(const Thread* t, traceid other_thread_id) {
+   assert(t != NULL, "invariant");
+   assert(other_thread_id != 0, "invariant");
+   JfrThreadLocal* const tl = t->jfr_thread_local();
+   tl->_thread_id_alias = other_thread_id;
+ }
+ 
+ void JfrThreadLocal::stop_impersonating(const Thread* t) {
+   assert(t != NULL, "invariant");
+   JfrThreadLocal* const tl = t->jfr_thread_local();
+   if (is_impersonating(t)) {
+     tl->_thread_id_alias = max_julong;
+   }
+   assert(!is_impersonating(t), "invariant");
+ }
+ 
+ traceid JfrThreadLocal::thread_id(const Thread* t, bool* is_virtual) {
+   assert(t != NULL, "invariant");
+   if (is_impersonating(t)) {
+     return t->jfr_thread_local()->_thread_id_alias;
+   }
+   return t->is_Java_thread() ? JfrJavaThread::contextual_thread_id(JavaThread::cast(t), is_virtual) : vm_thread_id(t);
+ }
+ 
+ traceid JfrThreadLocal::virtual_thread_id(const Thread* t, oop vthread) {
+   assert(t != NULL, "invariant");
+   assert(vthread != NULL, "invariant");
+   return JfrJavaThread::virtual_thread_id(vthread, (JavaThread*)t);
+ }
+ 
+ traceid JfrThreadLocal::assign_thread_id(const Thread* t) {
+   assert(t != NULL, "invariant");
+   JfrThreadLocal* const tl = t->jfr_thread_local();
+   JfrSpinlockHelper spinlock(&tl->_critical_section);
+   traceid tid = tl->_thread_id;
+   if (tid == 0) {
+     tid = t->is_Java_thread() ? JfrJavaThread::java_thread_id((JavaThread*)t) :
+                                 JfrTraceId::assign_thread_id();
+     tl->_thread_id = tid;
+   }
+   assert(tid != 0, "invariant");
+   return tid;
+ }
+ 
+ traceid JfrThreadLocal::vm_thread_id(const Thread* t) {
+   assert(t != NULL, "invariant");
+   JfrThreadLocal* const tl = t->jfr_thread_local();
+   return tl->_thread_id != 0 ? tl->_thread_id : JfrThreadLocal::assign_thread_id(t);
+ }
< prev index next >