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) {
 88   assert(t != NULL, "invariant");
 89   if (!t->is_Java_thread()) {
 90     return os_id(t);
 91   }
 92   const oop thread_obj = JavaThread::cast(t)->threadObj();
 93   return thread_obj != NULL ? java_lang_Thread::thread_id(thread_obj) : 0;
 94 }
 95 
 96 traceid JfrThreadId::os_id(const Thread* t) {
 97   assert(t != NULL, "invariant");
 98   const OSThread* const os_thread = t->osthread();
 99   return os_thread != NULL ? os_thread->thread_id() : 0;
100 }
101 
102 traceid JfrThreadId::jfr_id(const Thread* t) {
103   assert(t != NULL, "invariant");
104   return t->jfr_thread_local()->thread_id();
105 }
106 
107 // caller needs ResourceMark
108 const char* get_java_thread_name(const JavaThread* jt) {
109   assert(jt != NULL, "invariant");
110   const char* name_str = "<no-name - thread name unresolved>";
111   const oop thread_obj = jt->threadObj();
112   if (thread_obj != NULL) {
113     const oop name = java_lang_Thread::name(thread_obj);
114     if (name != NULL) {
115       name_str = java_lang_String::as_utf8_string(name);
116     }
117   } else if (jt->is_attaching_via_jni()) {
118     name_str = "<no-name - thread is attaching>";
119   }
120   assert(name_str != NULL, "unexpected NULL thread name");
121   return name_str;
122 }
123 
124 const char* JfrThreadName::name(const Thread* t) {
125   assert(t != NULL, "invariant");
126   return t->is_Java_thread() ? get_java_thread_name(JavaThread::cast(t)) : t->name();
127 }