1 /*
  2 * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
  3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4 *
  5 * This code is free software; you can redistribute it and/or modify it
  6 * under the terms of the GNU General Public License version 2 only, as
  7 * published by the Free Software Foundation.
  8 *
  9 * This code is distributed in the hope that it will be useful, but WITHOUT
 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12 * version 2 for more details (a copy is included in the LICENSE file that
 13 * accompanied this code).
 14 *
 15 * You should have received a copy of the GNU General Public License version
 16 * 2 along with this work; if not, write to the Free Software Foundation,
 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18 *
 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20 * or visit www.oracle.com if you need additional information or have any
 21 * questions.
 22 *
 23 */
 24 
 25 #include "precompiled.hpp"
 26 #include "classfile/javaClasses.inline.hpp"
 27 #include "jfr/recorder/checkpoint/types/jfrThreadState.hpp"
 28 #include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"
 29 #include "jfr/support/jfrThreadLocal.hpp"
 30 #include "jvmtifiles/jvmti.h"
 31 #include "runtime/osThread.hpp"
 32 #include "runtime/thread.hpp"
 33 
 34 struct jvmti_thread_state {
 35   u8 id;
 36   const char* description;
 37 };
 38 
 39 static jvmti_thread_state states[] = {
 40   {
 41     JVMTI_JAVA_LANG_THREAD_STATE_NEW,
 42     "STATE_NEW"
 43   },
 44   {
 45     JVMTI_THREAD_STATE_TERMINATED,
 46     "STATE_TERMINATED"
 47   },
 48   {
 49     JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE,
 50     "STATE_RUNNABLE"
 51   },
 52   {
 53     (JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT | JVMTI_THREAD_STATE_SLEEPING),
 54     "STATE_SLEEPING"
 55   },
 56   {
 57     (JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY | JVMTI_THREAD_STATE_IN_OBJECT_WAIT),
 58     "STATE_IN_OBJECT_WAIT"
 59   },
 60   {
 61     (JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT | JVMTI_THREAD_STATE_IN_OBJECT_WAIT),
 62     "STATE_IN_OBJECT_WAIT_TIMED"
 63   },
 64   {
 65     (JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY | JVMTI_THREAD_STATE_PARKED),
 66     "STATE_PARKED"
 67   },
 68   {
 69     (JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT | JVMTI_THREAD_STATE_PARKED),
 70     "STATE_PARKED_TIMED"
 71   },
 72   {
 73     JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED,
 74     "STATE_BLOCKED_ON_MONITOR_ENTER"
 75   }
 76 };
 77 
 78 void JfrThreadState::serialize(JfrCheckpointWriter& writer) {
 79   const u4 number_of_states = sizeof(states) / sizeof(jvmti_thread_state);
 80   writer.write_count(number_of_states);
 81   for (u4 i = 0; i < number_of_states; ++i) {
 82     writer.write_key(states[i].id);
 83     writer.write(states[i].description);
 84   }
 85 }
 86 
 87 traceid JfrThreadId::id(const Thread* t, oop vthread) {
 88   assert(t != NULL, "invariant");
 89   if (!t->is_Java_thread()) {
 90     return os_id(t);
 91   }
 92   if (vthread != NULL) {
 93     return java_lang_Thread::thread_id(vthread);
 94   }
 95   const oop thread_obj = JavaThread::cast(t)->threadObj();
 96   return thread_obj != NULL ? java_lang_Thread::thread_id(thread_obj) : 0;
 97 }
 98 
 99 traceid JfrThreadId::os_id(const Thread* t) {
100   assert(t != NULL, "invariant");
101   const OSThread* const os_thread = t->osthread();
102   return os_thread != NULL ? os_thread->thread_id() : 0;
103 }
104 
105 traceid JfrThreadId::jfr_id(const Thread* t, traceid tid) {
106   assert(t != NULL, "invariant");
107   return tid != 0 ? tid : JfrThreadLocal::vm_thread_id(t);
108 }
109 
110 // caller needs ResourceMark
111 const char* get_java_thread_name(const JavaThread* jt, oop vthread) {
112   assert(jt != NULL, "invariant");
113   const char* name_str = "<no-name - thread name unresolved>";
114   oop thread_obj = vthread != NULL ? vthread : jt->threadObj();
115   if (thread_obj == NULL) {
116     if (jt->is_attaching_via_jni()) {
117       name_str = "<no-name - thread is attaching>";
118     }
119   } else {
120     const oop name = java_lang_Thread::name(thread_obj);
121     if (name != NULL) {
122       name_str = java_lang_String::as_utf8_string(name);
123     }
124   }
125   assert(name_str != NULL, "unexpected NULL thread name");
126   return name_str;
127 }
128 
129 const char* JfrThreadName::name(const Thread* t, oop vthread) {
130   assert(t != NULL, "invariant");
131   return t->is_Java_thread() ? get_java_thread_name(JavaThread::cast(t), vthread) : t->name();
132 }