ti_thread.cc revision 1d8a9741d2979d09a21942fbf9107d212ce2511b
1af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe/* Copyright (C) 2017 The Android Open Source Project
2af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe *
4af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * This file implements interfaces from the file jvmti.h. This implementation
5af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * is licensed under the same terms as the file jvmti.h.  The
6af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * copyright and license information for the file jvmti.h follows.
7af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe *
8af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
9af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe *
11af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * This code is free software; you can redistribute it and/or modify it
12af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * under the terms of the GNU General Public License version 2 only, as
13af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * published by the Free Software Foundation.  Oracle designates this
14af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * particular file as subject to the "Classpath" exception as provided
15af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * by Oracle in the LICENSE file that accompanied this code.
16af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe *
17af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * This code is distributed in the hope that it will be useful, but WITHOUT
18af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * version 2 for more details (a copy is included in the LICENSE file that
21af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * accompanied this code).
22af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe *
23af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * You should have received a copy of the GNU General Public License version
24af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * 2 along with this work; if not, write to the Free Software Foundation,
25af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe *
27af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
28af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * or visit www.oracle.com if you need additional information or have any
29af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe * questions.
30af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe */
31af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
32af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe#include "ti_thread.h"
33af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
34eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe#include "android-base/strings.h"
35a1d2f957a21319d1110bebb9a52f46fd1c67ffafAndreas Gampe#include "art_field-inl.h"
36af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe#include "art_jvmti.h"
37af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe#include "base/logging.h"
38af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe#include "base/mutex.h"
39eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe#include "events-inl.h"
40f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe#include "gc/system_weak.h"
41f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe#include "gc_root-inl.h"
42af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe#include "jni_internal.h"
43af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe#include "mirror/class.h"
44af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe#include "mirror/object-inl.h"
45af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe#include "mirror/string.h"
46e431e2758d62cf56f7f347f5a8c9d79e41b6dcd7Steven Moreland#include "nativehelper/ScopedLocalRef.h"
47af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe#include "obj_ptr.h"
48f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe#include "runtime.h"
49eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe#include "runtime_callbacks.h"
50af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe#include "scoped_thread_state_change-inl.h"
51b486a98aadc95d80548953410cf23edba62259faAndreas Gampe#include "thread-current-inl.h"
528580744607a963d408956c3eb712b0e070c139b0Andreas Gampe#include "thread_list.h"
53e431e2758d62cf56f7f347f5a8c9d79e41b6dcd7Steven Moreland#include "ti_phase.h"
54af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe#include "well_known_classes.h"
55af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
56af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampenamespace openjdkjvmti {
57af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
58db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampeart::ArtField* ThreadUtil::context_class_loader_ = nullptr;
59db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampe
601d8a9741d2979d09a21942fbf9107d212ce2511bAlex Lightstruct ThreadCallback : public art::ThreadLifecycleCallback {
61eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe  jthread GetThreadObject(art::Thread* self) REQUIRES_SHARED(art::Locks::mutator_lock_) {
62eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe    if (self->GetPeer() == nullptr) {
63eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe      return nullptr;
64eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe    }
65eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe    return self->GetJniEnv()->AddLocalReference<jthread>(self->GetPeer());
66eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe  }
671d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light
68983c175aa134c7f6794a4b3407d7e99536b1f7f1Andreas Gampe  template <ArtJvmtiEvent kEvent>
69983c175aa134c7f6794a4b3407d7e99536b1f7f1Andreas Gampe  void Post(art::Thread* self) REQUIRES_SHARED(art::Locks::mutator_lock_) {
70eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe    DCHECK_EQ(self, art::Thread::Current());
71eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe    ScopedLocalRef<jthread> thread(self->GetJniEnv(), GetThreadObject(self));
72e6377461540c1159e94cb45c9ade347e8e6bb52bAndreas Gampe    art::ScopedThreadSuspension sts(self, art::ThreadState::kNative);
73983c175aa134c7f6794a4b3407d7e99536b1f7f1Andreas Gampe    event_handler->DispatchEvent<kEvent>(self,
74983c175aa134c7f6794a4b3407d7e99536b1f7f1Andreas Gampe                                         reinterpret_cast<JNIEnv*>(self->GetJniEnv()),
75983c175aa134c7f6794a4b3407d7e99536b1f7f1Andreas Gampe                                         thread.get());
76eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe  }
77eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe
78eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe  void ThreadStart(art::Thread* self) OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
79eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe    if (!started) {
80eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe      // Runtime isn't started. We only expect at most the signal handler or JIT threads to be
81eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe      // started here.
82eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe      if (art::kIsDebugBuild) {
83eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe        std::string name;
84eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe        self->GetThreadName(name);
855bd09549b443659ddd81768c811dcb5c6850775cAlex Light        if (name != "JDWP" &&
865bd09549b443659ddd81768c811dcb5c6850775cAlex Light            name != "Signal Catcher" &&
875bd09549b443659ddd81768c811dcb5c6850775cAlex Light            !android::base::StartsWith(name, "Jit thread pool")) {
88eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe          LOG(FATAL) << "Unexpected thread before start: " << name;
89eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe        }
90eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe      }
91eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe      return;
92eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe    }
93983c175aa134c7f6794a4b3407d7e99536b1f7f1Andreas Gampe    Post<ArtJvmtiEvent::kThreadStart>(self);
94eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe  }
95eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe
96eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe  void ThreadDeath(art::Thread* self) OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
97983c175aa134c7f6794a4b3407d7e99536b1f7f1Andreas Gampe    Post<ArtJvmtiEvent::kThreadEnd>(self);
98eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe  }
99eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe
100eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe  EventHandler* event_handler = nullptr;
101eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe  bool started = false;
102eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe};
103eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe
104eafaf57557939bcabeb7a7388fb4951e74661a53Andreas GampeThreadCallback gThreadCallback;
105eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe
106eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampevoid ThreadUtil::Register(EventHandler* handler) {
107eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe  art::Runtime* runtime = art::Runtime::Current();
108eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe
109eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe  gThreadCallback.started = runtime->IsStarted();
110eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe  gThreadCallback.event_handler = handler;
111eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe
112eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe  art::ScopedThreadStateChange stsc(art::Thread::Current(),
113eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe                                    art::ThreadState::kWaitingForDebuggerToAttach);
114eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe  art::ScopedSuspendAll ssa("Add thread callback");
115eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe  runtime->GetRuntimeCallbacks()->AddThreadLifecycleCallback(&gThreadCallback);
1161d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light}
1171d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light
1181d8a9741d2979d09a21942fbf9107d212ce2511bAlex Lightvoid ThreadUtil::VMInitEventSent() {
1191d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light  // We should have already started.
1201d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light  DCHECK(gThreadCallback.started);
1211d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light  // We moved to VMInit. Report the main thread as started (it was attached early, and must not be
1221d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light  // reported until Init.
1231d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light  gThreadCallback.Post<ArtJvmtiEvent::kThreadStart>(art::Thread::Current());
124eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe}
125eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe
126db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampevoid ThreadUtil::CacheData() {
1271d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light  // We must have started since it is now safe to cache our data;
1281d8a9741d2979d09a21942fbf9107d212ce2511bAlex Light  gThreadCallback.started = true;
129db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampe  art::ScopedObjectAccess soa(art::Thread::Current());
130db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampe  art::ObjPtr<art::mirror::Class> thread_class =
131db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampe      soa.Decode<art::mirror::Class>(art::WellKnownClasses::java_lang_Thread);
132db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampe  CHECK(thread_class != nullptr);
133db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampe  context_class_loader_ = thread_class->FindDeclaredInstanceField("contextClassLoader",
134db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampe                                                                  "Ljava/lang/ClassLoader;");
135db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampe  CHECK(context_class_loader_ != nullptr);
136db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampe}
137db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampe
138eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampevoid ThreadUtil::Unregister() {
139eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe  art::ScopedThreadStateChange stsc(art::Thread::Current(),
140eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe                                    art::ThreadState::kWaitingForDebuggerToAttach);
141eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe  art::ScopedSuspendAll ssa("Remove thread callback");
142eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe  art::Runtime* runtime = art::Runtime::Current();
143eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe  runtime->GetRuntimeCallbacks()->RemoveThreadLifecycleCallback(&gThreadCallback);
144eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe}
145eafaf57557939bcabeb7a7388fb4951e74661a53Andreas Gampe
146af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas GampejvmtiError ThreadUtil::GetCurrentThread(jvmtiEnv* env ATTRIBUTE_UNUSED, jthread* thread_ptr) {
147af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe  art::Thread* self = art::Thread::Current();
148af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
149af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe  art::ScopedObjectAccess soa(self);
150af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
151af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe  jthread thread_peer;
152af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe  if (self->IsStillStarting()) {
153af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    thread_peer = nullptr;
154af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe  } else {
155af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    thread_peer = soa.AddLocalReference<jthread>(self->GetPeer());
156af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe  }
157af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
158af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe  *thread_ptr = thread_peer;
159af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe  return ERR(NONE);
160af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe}
161af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
162af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe// Get the native thread. The spec says a null object denotes the current thread.
163bebd7bd02a073056851cc1b0942c53ce0d2ee206Alex Lightart::Thread* ThreadUtil::GetNativeThread(jthread thread,
164bebd7bd02a073056851cc1b0942c53ce0d2ee206Alex Light                                         const art::ScopedObjectAccessAlreadyRunnable& soa) {
165af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe  if (thread == nullptr) {
166af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    return art::Thread::Current();
167af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe  }
168af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
169af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe  return art::Thread::FromManagedThread(soa, thread);
170af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe}
171af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
172af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas GampejvmtiError ThreadUtil::GetThreadInfo(jvmtiEnv* env, jthread thread, jvmtiThreadInfo* info_ptr) {
173af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe  if (info_ptr == nullptr) {
174af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    return ERR(NULL_POINTER);
175af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe  }
176db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampe  if (!PhaseUtil::IsLivePhase()) {
177db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampe    return JVMTI_ERROR_WRONG_PHASE;
178db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampe  }
179af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
1803ae82531b336b195a78c864c28af1448a74af633Alex Light  art::Thread* self = art::Thread::Current();
1813ae82531b336b195a78c864c28af1448a74af633Alex Light  art::ScopedObjectAccess soa(self);
1823ae82531b336b195a78c864c28af1448a74af633Alex Light  art::MutexLock mu(self, *art::Locks::thread_list_lock_);
183af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
1843ae82531b336b195a78c864c28af1448a74af633Alex Light  art::Thread* target = GetNativeThread(thread, soa);
1853ae82531b336b195a78c864c28af1448a74af633Alex Light  if (target == nullptr && thread == nullptr) {
186af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    return ERR(INVALID_THREAD);
187af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe  }
188af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
1895471141cf6631b4162b222540b531b9f493d3cb2Andreas Gampe  JvmtiUniquePtr<char[]> name_uptr;
1903ae82531b336b195a78c864c28af1448a74af633Alex Light  if (target != nullptr) {
191af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    // Have a native thread object, this thread is alive.
192af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    std::string name;
1933ae82531b336b195a78c864c28af1448a74af633Alex Light    target->GetThreadName(name);
1945471141cf6631b4162b222540b531b9f493d3cb2Andreas Gampe    jvmtiError name_result;
1955471141cf6631b4162b222540b531b9f493d3cb2Andreas Gampe    name_uptr = CopyString(env, name.c_str(), &name_result);
1965471141cf6631b4162b222540b531b9f493d3cb2Andreas Gampe    if (name_uptr == nullptr) {
197af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      return name_result;
198af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    }
1995471141cf6631b4162b222540b531b9f493d3cb2Andreas Gampe    info_ptr->name = name_uptr.get();
200af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
2013ae82531b336b195a78c864c28af1448a74af633Alex Light    info_ptr->priority = target->GetNativePriority();
202af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
2033ae82531b336b195a78c864c28af1448a74af633Alex Light    info_ptr->is_daemon = target->IsDaemon();
204af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
2053ae82531b336b195a78c864c28af1448a74af633Alex Light    art::ObjPtr<art::mirror::Object> peer = target->GetPeerFromOtherThread();
206af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
207af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    // ThreadGroup.
208af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    if (peer != nullptr) {
209af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_group);
210af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      CHECK(f != nullptr);
211af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      art::ObjPtr<art::mirror::Object> group = f->GetObject(peer);
212af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      info_ptr->thread_group = group == nullptr
213af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe                                   ? nullptr
214af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe                                   : soa.AddLocalReference<jthreadGroup>(group);
215af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    } else {
216af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      info_ptr->thread_group = nullptr;
217af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    }
218af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
219af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    // Context classloader.
220db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampe    DCHECK(context_class_loader_ != nullptr);
221db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampe    art::ObjPtr<art::mirror::Object> ccl = peer != nullptr
222db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampe        ? context_class_loader_->GetObject(peer)
223db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampe        : nullptr;
224af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    info_ptr->context_class_loader = ccl == nullptr
225af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe                                         ? nullptr
226af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe                                         : soa.AddLocalReference<jobject>(ccl);
227af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe  } else {
228af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    // Only the peer. This thread has either not been started, or is dead. Read things from
229af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    // the Java side.
230af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    art::ObjPtr<art::mirror::Object> peer = soa.Decode<art::mirror::Object>(thread);
231af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
232af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    // Name.
233af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    {
234af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_name);
235af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      CHECK(f != nullptr);
236af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      art::ObjPtr<art::mirror::Object> name = f->GetObject(peer);
237af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      std::string name_cpp;
238af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      const char* name_cstr;
239af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      if (name != nullptr) {
240af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe        name_cpp = name->AsString()->ToModifiedUtf8();
241af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe        name_cstr = name_cpp.c_str();
242af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      } else {
243af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe        name_cstr = "";
244af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      }
2455471141cf6631b4162b222540b531b9f493d3cb2Andreas Gampe      jvmtiError name_result;
2465471141cf6631b4162b222540b531b9f493d3cb2Andreas Gampe      name_uptr = CopyString(env, name_cstr, &name_result);
2475471141cf6631b4162b222540b531b9f493d3cb2Andreas Gampe      if (name_uptr == nullptr) {
248af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe        return name_result;
249af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      }
2505471141cf6631b4162b222540b531b9f493d3cb2Andreas Gampe      info_ptr->name = name_uptr.get();
251af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    }
252af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
253af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    // Priority.
254af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    {
255af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_priority);
256af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      CHECK(f != nullptr);
257af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      info_ptr->priority = static_cast<jint>(f->GetInt(peer));
258af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    }
259af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
260af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    // Daemon.
261af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    {
262af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_daemon);
263af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      CHECK(f != nullptr);
264af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      info_ptr->is_daemon = f->GetBoolean(peer) == 0 ? JNI_FALSE : JNI_TRUE;
265af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    }
266af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
267af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    // ThreadGroup.
268af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    {
269af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_group);
270af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      CHECK(f != nullptr);
271af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      art::ObjPtr<art::mirror::Object> group = f->GetObject(peer);
272af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe      info_ptr->thread_group = group == nullptr
273af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe                                   ? nullptr
274af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe                                   : soa.AddLocalReference<jthreadGroup>(group);
275af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    }
276af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
277af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    // Context classloader.
278db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampe    DCHECK(context_class_loader_ != nullptr);
279db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampe    art::ObjPtr<art::mirror::Object> ccl = peer != nullptr
280db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampe        ? context_class_loader_->GetObject(peer)
281db6c2ab29ef6ebe89c9ea43dae3b899a935fa74eAndreas Gampe        : nullptr;
282af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe    info_ptr->context_class_loader = ccl == nullptr
283af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe                                         ? nullptr
284af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe                                         : soa.AddLocalReference<jobject>(ccl);
285af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe  }
286af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
287af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe  name_uptr.release();
288af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
289af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe  return ERR(NONE);
290af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe}
291af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe
2921f0a22f486873063246e64ec6bb38238987ae23eAlex Lightstruct InternalThreadState {
2931f0a22f486873063246e64ec6bb38238987ae23eAlex Light  art::Thread* native_thread;
2941f0a22f486873063246e64ec6bb38238987ae23eAlex Light  art::ThreadState art_state;
2951f0a22f486873063246e64ec6bb38238987ae23eAlex Light  int thread_user_code_suspend_count;
2961f0a22f486873063246e64ec6bb38238987ae23eAlex Light};
2971f0a22f486873063246e64ec6bb38238987ae23eAlex Light
2981f0a22f486873063246e64ec6bb38238987ae23eAlex Light// Return the thread's (or current thread, if null) thread state.
2991f0a22f486873063246e64ec6bb38238987ae23eAlex Lightstatic InternalThreadState GetNativeThreadState(jthread thread,
3001f0a22f486873063246e64ec6bb38238987ae23eAlex Light                                                const art::ScopedObjectAccessAlreadyRunnable& soa)
3011f0a22f486873063246e64ec6bb38238987ae23eAlex Light    REQUIRES_SHARED(art::Locks::mutator_lock_)
3023ae82531b336b195a78c864c28af1448a74af633Alex Light    REQUIRES(art::Locks::thread_list_lock_, art::Locks::user_code_suspension_lock_) {
30372c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe  art::Thread* self = nullptr;
30472c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe  if (thread == nullptr) {
30572c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    self = art::Thread::Current();
30672c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe  } else {
30772c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    self = art::Thread::FromManagedThread(soa, thread);
30872c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe  }
3091f0a22f486873063246e64ec6bb38238987ae23eAlex Light  InternalThreadState thread_state = {};
3101f0a22f486873063246e64ec6bb38238987ae23eAlex Light  art::MutexLock tscl_mu(soa.Self(), *art::Locks::thread_suspend_count_lock_);
3111f0a22f486873063246e64ec6bb38238987ae23eAlex Light  thread_state.native_thread = self;
31272c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe  if (self == nullptr || self->IsStillStarting()) {
3131f0a22f486873063246e64ec6bb38238987ae23eAlex Light    thread_state.art_state = art::ThreadState::kStarting;
3141f0a22f486873063246e64ec6bb38238987ae23eAlex Light    thread_state.thread_user_code_suspend_count = 0;
3151f0a22f486873063246e64ec6bb38238987ae23eAlex Light  } else {
3161f0a22f486873063246e64ec6bb38238987ae23eAlex Light    thread_state.art_state = self->GetState();
3171f0a22f486873063246e64ec6bb38238987ae23eAlex Light    thread_state.thread_user_code_suspend_count = self->GetUserCodeSuspendCount();
31872c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe  }
3191f0a22f486873063246e64ec6bb38238987ae23eAlex Light  return thread_state;
32072c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe}
32172c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
3221f0a22f486873063246e64ec6bb38238987ae23eAlex Lightstatic jint GetJvmtiThreadStateFromInternal(const InternalThreadState& state) {
3231f0a22f486873063246e64ec6bb38238987ae23eAlex Light  art::ThreadState internal_thread_state = state.art_state;
32472c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe  jint jvmti_state = JVMTI_THREAD_STATE_ALIVE;
32572c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
3261f0a22f486873063246e64ec6bb38238987ae23eAlex Light  if (state.thread_user_code_suspend_count != 0) {
32772c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    jvmti_state |= JVMTI_THREAD_STATE_SUSPENDED;
32872c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    // Note: We do not have data about the previous state. Otherwise we should load the previous
32972c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    //       state here.
33072c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe  }
33172c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
3321f0a22f486873063246e64ec6bb38238987ae23eAlex Light  if (state.native_thread->IsInterrupted()) {
3331f0a22f486873063246e64ec6bb38238987ae23eAlex Light    jvmti_state |= JVMTI_THREAD_STATE_INTERRUPTED;
3341f0a22f486873063246e64ec6bb38238987ae23eAlex Light  }
3351f0a22f486873063246e64ec6bb38238987ae23eAlex Light
33672c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe  if (internal_thread_state == art::ThreadState::kNative) {
33772c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    jvmti_state |= JVMTI_THREAD_STATE_IN_NATIVE;
33872c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe  }
33972c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
34072c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe  if (internal_thread_state == art::ThreadState::kRunnable ||
34172c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe      internal_thread_state == art::ThreadState::kWaitingWeakGcRootRead ||
34272c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe      internal_thread_state == art::ThreadState::kSuspended) {
34372c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    jvmti_state |= JVMTI_THREAD_STATE_RUNNABLE;
34472c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe  } else if (internal_thread_state == art::ThreadState::kBlocked) {
34572c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    jvmti_state |= JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
34672c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe  } else {
34772c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    // Should be in waiting state.
34872c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    jvmti_state |= JVMTI_THREAD_STATE_WAITING;
34972c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
35072c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    if (internal_thread_state == art::ThreadState::kTimedWaiting ||
35172c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe        internal_thread_state == art::ThreadState::kSleeping) {
35272c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe      jvmti_state |= JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT;
35372c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    } else {
35472c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe      jvmti_state |= JVMTI_THREAD_STATE_WAITING_INDEFINITELY;
35572c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    }
35672c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
35772c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    if (internal_thread_state == art::ThreadState::kSleeping) {
35872c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe      jvmti_state |= JVMTI_THREAD_STATE_SLEEPING;
35972c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    }
36072c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
36172c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    if (internal_thread_state == art::ThreadState::kTimedWaiting ||
36272c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe        internal_thread_state == art::ThreadState::kWaiting) {
36372c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe      jvmti_state |= JVMTI_THREAD_STATE_IN_OBJECT_WAIT;
36472c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    }
36572c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
36672c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    // TODO: PARKED. We'll have to inspect the stack.
36772c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe  }
36872c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
36972c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe  return jvmti_state;
37072c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe}
37172c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
3721f0a22f486873063246e64ec6bb38238987ae23eAlex Lightstatic jint GetJavaStateFromInternal(const InternalThreadState& state) {
3731f0a22f486873063246e64ec6bb38238987ae23eAlex Light  switch (state.art_state) {
37472c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kTerminated:
37572c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe      return JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED;
37672c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
37772c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kRunnable:
37872c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kNative:
37972c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kWaitingWeakGcRootRead:
38072c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kSuspended:
38172c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe      return JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE;
38272c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
38372c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kTimedWaiting:
38472c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kSleeping:
38572c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe      return JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING;
38672c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
38772c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kBlocked:
38872c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe      return JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED;
38972c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
39072c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kStarting:
39172c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe      return JVMTI_JAVA_LANG_THREAD_STATE_NEW;
39272c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
39372c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kWaiting:
39472c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kWaitingForGcToComplete:
39572c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kWaitingPerformingGc:
39672c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kWaitingForCheckPointsToRun:
39772c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kWaitingForDebuggerSend:
39872c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kWaitingForDebuggerToAttach:
39972c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kWaitingInMainDebuggerLoop:
40072c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kWaitingForDebuggerSuspension:
40172c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kWaitingForDeoptimization:
40272c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kWaitingForGetObjectsAllocated:
40372c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kWaitingForJniOnLoad:
40472c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kWaitingForSignalCatcherOutput:
40572c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kWaitingInMainSignalCatcherLoop:
40672c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kWaitingForMethodTracingStart:
40772c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kWaitingForVisitObjects:
40872c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    case art::ThreadState::kWaitingForGcThreadFlip:
40972c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe      return JVMTI_JAVA_LANG_THREAD_STATE_WAITING;
41072c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe  }
41172c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe  LOG(FATAL) << "Unreachable";
41272c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe  UNREACHABLE();
41372c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe}
41472c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
4151f0a22f486873063246e64ec6bb38238987ae23eAlex Light// Suspends the current thread if it has any suspend requests on it.
4161f0a22f486873063246e64ec6bb38238987ae23eAlex Lightstatic void SuspendCheck(art::Thread* self)
4171f0a22f486873063246e64ec6bb38238987ae23eAlex Light    REQUIRES(!art::Locks::mutator_lock_, !art::Locks::user_code_suspension_lock_) {
4181f0a22f486873063246e64ec6bb38238987ae23eAlex Light  art::ScopedObjectAccess soa(self);
4191f0a22f486873063246e64ec6bb38238987ae23eAlex Light  // Really this is only needed if we are in FastJNI and actually have the mutator_lock_ already.
4201f0a22f486873063246e64ec6bb38238987ae23eAlex Light  self->FullSuspendCheck();
4211f0a22f486873063246e64ec6bb38238987ae23eAlex Light}
4221f0a22f486873063246e64ec6bb38238987ae23eAlex Light
42372c19834136c81eace33687e06f5daf92a5a7583Andreas GampejvmtiError ThreadUtil::GetThreadState(jvmtiEnv* env ATTRIBUTE_UNUSED,
42472c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe                                      jthread thread,
42572c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe                                      jint* thread_state_ptr) {
42672c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe  if (thread_state_ptr == nullptr) {
42772c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    return ERR(NULL_POINTER);
42872c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe  }
42972c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
4301f0a22f486873063246e64ec6bb38238987ae23eAlex Light  art::Thread* self = art::Thread::Current();
4311f0a22f486873063246e64ec6bb38238987ae23eAlex Light  InternalThreadState state = {};
4321f0a22f486873063246e64ec6bb38238987ae23eAlex Light  // Loop since we need to bail out and try again if we would end up getting suspended while holding
4331f0a22f486873063246e64ec6bb38238987ae23eAlex Light  // the user_code_suspension_lock_ due to a SuspendReason::kForUserCode. In this situation we
4341f0a22f486873063246e64ec6bb38238987ae23eAlex Light  // release the lock, wait to get resumed and try again.
4351f0a22f486873063246e64ec6bb38238987ae23eAlex Light  do {
4361f0a22f486873063246e64ec6bb38238987ae23eAlex Light    SuspendCheck(self);
4371f0a22f486873063246e64ec6bb38238987ae23eAlex Light    art::MutexLock ucsl_mu(self, *art::Locks::user_code_suspension_lock_);
4381f0a22f486873063246e64ec6bb38238987ae23eAlex Light    {
4391f0a22f486873063246e64ec6bb38238987ae23eAlex Light      art::MutexLock tscl_mu(self, *art::Locks::thread_suspend_count_lock_);
4401f0a22f486873063246e64ec6bb38238987ae23eAlex Light      if (self->GetUserCodeSuspendCount() != 0) {
4411f0a22f486873063246e64ec6bb38238987ae23eAlex Light        // Make sure we won't be suspended in the middle of holding the thread_suspend_count_lock_
4421f0a22f486873063246e64ec6bb38238987ae23eAlex Light        // by a user-code suspension. We retry and do another SuspendCheck to clear this.
4431f0a22f486873063246e64ec6bb38238987ae23eAlex Light        continue;
4441f0a22f486873063246e64ec6bb38238987ae23eAlex Light      }
4451f0a22f486873063246e64ec6bb38238987ae23eAlex Light    }
4461f0a22f486873063246e64ec6bb38238987ae23eAlex Light    art::ScopedObjectAccess soa(self);
4473ae82531b336b195a78c864c28af1448a74af633Alex Light    art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_);
4481f0a22f486873063246e64ec6bb38238987ae23eAlex Light    state = GetNativeThreadState(thread, soa);
4493ae82531b336b195a78c864c28af1448a74af633Alex Light    if (state.art_state == art::ThreadState::kStarting) {
4503ae82531b336b195a78c864c28af1448a74af633Alex Light      break;
45172c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    }
4523ae82531b336b195a78c864c28af1448a74af633Alex Light    DCHECK(state.native_thread != nullptr);
45372c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
4543ae82531b336b195a78c864c28af1448a74af633Alex Light    // Translate internal thread state to JVMTI and Java state.
4553ae82531b336b195a78c864c28af1448a74af633Alex Light    jint jvmti_state = GetJvmtiThreadStateFromInternal(state);
4563ae82531b336b195a78c864c28af1448a74af633Alex Light
4573ae82531b336b195a78c864c28af1448a74af633Alex Light    // Java state is derived from nativeGetState.
4583ae82531b336b195a78c864c28af1448a74af633Alex Light    // TODO: Our implementation assigns "runnable" to suspended. As such, we will have slightly
4593ae82531b336b195a78c864c28af1448a74af633Alex Light    //       different mask if a thread got suspended due to user-code. However, this is for
4603ae82531b336b195a78c864c28af1448a74af633Alex Light    //       consistency with the Java view.
4613ae82531b336b195a78c864c28af1448a74af633Alex Light    jint java_state = GetJavaStateFromInternal(state);
4623ae82531b336b195a78c864c28af1448a74af633Alex Light
4633ae82531b336b195a78c864c28af1448a74af633Alex Light    *thread_state_ptr = jvmti_state | java_state;
4641f0a22f486873063246e64ec6bb38238987ae23eAlex Light
46572c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe    return ERR(NONE);
4663ae82531b336b195a78c864c28af1448a74af633Alex Light  } while (true);
46772c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
4683ae82531b336b195a78c864c28af1448a74af633Alex Light  DCHECK_EQ(state.art_state, art::ThreadState::kStarting);
46972c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
4703ae82531b336b195a78c864c28af1448a74af633Alex Light  if (thread == nullptr) {
4713ae82531b336b195a78c864c28af1448a74af633Alex Light    // No native thread, and no Java thread? We must be starting up. Report as wrong phase.
4723ae82531b336b195a78c864c28af1448a74af633Alex Light    return ERR(WRONG_PHASE);
4733ae82531b336b195a78c864c28af1448a74af633Alex Light  }
47472c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
4753ae82531b336b195a78c864c28af1448a74af633Alex Light  art::ScopedObjectAccess soa(self);
47672c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
4773ae82531b336b195a78c864c28af1448a74af633Alex Light  // Need to read the Java "started" field to know whether this is starting or terminated.
4783ae82531b336b195a78c864c28af1448a74af633Alex Light  art::ObjPtr<art::mirror::Object> peer = soa.Decode<art::mirror::Object>(thread);
4793ae82531b336b195a78c864c28af1448a74af633Alex Light  art::ObjPtr<art::mirror::Class> klass = peer->GetClass();
4803ae82531b336b195a78c864c28af1448a74af633Alex Light  art::ArtField* started_field = klass->FindDeclaredInstanceField("started", "Z");
4813ae82531b336b195a78c864c28af1448a74af633Alex Light  CHECK(started_field != nullptr);
4823ae82531b336b195a78c864c28af1448a74af633Alex Light  bool started = started_field->GetBoolean(peer) != 0;
4833ae82531b336b195a78c864c28af1448a74af633Alex Light  constexpr jint kStartedState = JVMTI_JAVA_LANG_THREAD_STATE_NEW;
4843ae82531b336b195a78c864c28af1448a74af633Alex Light  constexpr jint kTerminatedState = JVMTI_THREAD_STATE_TERMINATED |
4853ae82531b336b195a78c864c28af1448a74af633Alex Light                                    JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED;
4863ae82531b336b195a78c864c28af1448a74af633Alex Light  *thread_state_ptr = started ? kTerminatedState : kStartedState;
48772c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe  return ERR(NONE);
48872c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe}
48972c19834136c81eace33687e06f5daf92a5a7583Andreas Gampe
4908580744607a963d408956c3eb712b0e070c139b0Andreas GampejvmtiError ThreadUtil::GetAllThreads(jvmtiEnv* env,
4918580744607a963d408956c3eb712b0e070c139b0Andreas Gampe                                     jint* threads_count_ptr,
4928580744607a963d408956c3eb712b0e070c139b0Andreas Gampe                                     jthread** threads_ptr) {
4938580744607a963d408956c3eb712b0e070c139b0Andreas Gampe  if (threads_count_ptr == nullptr || threads_ptr == nullptr) {
4948580744607a963d408956c3eb712b0e070c139b0Andreas Gampe    return ERR(NULL_POINTER);
4958580744607a963d408956c3eb712b0e070c139b0Andreas Gampe  }
4968580744607a963d408956c3eb712b0e070c139b0Andreas Gampe
4978580744607a963d408956c3eb712b0e070c139b0Andreas Gampe  art::Thread* current = art::Thread::Current();
4988580744607a963d408956c3eb712b0e070c139b0Andreas Gampe
4998580744607a963d408956c3eb712b0e070c139b0Andreas Gampe  art::ScopedObjectAccess soa(current);
5008580744607a963d408956c3eb712b0e070c139b0Andreas Gampe
5018580744607a963d408956c3eb712b0e070c139b0Andreas Gampe  art::MutexLock mu(current, *art::Locks::thread_list_lock_);
5028580744607a963d408956c3eb712b0e070c139b0Andreas Gampe  std::list<art::Thread*> thread_list = art::Runtime::Current()->GetThreadList()->GetList();
5038580744607a963d408956c3eb712b0e070c139b0Andreas Gampe
5048580744607a963d408956c3eb712b0e070c139b0Andreas Gampe  std::vector<art::ObjPtr<art::mirror::Object>> peers;
5058580744607a963d408956c3eb712b0e070c139b0Andreas Gampe
5068580744607a963d408956c3eb712b0e070c139b0Andreas Gampe  for (art::Thread* thread : thread_list) {
5078580744607a963d408956c3eb712b0e070c139b0Andreas Gampe    // Skip threads that are still starting.
5088580744607a963d408956c3eb712b0e070c139b0Andreas Gampe    if (thread->IsStillStarting()) {
5098580744607a963d408956c3eb712b0e070c139b0Andreas Gampe      continue;
5108580744607a963d408956c3eb712b0e070c139b0Andreas Gampe    }
5118580744607a963d408956c3eb712b0e070c139b0Andreas Gampe
512202f85a54bfd1844664a18c18a4c0494763c6b82Andreas Gampe    art::ObjPtr<art::mirror::Object> peer = thread->GetPeerFromOtherThread();
5138580744607a963d408956c3eb712b0e070c139b0Andreas Gampe    if (peer != nullptr) {
5148580744607a963d408956c3eb712b0e070c139b0Andreas Gampe      peers.push_back(peer);
5158580744607a963d408956c3eb712b0e070c139b0Andreas Gampe    }
5168580744607a963d408956c3eb712b0e070c139b0Andreas Gampe  }
5178580744607a963d408956c3eb712b0e070c139b0Andreas Gampe
5188580744607a963d408956c3eb712b0e070c139b0Andreas Gampe  if (peers.empty()) {
5198580744607a963d408956c3eb712b0e070c139b0Andreas Gampe    *threads_count_ptr = 0;
5208580744607a963d408956c3eb712b0e070c139b0Andreas Gampe    *threads_ptr = nullptr;
5218580744607a963d408956c3eb712b0e070c139b0Andreas Gampe  } else {
5228580744607a963d408956c3eb712b0e070c139b0Andreas Gampe    unsigned char* data;
5238580744607a963d408956c3eb712b0e070c139b0Andreas Gampe    jvmtiError data_result = env->Allocate(peers.size() * sizeof(jthread), &data);
5248580744607a963d408956c3eb712b0e070c139b0Andreas Gampe    if (data_result != ERR(NONE)) {
5258580744607a963d408956c3eb712b0e070c139b0Andreas Gampe      return data_result;
5268580744607a963d408956c3eb712b0e070c139b0Andreas Gampe    }
5278580744607a963d408956c3eb712b0e070c139b0Andreas Gampe    jthread* threads = reinterpret_cast<jthread*>(data);
5288580744607a963d408956c3eb712b0e070c139b0Andreas Gampe    for (size_t i = 0; i != peers.size(); ++i) {
5298580744607a963d408956c3eb712b0e070c139b0Andreas Gampe      threads[i] = soa.AddLocalReference<jthread>(peers[i]);
5308580744607a963d408956c3eb712b0e070c139b0Andreas Gampe    }
5318580744607a963d408956c3eb712b0e070c139b0Andreas Gampe
5328580744607a963d408956c3eb712b0e070c139b0Andreas Gampe    *threads_count_ptr = static_cast<jint>(peers.size());
5338580744607a963d408956c3eb712b0e070c139b0Andreas Gampe    *threads_ptr = threads;
5348580744607a963d408956c3eb712b0e070c139b0Andreas Gampe  }
535f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe  return ERR(NONE);
536f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe}
537f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe
538092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light// The struct that we store in the art::Thread::custom_tls_ that maps the jvmtiEnvs to the data
539092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light// stored with that thread. This is needed since different jvmtiEnvs are not supposed to share TLS
540092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light// data but we only have a single slot in Thread objects to store data.
541092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Lightstruct JvmtiGlobalTLSData {
542092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  std::unordered_map<jvmtiEnv*, const void*> data GUARDED_BY(art::Locks::thread_list_lock_);
543092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light};
544092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light
545092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Lightstatic void RemoveTLSData(art::Thread* target, void* ctx) REQUIRES(art::Locks::thread_list_lock_) {
546092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  jvmtiEnv* env = reinterpret_cast<jvmtiEnv*>(ctx);
547092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  art::Locks::thread_list_lock_->AssertHeld(art::Thread::Current());
548092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  JvmtiGlobalTLSData* global_tls = reinterpret_cast<JvmtiGlobalTLSData*>(target->GetCustomTLS());
549092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  if (global_tls != nullptr) {
550092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light    global_tls->data.erase(env);
551092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  }
552092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light}
553092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light
554092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Lightvoid ThreadUtil::RemoveEnvironment(jvmtiEnv* env) {
555092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  art::Thread* self = art::Thread::Current();
556092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  art::MutexLock mu(self, *art::Locks::thread_list_lock_);
557092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  art::ThreadList* list = art::Runtime::Current()->GetThreadList();
558092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  list->ForEach(RemoveTLSData, env);
559092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light}
560092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light
561092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex LightjvmtiError ThreadUtil::SetThreadLocalStorage(jvmtiEnv* env, jthread thread, const void* data) {
562092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  art::Thread* self = art::Thread::Current();
563092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  art::ScopedObjectAccess soa(self);
564092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  art::MutexLock mu(self, *art::Locks::thread_list_lock_);
5653ae82531b336b195a78c864c28af1448a74af633Alex Light  art::Thread* target = GetNativeThread(thread, soa);
566092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  if (target == nullptr && thread == nullptr) {
567f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe    return ERR(INVALID_THREAD);
568f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe  }
569092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  if (target == nullptr) {
570f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe    return ERR(THREAD_NOT_ALIVE);
571f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe  }
572f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe
573092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  JvmtiGlobalTLSData* global_tls = reinterpret_cast<JvmtiGlobalTLSData*>(target->GetCustomTLS());
574092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  if (global_tls == nullptr) {
575092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light    target->SetCustomTLS(new JvmtiGlobalTLSData);
576092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light    global_tls = reinterpret_cast<JvmtiGlobalTLSData*>(target->GetCustomTLS());
577092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  }
578092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light
579092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  global_tls->data[env] = data;
580f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe
581f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe  return ERR(NONE);
582f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe}
583f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe
584092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex LightjvmtiError ThreadUtil::GetThreadLocalStorage(jvmtiEnv* env,
585f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe                                             jthread thread,
586f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe                                             void** data_ptr) {
587f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe  if (data_ptr == nullptr) {
588f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe    return ERR(NULL_POINTER);
589f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe  }
590f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe
591092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  art::Thread* self = art::Thread::Current();
592092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  art::ScopedObjectAccess soa(self);
593092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  art::MutexLock mu(self, *art::Locks::thread_list_lock_);
5943ae82531b336b195a78c864c28af1448a74af633Alex Light  art::Thread* target = GetNativeThread(thread, soa);
595092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  if (target == nullptr && thread == nullptr) {
596f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe    return ERR(INVALID_THREAD);
597f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe  }
598092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  if (target == nullptr) {
599f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe    return ERR(THREAD_NOT_ALIVE);
600f26bf2dd7d43716946ef8d4e046b9c0be36fb3a4Andreas Gampe  }
6018580744607a963d408956c3eb712b0e070c139b0Andreas Gampe
602092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  JvmtiGlobalTLSData* global_tls = reinterpret_cast<JvmtiGlobalTLSData*>(target->GetCustomTLS());
603092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  if (global_tls == nullptr) {
604092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light    *data_ptr = nullptr;
605092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light    return OK;
606092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  }
607092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  auto it = global_tls->data.find(env);
608092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  if (it != global_tls->data.end()) {
609092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light    *data_ptr = const_cast<void*>(it->second);
610092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  } else {
611092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light    *data_ptr = nullptr;
612092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light  }
613092a4046ff7bd3d7e24bc77cecf3d1bb0aa52107Alex Light
6148580744607a963d408956c3eb712b0e070c139b0Andreas Gampe  return ERR(NONE);
6158580744607a963d408956c3eb712b0e070c139b0Andreas Gampe}
6168580744607a963d408956c3eb712b0e070c139b0Andreas Gampe
617732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampestruct AgentData {
618732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  const void* arg;
619732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  jvmtiStartFunction proc;
620732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  jthread thread;
621732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  JavaVM* java_vm;
622732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  jvmtiEnv* jvmti_env;
623732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  jint priority;
624732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe};
625732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe
626732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampestatic void* AgentCallback(void* arg) {
627732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  std::unique_ptr<AgentData> data(reinterpret_cast<AgentData*>(arg));
628732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  CHECK(data->thread != nullptr);
629732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe
630732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  // We already have a peer. So call our special Attach function.
631732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  art::Thread* self = art::Thread::Attach("JVMTI Agent thread", true, data->thread);
632732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  CHECK(self != nullptr);
633732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  // The name in Attach() is only for logging. Set the thread name. This is important so
634732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  // that the thread is no longer seen as starting up.
635732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  {
636732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe    art::ScopedObjectAccess soa(self);
637732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe    self->SetThreadName("JVMTI Agent thread");
638732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  }
639732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe
640732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  // Release the peer.
641732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  JNIEnv* env = self->GetJniEnv();
642732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  env->DeleteGlobalRef(data->thread);
643732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  data->thread = nullptr;
644732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe
645732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  // Run the agent code.
646732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  data->proc(data->jvmti_env, env, const_cast<void*>(data->arg));
647732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe
648732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  // Detach the thread.
649732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  int detach_result = data->java_vm->DetachCurrentThread();
650732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  CHECK_EQ(detach_result, 0);
651732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe
652732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  return nullptr;
653732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe}
654732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe
655732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas GampejvmtiError ThreadUtil::RunAgentThread(jvmtiEnv* jvmti_env,
656732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe                                      jthread thread,
657732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe                                      jvmtiStartFunction proc,
658732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe                                      const void* arg,
659732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe                                      jint priority) {
660732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  if (priority < JVMTI_THREAD_MIN_PRIORITY || priority > JVMTI_THREAD_MAX_PRIORITY) {
661732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe    return ERR(INVALID_PRIORITY);
662732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  }
663732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  JNIEnv* env = art::Thread::Current()->GetJniEnv();
664732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  if (thread == nullptr || !env->IsInstanceOf(thread, art::WellKnownClasses::java_lang_Thread)) {
665732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe    return ERR(INVALID_THREAD);
666732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  }
667732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  if (proc == nullptr) {
668732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe    return ERR(NULL_POINTER);
669732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  }
670732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe
671732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  std::unique_ptr<AgentData> data(new AgentData);
672732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  data->arg = arg;
673732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  data->proc = proc;
674732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  // We need a global ref for Java objects, as local refs will be invalid.
675732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  data->thread = env->NewGlobalRef(thread);
676732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  data->java_vm = art::Runtime::Current()->GetJavaVM();
677732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  data->jvmti_env = jvmti_env;
678732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  data->priority = priority;
679732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe
680732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  pthread_t pthread;
681732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  int pthread_create_result = pthread_create(&pthread,
682732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe                                             nullptr,
683732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe                                             &AgentCallback,
684732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe                                             reinterpret_cast<void*>(data.get()));
685732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  if (pthread_create_result != 0) {
686732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe    return ERR(INTERNAL);
687732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  }
688732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  data.release();
689732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe
690732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe  return ERR(NONE);
691732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe}
692732b0aca4fb8e5ffbd518ca913cb82810b6b2061Andreas Gampe
69388fd720b6799184c8ad61e766a6d37af33ed30efAlex LightjvmtiError ThreadUtil::SuspendOther(art::Thread* self,
6943ae82531b336b195a78c864c28af1448a74af633Alex Light                                    jthread target_jthread) {
69588fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  // Loop since we need to bail out and try again if we would end up getting suspended while holding
69688fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  // the user_code_suspension_lock_ due to a SuspendReason::kForUserCode. In this situation we
69788fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  // release the lock, wait to get resumed and try again.
69888fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  do {
69988fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    // Suspend ourself if we have any outstanding suspends. This is so we won't suspend due to
70088fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    // another SuspendThread in the middle of suspending something else potentially causing a
70188fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    // deadlock. We need to do this in the loop because if we ended up back here then we had
70288fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    // outstanding SuspendReason::kForUserCode suspensions and we should wait for them to be cleared
70388fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    // before continuing.
70488fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    SuspendCheck(self);
70588fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    art::MutexLock mu(self, *art::Locks::user_code_suspension_lock_);
70688fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    {
7073ae82531b336b195a78c864c28af1448a74af633Alex Light      art::MutexLock thread_suspend_count_mu(self, *art::Locks::thread_suspend_count_lock_);
70888fd720b6799184c8ad61e766a6d37af33ed30efAlex Light      // Make sure we won't be suspended in the middle of holding the thread_suspend_count_lock_ by
70988fd720b6799184c8ad61e766a6d37af33ed30efAlex Light      // a user-code suspension. We retry and do another SuspendCheck to clear this.
71088fd720b6799184c8ad61e766a6d37af33ed30efAlex Light      if (self->GetUserCodeSuspendCount() != 0) {
71188fd720b6799184c8ad61e766a6d37af33ed30efAlex Light        continue;
71288fd720b6799184c8ad61e766a6d37af33ed30efAlex Light      }
7133ae82531b336b195a78c864c28af1448a74af633Alex Light      // We are not going to be suspended by user code from now on.
71488fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    }
7153ae82531b336b195a78c864c28af1448a74af633Alex Light    {
7163ae82531b336b195a78c864c28af1448a74af633Alex Light      art::ScopedObjectAccess soa(self);
7173ae82531b336b195a78c864c28af1448a74af633Alex Light      art::MutexLock thread_list_mu(self, *art::Locks::thread_list_lock_);
7183ae82531b336b195a78c864c28af1448a74af633Alex Light      art::Thread* target = GetNativeThread(target_jthread, soa);
71988fd720b6799184c8ad61e766a6d37af33ed30efAlex Light      art::ThreadState state = target->GetState();
72088fd720b6799184c8ad61e766a6d37af33ed30efAlex Light      if (state == art::ThreadState::kTerminated || state == art::ThreadState::kStarting) {
72188fd720b6799184c8ad61e766a6d37af33ed30efAlex Light        return ERR(THREAD_NOT_ALIVE);
7223ae82531b336b195a78c864c28af1448a74af633Alex Light      } else {
7233ae82531b336b195a78c864c28af1448a74af633Alex Light        art::MutexLock thread_suspend_count_mu(self, *art::Locks::thread_suspend_count_lock_);
7243ae82531b336b195a78c864c28af1448a74af633Alex Light        if (target->GetUserCodeSuspendCount() != 0) {
7253ae82531b336b195a78c864c28af1448a74af633Alex Light          return ERR(THREAD_SUSPENDED);
7263ae82531b336b195a78c864c28af1448a74af633Alex Light        }
72788fd720b6799184c8ad61e766a6d37af33ed30efAlex Light      }
72888fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    }
7293ae82531b336b195a78c864c28af1448a74af633Alex Light    bool timeout = true;
7303ae82531b336b195a78c864c28af1448a74af633Alex Light    art::Thread* ret_target = art::Runtime::Current()->GetThreadList()->SuspendThreadByPeer(
7313ae82531b336b195a78c864c28af1448a74af633Alex Light        target_jthread,
7323ae82531b336b195a78c864c28af1448a74af633Alex Light        /* request_suspension */ true,
7333ae82531b336b195a78c864c28af1448a74af633Alex Light        art::SuspendReason::kForUserCode,
7343ae82531b336b195a78c864c28af1448a74af633Alex Light        &timeout);
7353ae82531b336b195a78c864c28af1448a74af633Alex Light    if (ret_target == nullptr && !timeout) {
7363ae82531b336b195a78c864c28af1448a74af633Alex Light      // TODO It would be good to get more information about why exactly the thread failed to
7373ae82531b336b195a78c864c28af1448a74af633Alex Light      // suspend.
7383ae82531b336b195a78c864c28af1448a74af633Alex Light      return ERR(INTERNAL);
7393ae82531b336b195a78c864c28af1448a74af633Alex Light    } else if (!timeout) {
7403ae82531b336b195a78c864c28af1448a74af633Alex Light      // we didn't time out and got a result.
7413ae82531b336b195a78c864c28af1448a74af633Alex Light      return OK;
7423ae82531b336b195a78c864c28af1448a74af633Alex Light    }
7433ae82531b336b195a78c864c28af1448a74af633Alex Light    // We timed out. Just go around and try again.
74488fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  } while (true);
74588fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  UNREACHABLE();
74688fd720b6799184c8ad61e766a6d37af33ed30efAlex Light}
74788fd720b6799184c8ad61e766a6d37af33ed30efAlex Light
74888fd720b6799184c8ad61e766a6d37af33ed30efAlex LightjvmtiError ThreadUtil::SuspendSelf(art::Thread* self) {
74988fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  CHECK(self == art::Thread::Current());
75088fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  {
75188fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    art::MutexLock mu(self, *art::Locks::user_code_suspension_lock_);
75288fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    art::MutexLock thread_list_mu(self, *art::Locks::thread_suspend_count_lock_);
75388fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    if (self->GetUserCodeSuspendCount() != 0) {
75488fd720b6799184c8ad61e766a6d37af33ed30efAlex Light      // This can only happen if we race with another thread to suspend 'self' and we lose.
75588fd720b6799184c8ad61e766a6d37af33ed30efAlex Light      return ERR(THREAD_SUSPENDED);
75688fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    }
75788fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    // We shouldn't be able to fail this.
75888fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    if (!self->ModifySuspendCount(self, +1, nullptr, art::SuspendReason::kForUserCode)) {
75988fd720b6799184c8ad61e766a6d37af33ed30efAlex Light      // TODO More specific error would be nice.
76088fd720b6799184c8ad61e766a6d37af33ed30efAlex Light      return ERR(INTERNAL);
76188fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    }
76288fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  }
76388fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  // Once we have requested the suspend we actually go to sleep. We need to do this after releasing
76488fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  // the suspend_lock to make sure we can be woken up. This call gains the mutator lock causing us
76588fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  // to go to sleep until we are resumed.
76688fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  SuspendCheck(self);
76788fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  return OK;
76888fd720b6799184c8ad61e766a6d37af33ed30efAlex Light}
76988fd720b6799184c8ad61e766a6d37af33ed30efAlex Light
77088fd720b6799184c8ad61e766a6d37af33ed30efAlex LightjvmtiError ThreadUtil::SuspendThread(jvmtiEnv* env ATTRIBUTE_UNUSED, jthread thread) {
77188fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  art::Thread* self = art::Thread::Current();
7723ae82531b336b195a78c864c28af1448a74af633Alex Light  bool target_is_self = false;
77388fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  {
77488fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    art::ScopedObjectAccess soa(self);
7753ae82531b336b195a78c864c28af1448a74af633Alex Light    art::MutexLock mu(self, *art::Locks::thread_list_lock_);
7763ae82531b336b195a78c864c28af1448a74af633Alex Light    art::Thread* target = GetNativeThread(thread, soa);
7773ae82531b336b195a78c864c28af1448a74af633Alex Light    if (target == nullptr) {
7783ae82531b336b195a78c864c28af1448a74af633Alex Light      return ERR(INVALID_THREAD);
7793ae82531b336b195a78c864c28af1448a74af633Alex Light    } else if (target == self) {
7803ae82531b336b195a78c864c28af1448a74af633Alex Light      target_is_self = true;
7813ae82531b336b195a78c864c28af1448a74af633Alex Light    }
78288fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  }
7833ae82531b336b195a78c864c28af1448a74af633Alex Light  if (target_is_self) {
78488fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    return SuspendSelf(self);
78588fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  } else {
7863ae82531b336b195a78c864c28af1448a74af633Alex Light    return SuspendOther(self, thread);
78788fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  }
78888fd720b6799184c8ad61e766a6d37af33ed30efAlex Light}
78988fd720b6799184c8ad61e766a6d37af33ed30efAlex Light
79088fd720b6799184c8ad61e766a6d37af33ed30efAlex LightjvmtiError ThreadUtil::ResumeThread(jvmtiEnv* env ATTRIBUTE_UNUSED,
79188fd720b6799184c8ad61e766a6d37af33ed30efAlex Light                                    jthread thread) {
79288fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  if (thread == nullptr) {
79388fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    return ERR(NULL_POINTER);
79488fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  }
79588fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  art::Thread* self = art::Thread::Current();
79688fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  art::Thread* target;
7973ae82531b336b195a78c864c28af1448a74af633Alex Light  // Retry until we know we won't get suspended by user code while resuming something.
7983ae82531b336b195a78c864c28af1448a74af633Alex Light  do {
7993ae82531b336b195a78c864c28af1448a74af633Alex Light    SuspendCheck(self);
8003ae82531b336b195a78c864c28af1448a74af633Alex Light    art::MutexLock ucsl_mu(self, *art::Locks::user_code_suspension_lock_);
8013ae82531b336b195a78c864c28af1448a74af633Alex Light    {
8023ae82531b336b195a78c864c28af1448a74af633Alex Light      art::MutexLock tscl_mu(self, *art::Locks::thread_suspend_count_lock_);
8033ae82531b336b195a78c864c28af1448a74af633Alex Light      // Make sure we won't be suspended in the middle of holding the thread_suspend_count_lock_ by
8043ae82531b336b195a78c864c28af1448a74af633Alex Light      // a user-code suspension. We retry and do another SuspendCheck to clear this.
8053ae82531b336b195a78c864c28af1448a74af633Alex Light      if (self->GetUserCodeSuspendCount() != 0) {
8063ae82531b336b195a78c864c28af1448a74af633Alex Light        continue;
8073ae82531b336b195a78c864c28af1448a74af633Alex Light      }
80888fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    }
8093ae82531b336b195a78c864c28af1448a74af633Alex Light    // From now on we know we cannot get suspended by user-code.
8103ae82531b336b195a78c864c28af1448a74af633Alex Light    {
8113ae82531b336b195a78c864c28af1448a74af633Alex Light      // NB This does a SuspendCheck (during thread state change) so we need to make sure we don't
8123ae82531b336b195a78c864c28af1448a74af633Alex Light      // have the 'suspend_lock' locked here.
8133ae82531b336b195a78c864c28af1448a74af633Alex Light      art::ScopedObjectAccess soa(self);
8143ae82531b336b195a78c864c28af1448a74af633Alex Light      art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_);
8153ae82531b336b195a78c864c28af1448a74af633Alex Light      target = GetNativeThread(thread, soa);
8163ae82531b336b195a78c864c28af1448a74af633Alex Light      if (target == nullptr) {
8173ae82531b336b195a78c864c28af1448a74af633Alex Light        return ERR(INVALID_THREAD);
8183ae82531b336b195a78c864c28af1448a74af633Alex Light      } else if (target == self) {
8193ae82531b336b195a78c864c28af1448a74af633Alex Light        // We would have paused until we aren't suspended anymore due to the ScopedObjectAccess so
8203ae82531b336b195a78c864c28af1448a74af633Alex Light        // we can just return THREAD_NOT_SUSPENDED. Unfortunately we cannot do any real DCHECKs
8213ae82531b336b195a78c864c28af1448a74af633Alex Light        // about current state since it's all concurrent.
8223ae82531b336b195a78c864c28af1448a74af633Alex Light        return ERR(THREAD_NOT_SUSPENDED);
8233ae82531b336b195a78c864c28af1448a74af633Alex Light      } else if (target->GetState() == art::ThreadState::kTerminated) {
8243ae82531b336b195a78c864c28af1448a74af633Alex Light        return ERR(THREAD_NOT_ALIVE);
8253ae82531b336b195a78c864c28af1448a74af633Alex Light      }
8263ae82531b336b195a78c864c28af1448a74af633Alex Light      // The JVMTI spec requires us to return THREAD_NOT_SUSPENDED if it is alive but we really
8273ae82531b336b195a78c864c28af1448a74af633Alex Light      // cannot tell why resume failed.
8283ae82531b336b195a78c864c28af1448a74af633Alex Light      {
8293ae82531b336b195a78c864c28af1448a74af633Alex Light        art::MutexLock thread_suspend_count_mu(self, *art::Locks::thread_suspend_count_lock_);
8303ae82531b336b195a78c864c28af1448a74af633Alex Light        if (target->GetUserCodeSuspendCount() == 0) {
8313ae82531b336b195a78c864c28af1448a74af633Alex Light          return ERR(THREAD_NOT_SUSPENDED);
8323ae82531b336b195a78c864c28af1448a74af633Alex Light        }
8333ae82531b336b195a78c864c28af1448a74af633Alex Light      }
8343ae82531b336b195a78c864c28af1448a74af633Alex Light    }
8353ae82531b336b195a78c864c28af1448a74af633Alex Light    // It is okay that we don't have a thread_list_lock here since we know that the thread cannot
8363ae82531b336b195a78c864c28af1448a74af633Alex Light    // die since it is currently held suspended by a SuspendReason::kForUserCode suspend.
8373ae82531b336b195a78c864c28af1448a74af633Alex Light    DCHECK(target != self);
8383ae82531b336b195a78c864c28af1448a74af633Alex Light    if (!art::Runtime::Current()->GetThreadList()->Resume(target,
8393ae82531b336b195a78c864c28af1448a74af633Alex Light                                                          art::SuspendReason::kForUserCode)) {
8403ae82531b336b195a78c864c28af1448a74af633Alex Light      // TODO Give a better error.
8413ae82531b336b195a78c864c28af1448a74af633Alex Light      // This is most likely THREAD_NOT_SUSPENDED but we cannot really be sure.
8423ae82531b336b195a78c864c28af1448a74af633Alex Light      return ERR(INTERNAL);
8433ae82531b336b195a78c864c28af1448a74af633Alex Light    } else {
8443ae82531b336b195a78c864c28af1448a74af633Alex Light      return OK;
8453ae82531b336b195a78c864c28af1448a74af633Alex Light    }
8463ae82531b336b195a78c864c28af1448a74af633Alex Light  } while (true);
84788fd720b6799184c8ad61e766a6d37af33ed30efAlex Light}
84888fd720b6799184c8ad61e766a6d37af33ed30efAlex Light
84988fd720b6799184c8ad61e766a6d37af33ed30efAlex Light// Suspends all the threads in the list at the same time. Getting this behavior is a little tricky
85088fd720b6799184c8ad61e766a6d37af33ed30efAlex Light// since we can have threads in the list multiple times. This generally doesn't matter unless the
85188fd720b6799184c8ad61e766a6d37af33ed30efAlex Light// current thread is present multiple times. In that case we need to suspend only once and either
85288fd720b6799184c8ad61e766a6d37af33ed30efAlex Light// return the same error code in all the other slots if it failed or return ERR(THREAD_SUSPENDED) if
85388fd720b6799184c8ad61e766a6d37af33ed30efAlex Light// it didn't. We also want to handle the current thread last to make the behavior of the code
85488fd720b6799184c8ad61e766a6d37af33ed30efAlex Light// simpler to understand.
85588fd720b6799184c8ad61e766a6d37af33ed30efAlex LightjvmtiError ThreadUtil::SuspendThreadList(jvmtiEnv* env,
85688fd720b6799184c8ad61e766a6d37af33ed30efAlex Light                                         jint request_count,
85788fd720b6799184c8ad61e766a6d37af33ed30efAlex Light                                         const jthread* threads,
85888fd720b6799184c8ad61e766a6d37af33ed30efAlex Light                                         jvmtiError* results) {
85988fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  if (request_count == 0) {
86088fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    return ERR(ILLEGAL_ARGUMENT);
86188fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  } else if (results == nullptr || threads == nullptr) {
86288fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    return ERR(NULL_POINTER);
86388fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  }
86488fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  // This is the list of the indexes in 'threads' and 'results' that correspond to the currently
86588fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  // running thread. These indexes we need to handle specially since we need to only actually
86688fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  // suspend a single time.
86788fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  std::vector<jint> current_thread_indexes;
86888fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  art::Thread* self = art::Thread::Current();
86988fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  for (jint i = 0; i < request_count; i++) {
87088fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    {
87188fd720b6799184c8ad61e766a6d37af33ed30efAlex Light      art::ScopedObjectAccess soa(self);
8723ae82531b336b195a78c864c28af1448a74af633Alex Light      art::MutexLock mu(self, *art::Locks::thread_list_lock_);
87388fd720b6799184c8ad61e766a6d37af33ed30efAlex Light      if (threads[i] == nullptr || GetNativeThread(threads[i], soa) == self) {
87488fd720b6799184c8ad61e766a6d37af33ed30efAlex Light        current_thread_indexes.push_back(i);
87588fd720b6799184c8ad61e766a6d37af33ed30efAlex Light        continue;
87688fd720b6799184c8ad61e766a6d37af33ed30efAlex Light      }
87788fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    }
87888fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    results[i] = env->SuspendThread(threads[i]);
87988fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  }
88088fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  if (!current_thread_indexes.empty()) {
88188fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    jint first_current_thread_index = current_thread_indexes[0];
88288fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    // Suspend self.
88388fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    jvmtiError res = env->SuspendThread(threads[first_current_thread_index]);
88488fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    results[first_current_thread_index] = res;
88588fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    // Fill in the rest of the error values as appropriate.
88688fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    jvmtiError other_results = (res != OK) ? res : ERR(THREAD_SUSPENDED);
88788fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    for (auto it = ++current_thread_indexes.begin(); it != current_thread_indexes.end(); ++it) {
88888fd720b6799184c8ad61e766a6d37af33ed30efAlex Light      results[*it] = other_results;
88988fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    }
89088fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  }
89188fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  return OK;
89288fd720b6799184c8ad61e766a6d37af33ed30efAlex Light}
89388fd720b6799184c8ad61e766a6d37af33ed30efAlex Light
89488fd720b6799184c8ad61e766a6d37af33ed30efAlex LightjvmtiError ThreadUtil::ResumeThreadList(jvmtiEnv* env,
89588fd720b6799184c8ad61e766a6d37af33ed30efAlex Light                                        jint request_count,
89688fd720b6799184c8ad61e766a6d37af33ed30efAlex Light                                        const jthread* threads,
89788fd720b6799184c8ad61e766a6d37af33ed30efAlex Light                                        jvmtiError* results) {
89888fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  if (request_count == 0) {
89988fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    return ERR(ILLEGAL_ARGUMENT);
90088fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  } else if (results == nullptr || threads == nullptr) {
90188fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    return ERR(NULL_POINTER);
90288fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  }
90388fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  for (jint i = 0; i < request_count; i++) {
90488fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    results[i] = env->ResumeThread(threads[i]);
90588fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  }
90688fd720b6799184c8ad61e766a6d37af33ed30efAlex Light  return OK;
90788fd720b6799184c8ad61e766a6d37af33ed30efAlex Light}
90888fd720b6799184c8ad61e766a6d37af33ed30efAlex Light
909af13ab9586cebbfc40204179e2dd0986cc14dd84Andreas Gampe}  // namespace openjdkjvmti
910