< prev index next >

src/hotspot/share/prims/jvmtiExport.cpp

Print this page
rev 47674 : Port 09.17.Thread_SMR_logging_update from JDK9 to JDK10
rev 47676 : eosterlund, stefank CR - refactor code into threadSMR.cpp and threadSMR.hpp
rev 47679 : stefank, coleenp CR - refactor most JavaThreadIterator usage to use JavaThreadIteratorWithHandle.

@@ -51,10 +51,11 @@
 #include "runtime/javaCalls.hpp"
 #include "runtime/objectMonitor.hpp"
 #include "runtime/objectMonitor.inline.hpp"
 #include "runtime/os.inline.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.hpp"
 #include "runtime/vframe.hpp"
 #include "services/serviceUtil.hpp"
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
 #include "gc/parallel/psMarkSweep.hpp"

@@ -719,10 +720,112 @@
     MutexLocker mu(JvmtiThreadState_lock);
     return JvmtiEnvBase::get_all_native_method_prefixes(count_ptr);
   }
 }
 
+// Convert an external thread reference to a JavaThread found on the
+// specified ThreadsList. The ThreadsListHandle in the caller "protects"
+// the returned JavaThread *.
+//
+// If thread_oop_p is not NULL, then the caller wants to use the oop
+// after this call so the oop is returned. On success, *jt_pp is set
+// to the converted JavaThread * and JVMTI_ERROR_NONE is returned.
+// On error, returns various JVMTI_ERROR_* values.
+//
+jvmtiError
+JvmtiExport::cv_external_thread_to_JavaThread(ThreadsList * t_list,
+                                              jthread thread,
+                                              JavaThread ** jt_pp,
+                                              oop * thread_oop_p) {
+  assert(t_list != NULL, "must have a ThreadsList");
+  assert(jt_pp != NULL, "must have a return JavaThread pointer");
+  // thread_oop_p is optional so no assert()
+
+  oop thread_oop = JNIHandles::resolve_external_guard(thread);
+  if (thread_oop == NULL) {
+    // NULL jthread, GC'ed jthread or a bad JNI handle.
+    return JVMTI_ERROR_INVALID_THREAD;
+  }
+  // Looks like an oop at this point.
+
+  if (!thread_oop->is_a(SystemDictionary::Thread_klass())) {
+    // The oop is not a java.lang.Thread.
+    return JVMTI_ERROR_INVALID_THREAD;
+  }
+  // Looks like a java.lang.Thread oop at this point.
+
+  if (thread_oop_p != NULL) {
+    // Return the oop to the caller; the caller may still want
+    // the oop even if this function returns an error.
+    *thread_oop_p = thread_oop;
+  }
+
+  JavaThread * java_thread = java_lang_Thread::thread(thread_oop);
+  if (java_thread == NULL) {
+    // The java.lang.Thread does not contain a JavaThread * so it has
+    // not yet run or it has died.
+    return JVMTI_ERROR_THREAD_NOT_ALIVE;
+  }
+  // Looks like a live JavaThread at this point.
+
+  // We do not check the EnableThreadSMRExtraValidityChecks option
+  // for this includes() call because JVM/TI's spec is tighter.
+  if (!t_list->includes(java_thread)) {
+    // Not on the JavaThreads list so it is not alive.
+    return JVMTI_ERROR_THREAD_NOT_ALIVE;
+  }
+
+  // Return a live JavaThread that is "protected" by the
+  // ThreadsListHandle in the caller.
+  *jt_pp = java_thread;
+
+  return JVMTI_ERROR_NONE;
+}
+
+// Convert an oop to a JavaThread found on the specified ThreadsList.
+// The ThreadsListHandle in the caller "protects" the returned
+// JavaThread *.
+//
+// On success, *jt_pp is set to the converted JavaThread * and
+// JVMTI_ERROR_NONE is returned. On error, returns various
+// JVMTI_ERROR_* values.
+//
+jvmtiError
+JvmtiExport::cv_oop_to_JavaThread(ThreadsList * t_list, oop thread_oop,
+                                  JavaThread ** jt_pp) {
+  assert(t_list != NULL, "must have a ThreadsList");
+  assert(thread_oop != NULL, "must have an oop");
+  assert(jt_pp != NULL, "must have a return JavaThread pointer");
+
+  if (!thread_oop->is_a(SystemDictionary::Thread_klass())) {
+    // The oop is not a java.lang.Thread.
+    return JVMTI_ERROR_INVALID_THREAD;
+  }
+  // Looks like a java.lang.Thread oop at this point.
+
+  JavaThread * java_thread = java_lang_Thread::thread(thread_oop);
+  if (java_thread == NULL) {
+    // The java.lang.Thread does not contain a JavaThread * so it has
+    // not yet run or it has died.
+    return JVMTI_ERROR_THREAD_NOT_ALIVE;
+  }
+  // Looks like a live JavaThread at this point.
+
+  // We do not check the EnableThreadSMRExtraValidityChecks option
+  // for this includes() call because JVM/TI's spec is tighter.
+  if (!t_list->includes(java_thread)) {
+    // Not on the JavaThreads list so it is not alive.
+    return JVMTI_ERROR_THREAD_NOT_ALIVE;
+  }
+
+  // Return a live JavaThread that is "protected" by the
+  // ThreadsListHandle in the caller.
+  *jt_pp = java_thread;
+
+  return JVMTI_ERROR_NONE;
+}
+
 class JvmtiClassFileLoadHookPoster : public StackObj {
  private:
   Symbol*            _h_name;
   Handle               _class_loader;
   Handle               _h_protection_domain;

@@ -2683,12 +2786,11 @@
   // no-op if jvmti not enabled
   if (!JvmtiEnv::environments_might_exist()) {
     return;
   }
 
-  // Runs at safepoint. So no need to acquire Threads_lock.
-  for (JavaThread *jthr = Threads::first(); jthr != NULL; jthr = jthr->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jthr = jtiwh.next(); ) {
     JvmtiThreadState *state = jthr->jvmti_thread_state();
     if (state != NULL) {
       JvmtiVMObjectAllocEventCollector *collector;
       collector = state->get_vm_object_alloc_event_collector();
       while (collector != NULL) {
< prev index next >