1*795d594fSAndroid Build Coastguard Worker /* Copyright (C) 2017 The Android Open Source Project
2*795d594fSAndroid Build Coastguard Worker * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * This file implements interfaces from the file jvmti.h. This implementation
5*795d594fSAndroid Build Coastguard Worker * is licensed under the same terms as the file jvmti.h. The
6*795d594fSAndroid Build Coastguard Worker * copyright and license information for the file jvmti.h follows.
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
9*795d594fSAndroid Build Coastguard Worker * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10*795d594fSAndroid Build Coastguard Worker *
11*795d594fSAndroid Build Coastguard Worker * This code is free software; you can redistribute it and/or modify it
12*795d594fSAndroid Build Coastguard Worker * under the terms of the GNU General Public License version 2 only, as
13*795d594fSAndroid Build Coastguard Worker * published by the Free Software Foundation. Oracle designates this
14*795d594fSAndroid Build Coastguard Worker * particular file as subject to the "Classpath" exception as provided
15*795d594fSAndroid Build Coastguard Worker * by Oracle in the LICENSE file that accompanied this code.
16*795d594fSAndroid Build Coastguard Worker *
17*795d594fSAndroid Build Coastguard Worker * This code is distributed in the hope that it will be useful, but WITHOUT
18*795d594fSAndroid Build Coastguard Worker * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19*795d594fSAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20*795d594fSAndroid Build Coastguard Worker * version 2 for more details (a copy is included in the LICENSE file that
21*795d594fSAndroid Build Coastguard Worker * accompanied this code).
22*795d594fSAndroid Build Coastguard Worker *
23*795d594fSAndroid Build Coastguard Worker * You should have received a copy of the GNU General Public License version
24*795d594fSAndroid Build Coastguard Worker * 2 along with this work; if not, write to the Free Software Foundation,
25*795d594fSAndroid Build Coastguard Worker * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26*795d594fSAndroid Build Coastguard Worker *
27*795d594fSAndroid Build Coastguard Worker * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
28*795d594fSAndroid Build Coastguard Worker * or visit www.oracle.com if you need additional information or have any
29*795d594fSAndroid Build Coastguard Worker * questions.
30*795d594fSAndroid Build Coastguard Worker */
31*795d594fSAndroid Build Coastguard Worker
32*795d594fSAndroid Build Coastguard Worker #include "ti_thread.h"
33*795d594fSAndroid Build Coastguard Worker
34*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
35*795d594fSAndroid Build Coastguard Worker
36*795d594fSAndroid Build Coastguard Worker #include "art_field-inl.h"
37*795d594fSAndroid Build Coastguard Worker #include "art_jvmti.h"
38*795d594fSAndroid Build Coastguard Worker #include "base/mutex.h"
39*795d594fSAndroid Build Coastguard Worker #include "deopt_manager.h"
40*795d594fSAndroid Build Coastguard Worker #include "events-inl.h"
41*795d594fSAndroid Build Coastguard Worker #include "gc/collector_type.h"
42*795d594fSAndroid Build Coastguard Worker #include "gc/gc_cause.h"
43*795d594fSAndroid Build Coastguard Worker #include "gc/scoped_gc_critical_section.h"
44*795d594fSAndroid Build Coastguard Worker #include "gc/system_weak.h"
45*795d594fSAndroid Build Coastguard Worker #include "gc_root-inl.h"
46*795d594fSAndroid Build Coastguard Worker #include "jni/jni_internal.h"
47*795d594fSAndroid Build Coastguard Worker #include "metrics/reporter.h"
48*795d594fSAndroid Build Coastguard Worker #include "mirror/class.h"
49*795d594fSAndroid Build Coastguard Worker #include "mirror/object-inl.h"
50*795d594fSAndroid Build Coastguard Worker #include "mirror/string.h"
51*795d594fSAndroid Build Coastguard Worker #include "mirror/throwable.h"
52*795d594fSAndroid Build Coastguard Worker #include "nativehelper/scoped_local_ref.h"
53*795d594fSAndroid Build Coastguard Worker #include "nativehelper/scoped_utf_chars.h"
54*795d594fSAndroid Build Coastguard Worker #include "obj_ptr.h"
55*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
56*795d594fSAndroid Build Coastguard Worker #include "runtime_callbacks.h"
57*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
58*795d594fSAndroid Build Coastguard Worker #include "thread-current-inl.h"
59*795d594fSAndroid Build Coastguard Worker #include "thread_list.h"
60*795d594fSAndroid Build Coastguard Worker #include "ti_phase.h"
61*795d594fSAndroid Build Coastguard Worker #include "well_known_classes-inl.h"
62*795d594fSAndroid Build Coastguard Worker
63*795d594fSAndroid Build Coastguard Worker namespace openjdkjvmti {
64*795d594fSAndroid Build Coastguard Worker
65*795d594fSAndroid Build Coastguard Worker static const char* kJvmtiTlsKey = "JvmtiTlsKey";
66*795d594fSAndroid Build Coastguard Worker
67*795d594fSAndroid Build Coastguard Worker art::ArtField* ThreadUtil::context_class_loader_ = nullptr;
68*795d594fSAndroid Build Coastguard Worker
ScopedNoUserCodeSuspension(art::Thread * self)69*795d594fSAndroid Build Coastguard Worker ScopedNoUserCodeSuspension::ScopedNoUserCodeSuspension(art::Thread* self) : self_(self) {
70*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(self, art::Thread::Current());
71*795d594fSAndroid Build Coastguard Worker // Loop until we both have the user_code_suspension_locK_ and don't have any pending user_code
72*795d594fSAndroid Build Coastguard Worker // suspensions.
73*795d594fSAndroid Build Coastguard Worker do {
74*795d594fSAndroid Build Coastguard Worker art::Locks::user_code_suspension_lock_->AssertNotHeld(self_);
75*795d594fSAndroid Build Coastguard Worker ThreadUtil::SuspendCheck(self_);
76*795d594fSAndroid Build Coastguard Worker
77*795d594fSAndroid Build Coastguard Worker art::Locks::user_code_suspension_lock_->ExclusiveLock(self_);
78*795d594fSAndroid Build Coastguard Worker if (ThreadUtil::WouldSuspendForUserCodeLocked(self_)) {
79*795d594fSAndroid Build Coastguard Worker art::Locks::user_code_suspension_lock_->ExclusiveUnlock(self_);
80*795d594fSAndroid Build Coastguard Worker continue;
81*795d594fSAndroid Build Coastguard Worker }
82*795d594fSAndroid Build Coastguard Worker
83*795d594fSAndroid Build Coastguard Worker art::Locks::user_code_suspension_lock_->AssertHeld(self_);
84*795d594fSAndroid Build Coastguard Worker
85*795d594fSAndroid Build Coastguard Worker return;
86*795d594fSAndroid Build Coastguard Worker } while (true);
87*795d594fSAndroid Build Coastguard Worker }
88*795d594fSAndroid Build Coastguard Worker
~ScopedNoUserCodeSuspension()89*795d594fSAndroid Build Coastguard Worker ScopedNoUserCodeSuspension::~ScopedNoUserCodeSuspension() {
90*795d594fSAndroid Build Coastguard Worker art::Locks::user_code_suspension_lock_->ExclusiveUnlock(self_);
91*795d594fSAndroid Build Coastguard Worker }
92*795d594fSAndroid Build Coastguard Worker
93*795d594fSAndroid Build Coastguard Worker struct ThreadCallback : public art::ThreadLifecycleCallback {
GetThreadObjectopenjdkjvmti::ThreadCallback94*795d594fSAndroid Build Coastguard Worker jthread GetThreadObject(art::Thread* self) REQUIRES_SHARED(art::Locks::mutator_lock_) {
95*795d594fSAndroid Build Coastguard Worker if (self->GetPeer() == nullptr) {
96*795d594fSAndroid Build Coastguard Worker return nullptr;
97*795d594fSAndroid Build Coastguard Worker }
98*795d594fSAndroid Build Coastguard Worker return self->GetJniEnv()->AddLocalReference<jthread>(self->GetPeer());
99*795d594fSAndroid Build Coastguard Worker }
100*795d594fSAndroid Build Coastguard Worker
101*795d594fSAndroid Build Coastguard Worker template <ArtJvmtiEvent kEvent>
Postopenjdkjvmti::ThreadCallback102*795d594fSAndroid Build Coastguard Worker void Post(art::Thread* self) REQUIRES_SHARED(art::Locks::mutator_lock_) {
103*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(self, art::Thread::Current());
104*795d594fSAndroid Build Coastguard Worker ScopedLocalRef<jthread> thread(self->GetJniEnv(), GetThreadObject(self));
105*795d594fSAndroid Build Coastguard Worker art::ScopedThreadSuspension sts(self, art::ThreadState::kNative);
106*795d594fSAndroid Build Coastguard Worker event_handler->DispatchEvent<kEvent>(self,
107*795d594fSAndroid Build Coastguard Worker reinterpret_cast<JNIEnv*>(self->GetJniEnv()),
108*795d594fSAndroid Build Coastguard Worker thread.get());
109*795d594fSAndroid Build Coastguard Worker }
110*795d594fSAndroid Build Coastguard Worker
ThreadStartopenjdkjvmti::ThreadCallback111*795d594fSAndroid Build Coastguard Worker void ThreadStart(art::Thread* self) override REQUIRES_SHARED(art::Locks::mutator_lock_) {
112*795d594fSAndroid Build Coastguard Worker // Needs to be checked first because we might start these threads before we actually send the
113*795d594fSAndroid Build Coastguard Worker // VMInit event.
114*795d594fSAndroid Build Coastguard Worker if (self->IsSystemDaemon()) {
115*795d594fSAndroid Build Coastguard Worker // System daemon threads are things like the finalizer or gc thread. It would be dangerous to
116*795d594fSAndroid Build Coastguard Worker // allow agents to get in the way of these threads starting up. These threads include things
117*795d594fSAndroid Build Coastguard Worker // like the HeapTaskDaemon and the finalizer daemon.
118*795d594fSAndroid Build Coastguard Worker //
119*795d594fSAndroid Build Coastguard Worker // This event can happen during the time before VMInit or just after zygote fork. Since the
120*795d594fSAndroid Build Coastguard Worker // second is hard to distinguish we unfortunately cannot really check the state here.
121*795d594fSAndroid Build Coastguard Worker return;
122*795d594fSAndroid Build Coastguard Worker }
123*795d594fSAndroid Build Coastguard Worker if (!started) {
124*795d594fSAndroid Build Coastguard Worker // Runtime isn't started. We only expect at most the signal handler or JIT threads to be
125*795d594fSAndroid Build Coastguard Worker // started here; this includes the perfetto_hprof_listener signal handler thread for
126*795d594fSAndroid Build Coastguard Worker // perfetto_hprof, as well as the metrics background reporting thread.
127*795d594fSAndroid Build Coastguard Worker if (art::kIsDebugBuild) {
128*795d594fSAndroid Build Coastguard Worker std::string name;
129*795d594fSAndroid Build Coastguard Worker self->GetThreadName(name);
130*795d594fSAndroid Build Coastguard Worker if (name != "JDWP" && name != "Signal Catcher" && name != "perfetto_hprof_listener" &&
131*795d594fSAndroid Build Coastguard Worker name != art::metrics::MetricsReporter::kBackgroundThreadName &&
132*795d594fSAndroid Build Coastguard Worker !name.starts_with("Jit thread pool") &&
133*795d594fSAndroid Build Coastguard Worker !name.starts_with("Heap thread pool worker thread") &&
134*795d594fSAndroid Build Coastguard Worker !name.starts_with("Runtime worker thread")) {
135*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected thread before start: " << name << " id: "
136*795d594fSAndroid Build Coastguard Worker << self->GetThreadId();
137*795d594fSAndroid Build Coastguard Worker }
138*795d594fSAndroid Build Coastguard Worker }
139*795d594fSAndroid Build Coastguard Worker return;
140*795d594fSAndroid Build Coastguard Worker }
141*795d594fSAndroid Build Coastguard Worker Post<ArtJvmtiEvent::kThreadStart>(self);
142*795d594fSAndroid Build Coastguard Worker }
143*795d594fSAndroid Build Coastguard Worker
ThreadDeathopenjdkjvmti::ThreadCallback144*795d594fSAndroid Build Coastguard Worker void ThreadDeath(art::Thread* self) override REQUIRES_SHARED(art::Locks::mutator_lock_) {
145*795d594fSAndroid Build Coastguard Worker Post<ArtJvmtiEvent::kThreadEnd>(self);
146*795d594fSAndroid Build Coastguard Worker }
147*795d594fSAndroid Build Coastguard Worker
148*795d594fSAndroid Build Coastguard Worker EventHandler* event_handler = nullptr;
149*795d594fSAndroid Build Coastguard Worker bool started = false;
150*795d594fSAndroid Build Coastguard Worker };
151*795d594fSAndroid Build Coastguard Worker
152*795d594fSAndroid Build Coastguard Worker ThreadCallback gThreadCallback;
153*795d594fSAndroid Build Coastguard Worker
Register(EventHandler * handler)154*795d594fSAndroid Build Coastguard Worker void ThreadUtil::Register(EventHandler* handler) {
155*795d594fSAndroid Build Coastguard Worker art::Runtime* runtime = art::Runtime::Current();
156*795d594fSAndroid Build Coastguard Worker
157*795d594fSAndroid Build Coastguard Worker gThreadCallback.started = runtime->IsStarted();
158*795d594fSAndroid Build Coastguard Worker gThreadCallback.event_handler = handler;
159*795d594fSAndroid Build Coastguard Worker
160*795d594fSAndroid Build Coastguard Worker art::ScopedThreadStateChange stsc(art::Thread::Current(),
161*795d594fSAndroid Build Coastguard Worker art::ThreadState::kWaitingForDebuggerToAttach);
162*795d594fSAndroid Build Coastguard Worker art::ScopedSuspendAll ssa("Add thread callback");
163*795d594fSAndroid Build Coastguard Worker runtime->GetRuntimeCallbacks()->AddThreadLifecycleCallback(&gThreadCallback);
164*795d594fSAndroid Build Coastguard Worker }
165*795d594fSAndroid Build Coastguard Worker
VMInitEventSent()166*795d594fSAndroid Build Coastguard Worker void ThreadUtil::VMInitEventSent() {
167*795d594fSAndroid Build Coastguard Worker // We should have already started.
168*795d594fSAndroid Build Coastguard Worker DCHECK(gThreadCallback.started);
169*795d594fSAndroid Build Coastguard Worker // We moved to VMInit. Report the main thread as started (it was attached early, and must not be
170*795d594fSAndroid Build Coastguard Worker // reported until Init.
171*795d594fSAndroid Build Coastguard Worker gThreadCallback.Post<ArtJvmtiEvent::kThreadStart>(art::Thread::Current());
172*795d594fSAndroid Build Coastguard Worker }
173*795d594fSAndroid Build Coastguard Worker
174*795d594fSAndroid Build Coastguard Worker
WaitForSystemDaemonStart(art::Thread * self)175*795d594fSAndroid Build Coastguard Worker static void WaitForSystemDaemonStart(art::Thread* self) REQUIRES_SHARED(art::Locks::mutator_lock_) {
176*795d594fSAndroid Build Coastguard Worker art::WellKnownClasses::java_lang_Daemons_waitForDaemonStart->InvokeStatic<'V'>(self);
177*795d594fSAndroid Build Coastguard Worker if (self->IsExceptionPending()) {
178*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "Exception occurred when waiting for system daemons to start: "
179*795d594fSAndroid Build Coastguard Worker << self->GetException()->Dump();
180*795d594fSAndroid Build Coastguard Worker self->ClearException();
181*795d594fSAndroid Build Coastguard Worker }
182*795d594fSAndroid Build Coastguard Worker }
183*795d594fSAndroid Build Coastguard Worker
CacheData()184*795d594fSAndroid Build Coastguard Worker void ThreadUtil::CacheData() {
185*795d594fSAndroid Build Coastguard Worker // We must have started since it is now safe to cache our data;
186*795d594fSAndroid Build Coastguard Worker gThreadCallback.started = true;
187*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current();
188*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(self);
189*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Class> thread_class = art::WellKnownClasses::java_lang_Thread.Get();
190*795d594fSAndroid Build Coastguard Worker CHECK(thread_class != nullptr);
191*795d594fSAndroid Build Coastguard Worker context_class_loader_ = thread_class->FindDeclaredInstanceField("contextClassLoader",
192*795d594fSAndroid Build Coastguard Worker "Ljava/lang/ClassLoader;");
193*795d594fSAndroid Build Coastguard Worker CHECK(context_class_loader_ != nullptr);
194*795d594fSAndroid Build Coastguard Worker // Now wait for all required system threads to come up before allowing the rest of loading to
195*795d594fSAndroid Build Coastguard Worker // continue.
196*795d594fSAndroid Build Coastguard Worker WaitForSystemDaemonStart(self);
197*795d594fSAndroid Build Coastguard Worker }
198*795d594fSAndroid Build Coastguard Worker
Unregister()199*795d594fSAndroid Build Coastguard Worker void ThreadUtil::Unregister() {
200*795d594fSAndroid Build Coastguard Worker art::ScopedThreadStateChange stsc(art::Thread::Current(),
201*795d594fSAndroid Build Coastguard Worker art::ThreadState::kWaitingForDebuggerToAttach);
202*795d594fSAndroid Build Coastguard Worker art::ScopedSuspendAll ssa("Remove thread callback");
203*795d594fSAndroid Build Coastguard Worker art::Runtime* runtime = art::Runtime::Current();
204*795d594fSAndroid Build Coastguard Worker runtime->GetRuntimeCallbacks()->RemoveThreadLifecycleCallback(&gThreadCallback);
205*795d594fSAndroid Build Coastguard Worker }
206*795d594fSAndroid Build Coastguard Worker
GetCurrentThread(jvmtiEnv * env,jthread * thread_ptr)207*795d594fSAndroid Build Coastguard Worker jvmtiError ThreadUtil::GetCurrentThread([[maybe_unused]] jvmtiEnv* env, jthread* thread_ptr) {
208*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current();
209*795d594fSAndroid Build Coastguard Worker
210*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(self);
211*795d594fSAndroid Build Coastguard Worker
212*795d594fSAndroid Build Coastguard Worker jthread thread_peer;
213*795d594fSAndroid Build Coastguard Worker if (self->IsStillStarting()) {
214*795d594fSAndroid Build Coastguard Worker thread_peer = nullptr;
215*795d594fSAndroid Build Coastguard Worker } else {
216*795d594fSAndroid Build Coastguard Worker thread_peer = soa.AddLocalReference<jthread>(self->GetPeer());
217*795d594fSAndroid Build Coastguard Worker }
218*795d594fSAndroid Build Coastguard Worker
219*795d594fSAndroid Build Coastguard Worker *thread_ptr = thread_peer;
220*795d594fSAndroid Build Coastguard Worker return ERR(NONE);
221*795d594fSAndroid Build Coastguard Worker }
222*795d594fSAndroid Build Coastguard Worker
223*795d594fSAndroid Build Coastguard Worker // Get the native thread. The spec says a null object denotes the current thread.
GetNativeThread(jthread thread,const art::ScopedObjectAccessAlreadyRunnable & soa,art::Thread ** thr,jvmtiError * err)224*795d594fSAndroid Build Coastguard Worker bool ThreadUtil::GetNativeThread(jthread thread,
225*795d594fSAndroid Build Coastguard Worker const art::ScopedObjectAccessAlreadyRunnable& soa,
226*795d594fSAndroid Build Coastguard Worker /*out*/ art::Thread** thr,
227*795d594fSAndroid Build Coastguard Worker /*out*/ jvmtiError* err) {
228*795d594fSAndroid Build Coastguard Worker art::ScopedExceptionStorage sse(soa.Self());
229*795d594fSAndroid Build Coastguard Worker if (thread == nullptr) {
230*795d594fSAndroid Build Coastguard Worker *thr = art::Thread::Current();
231*795d594fSAndroid Build Coastguard Worker return true;
232*795d594fSAndroid Build Coastguard Worker }
233*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> othread = soa.Decode<art::mirror::Object>(thread);
234*795d594fSAndroid Build Coastguard Worker if (!othread->InstanceOf(art::WellKnownClasses::java_lang_Thread.Get())) {
235*795d594fSAndroid Build Coastguard Worker *err = ERR(INVALID_THREAD);
236*795d594fSAndroid Build Coastguard Worker return false;
237*795d594fSAndroid Build Coastguard Worker } else {
238*795d594fSAndroid Build Coastguard Worker *thr = art::Thread::FromManagedThread(soa, thread);
239*795d594fSAndroid Build Coastguard Worker return true;
240*795d594fSAndroid Build Coastguard Worker }
241*795d594fSAndroid Build Coastguard Worker }
242*795d594fSAndroid Build Coastguard Worker
GetAliveNativeThread(jthread thread,const art::ScopedObjectAccessAlreadyRunnable & soa,art::Thread ** thr,jvmtiError * err)243*795d594fSAndroid Build Coastguard Worker bool ThreadUtil::GetAliveNativeThread(jthread thread,
244*795d594fSAndroid Build Coastguard Worker const art::ScopedObjectAccessAlreadyRunnable& soa,
245*795d594fSAndroid Build Coastguard Worker /*out*/ art::Thread** thr,
246*795d594fSAndroid Build Coastguard Worker /*out*/ jvmtiError* err) {
247*795d594fSAndroid Build Coastguard Worker if (!GetNativeThread(thread, soa, thr, err)) {
248*795d594fSAndroid Build Coastguard Worker return false;
249*795d594fSAndroid Build Coastguard Worker } else if (*thr == nullptr || (*thr)->GetState() == art::ThreadState::kTerminated) {
250*795d594fSAndroid Build Coastguard Worker *err = ERR(THREAD_NOT_ALIVE);
251*795d594fSAndroid Build Coastguard Worker return false;
252*795d594fSAndroid Build Coastguard Worker } else {
253*795d594fSAndroid Build Coastguard Worker return true;
254*795d594fSAndroid Build Coastguard Worker }
255*795d594fSAndroid Build Coastguard Worker }
256*795d594fSAndroid Build Coastguard Worker
GetThreadInfo(jvmtiEnv * env,jthread thread,jvmtiThreadInfo * info_ptr)257*795d594fSAndroid Build Coastguard Worker jvmtiError ThreadUtil::GetThreadInfo(jvmtiEnv* env, jthread thread, jvmtiThreadInfo* info_ptr) {
258*795d594fSAndroid Build Coastguard Worker if (info_ptr == nullptr) {
259*795d594fSAndroid Build Coastguard Worker return ERR(NULL_POINTER);
260*795d594fSAndroid Build Coastguard Worker }
261*795d594fSAndroid Build Coastguard Worker if (!PhaseUtil::IsLivePhase()) {
262*795d594fSAndroid Build Coastguard Worker return JVMTI_ERROR_WRONG_PHASE;
263*795d594fSAndroid Build Coastguard Worker }
264*795d594fSAndroid Build Coastguard Worker
265*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current();
266*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(self);
267*795d594fSAndroid Build Coastguard Worker art::MutexLock mu(self, *art::Locks::thread_list_lock_);
268*795d594fSAndroid Build Coastguard Worker
269*795d594fSAndroid Build Coastguard Worker art::Thread* target;
270*795d594fSAndroid Build Coastguard Worker jvmtiError err = ERR(INTERNAL);
271*795d594fSAndroid Build Coastguard Worker if (!GetNativeThread(thread, soa, &target, &err)) {
272*795d594fSAndroid Build Coastguard Worker return err;
273*795d594fSAndroid Build Coastguard Worker }
274*795d594fSAndroid Build Coastguard Worker
275*795d594fSAndroid Build Coastguard Worker JvmtiUniquePtr<char[]> name_uptr;
276*795d594fSAndroid Build Coastguard Worker if (target != nullptr) {
277*795d594fSAndroid Build Coastguard Worker // Have a native thread object, this thread is alive.
278*795d594fSAndroid Build Coastguard Worker std::string name;
279*795d594fSAndroid Build Coastguard Worker target->GetThreadName(name);
280*795d594fSAndroid Build Coastguard Worker jvmtiError name_result;
281*795d594fSAndroid Build Coastguard Worker name_uptr = CopyString(env, name.c_str(), &name_result);
282*795d594fSAndroid Build Coastguard Worker if (name_uptr == nullptr) {
283*795d594fSAndroid Build Coastguard Worker return name_result;
284*795d594fSAndroid Build Coastguard Worker }
285*795d594fSAndroid Build Coastguard Worker info_ptr->name = name_uptr.get();
286*795d594fSAndroid Build Coastguard Worker
287*795d594fSAndroid Build Coastguard Worker info_ptr->priority = target->GetNativePriority();
288*795d594fSAndroid Build Coastguard Worker
289*795d594fSAndroid Build Coastguard Worker info_ptr->is_daemon = target->IsDaemon();
290*795d594fSAndroid Build Coastguard Worker
291*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> peer = target->LockedGetPeerFromOtherThread();
292*795d594fSAndroid Build Coastguard Worker // *target may be invalid here since we may have temporarily released thread_list_lock_.
293*795d594fSAndroid Build Coastguard Worker target = nullptr; // Value should not be used.
294*795d594fSAndroid Build Coastguard Worker
295*795d594fSAndroid Build Coastguard Worker // ThreadGroup.
296*795d594fSAndroid Build Coastguard Worker if (peer != nullptr) {
297*795d594fSAndroid Build Coastguard Worker art::ArtField* f = art::WellKnownClasses::java_lang_Thread_group;
298*795d594fSAndroid Build Coastguard Worker CHECK(f != nullptr);
299*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> group = f->GetObject(peer);
300*795d594fSAndroid Build Coastguard Worker info_ptr->thread_group = group == nullptr
301*795d594fSAndroid Build Coastguard Worker ? nullptr
302*795d594fSAndroid Build Coastguard Worker : soa.AddLocalReference<jthreadGroup>(group);
303*795d594fSAndroid Build Coastguard Worker } else {
304*795d594fSAndroid Build Coastguard Worker info_ptr->thread_group = nullptr;
305*795d594fSAndroid Build Coastguard Worker }
306*795d594fSAndroid Build Coastguard Worker
307*795d594fSAndroid Build Coastguard Worker // Context classloader.
308*795d594fSAndroid Build Coastguard Worker DCHECK(context_class_loader_ != nullptr);
309*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> ccl = peer != nullptr
310*795d594fSAndroid Build Coastguard Worker ? context_class_loader_->GetObject(peer)
311*795d594fSAndroid Build Coastguard Worker : nullptr;
312*795d594fSAndroid Build Coastguard Worker info_ptr->context_class_loader = ccl == nullptr
313*795d594fSAndroid Build Coastguard Worker ? nullptr
314*795d594fSAndroid Build Coastguard Worker : soa.AddLocalReference<jobject>(ccl);
315*795d594fSAndroid Build Coastguard Worker } else {
316*795d594fSAndroid Build Coastguard Worker // Only the peer. This thread has either not been started, or is dead. Read things from
317*795d594fSAndroid Build Coastguard Worker // the Java side.
318*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> peer = soa.Decode<art::mirror::Object>(thread);
319*795d594fSAndroid Build Coastguard Worker
320*795d594fSAndroid Build Coastguard Worker // Name.
321*795d594fSAndroid Build Coastguard Worker {
322*795d594fSAndroid Build Coastguard Worker art::ArtField* f = art::WellKnownClasses::java_lang_Thread_name;
323*795d594fSAndroid Build Coastguard Worker CHECK(f != nullptr);
324*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> name = f->GetObject(peer);
325*795d594fSAndroid Build Coastguard Worker std::string name_cpp;
326*795d594fSAndroid Build Coastguard Worker const char* name_cstr;
327*795d594fSAndroid Build Coastguard Worker if (name != nullptr) {
328*795d594fSAndroid Build Coastguard Worker name_cpp = name->AsString()->ToModifiedUtf8();
329*795d594fSAndroid Build Coastguard Worker name_cstr = name_cpp.c_str();
330*795d594fSAndroid Build Coastguard Worker } else {
331*795d594fSAndroid Build Coastguard Worker name_cstr = "";
332*795d594fSAndroid Build Coastguard Worker }
333*795d594fSAndroid Build Coastguard Worker jvmtiError name_result;
334*795d594fSAndroid Build Coastguard Worker name_uptr = CopyString(env, name_cstr, &name_result);
335*795d594fSAndroid Build Coastguard Worker if (name_uptr == nullptr) {
336*795d594fSAndroid Build Coastguard Worker return name_result;
337*795d594fSAndroid Build Coastguard Worker }
338*795d594fSAndroid Build Coastguard Worker info_ptr->name = name_uptr.get();
339*795d594fSAndroid Build Coastguard Worker }
340*795d594fSAndroid Build Coastguard Worker
341*795d594fSAndroid Build Coastguard Worker // Priority.
342*795d594fSAndroid Build Coastguard Worker {
343*795d594fSAndroid Build Coastguard Worker art::ArtField* f = art::WellKnownClasses::java_lang_Thread_priority;
344*795d594fSAndroid Build Coastguard Worker CHECK(f != nullptr);
345*795d594fSAndroid Build Coastguard Worker info_ptr->priority = static_cast<jint>(f->GetInt(peer));
346*795d594fSAndroid Build Coastguard Worker }
347*795d594fSAndroid Build Coastguard Worker
348*795d594fSAndroid Build Coastguard Worker // Daemon.
349*795d594fSAndroid Build Coastguard Worker {
350*795d594fSAndroid Build Coastguard Worker art::ArtField* f = art::WellKnownClasses::java_lang_Thread_daemon;
351*795d594fSAndroid Build Coastguard Worker CHECK(f != nullptr);
352*795d594fSAndroid Build Coastguard Worker info_ptr->is_daemon = f->GetBoolean(peer) == 0 ? JNI_FALSE : JNI_TRUE;
353*795d594fSAndroid Build Coastguard Worker }
354*795d594fSAndroid Build Coastguard Worker
355*795d594fSAndroid Build Coastguard Worker // ThreadGroup.
356*795d594fSAndroid Build Coastguard Worker {
357*795d594fSAndroid Build Coastguard Worker art::ArtField* f = art::WellKnownClasses::java_lang_Thread_group;
358*795d594fSAndroid Build Coastguard Worker CHECK(f != nullptr);
359*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> group = f->GetObject(peer);
360*795d594fSAndroid Build Coastguard Worker info_ptr->thread_group = group == nullptr
361*795d594fSAndroid Build Coastguard Worker ? nullptr
362*795d594fSAndroid Build Coastguard Worker : soa.AddLocalReference<jthreadGroup>(group);
363*795d594fSAndroid Build Coastguard Worker }
364*795d594fSAndroid Build Coastguard Worker
365*795d594fSAndroid Build Coastguard Worker // Context classloader.
366*795d594fSAndroid Build Coastguard Worker DCHECK(context_class_loader_ != nullptr);
367*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> ccl = peer != nullptr
368*795d594fSAndroid Build Coastguard Worker ? context_class_loader_->GetObject(peer)
369*795d594fSAndroid Build Coastguard Worker : nullptr;
370*795d594fSAndroid Build Coastguard Worker info_ptr->context_class_loader = ccl == nullptr
371*795d594fSAndroid Build Coastguard Worker ? nullptr
372*795d594fSAndroid Build Coastguard Worker : soa.AddLocalReference<jobject>(ccl);
373*795d594fSAndroid Build Coastguard Worker }
374*795d594fSAndroid Build Coastguard Worker
375*795d594fSAndroid Build Coastguard Worker name_uptr.release();
376*795d594fSAndroid Build Coastguard Worker
377*795d594fSAndroid Build Coastguard Worker return ERR(NONE);
378*795d594fSAndroid Build Coastguard Worker }
379*795d594fSAndroid Build Coastguard Worker
380*795d594fSAndroid Build Coastguard Worker struct InternalThreadState {
381*795d594fSAndroid Build Coastguard Worker art::Thread* native_thread;
382*795d594fSAndroid Build Coastguard Worker art::ThreadState art_state;
383*795d594fSAndroid Build Coastguard Worker int thread_user_code_suspend_count;
384*795d594fSAndroid Build Coastguard Worker };
385*795d594fSAndroid Build Coastguard Worker
386*795d594fSAndroid Build Coastguard Worker // Return the thread's (or current thread, if null) thread state.
GetNativeThreadState(art::Thread * target)387*795d594fSAndroid Build Coastguard Worker static InternalThreadState GetNativeThreadState(art::Thread* target)
388*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_)
389*795d594fSAndroid Build Coastguard Worker REQUIRES(art::Locks::thread_list_lock_, art::Locks::user_code_suspension_lock_) {
390*795d594fSAndroid Build Coastguard Worker InternalThreadState thread_state = {};
391*795d594fSAndroid Build Coastguard Worker art::MutexLock tscl_mu(art::Thread::Current(), *art::Locks::thread_suspend_count_lock_);
392*795d594fSAndroid Build Coastguard Worker thread_state.native_thread = target;
393*795d594fSAndroid Build Coastguard Worker if (target == nullptr || target->IsStillStarting()) {
394*795d594fSAndroid Build Coastguard Worker thread_state.art_state = art::ThreadState::kStarting;
395*795d594fSAndroid Build Coastguard Worker thread_state.thread_user_code_suspend_count = 0;
396*795d594fSAndroid Build Coastguard Worker } else {
397*795d594fSAndroid Build Coastguard Worker thread_state.art_state = target->GetState();
398*795d594fSAndroid Build Coastguard Worker thread_state.thread_user_code_suspend_count = target->GetUserCodeSuspendCount();
399*795d594fSAndroid Build Coastguard Worker }
400*795d594fSAndroid Build Coastguard Worker return thread_state;
401*795d594fSAndroid Build Coastguard Worker }
402*795d594fSAndroid Build Coastguard Worker
GetJvmtiThreadStateFromInternal(const InternalThreadState & state)403*795d594fSAndroid Build Coastguard Worker static jint GetJvmtiThreadStateFromInternal(const InternalThreadState& state) {
404*795d594fSAndroid Build Coastguard Worker art::ThreadState internal_thread_state = state.art_state;
405*795d594fSAndroid Build Coastguard Worker jint jvmti_state = JVMTI_THREAD_STATE_ALIVE;
406*795d594fSAndroid Build Coastguard Worker
407*795d594fSAndroid Build Coastguard Worker if (state.thread_user_code_suspend_count != 0) {
408*795d594fSAndroid Build Coastguard Worker // Suspended can be set with any thread state so check it here. Even if the thread isn't in
409*795d594fSAndroid Build Coastguard Worker // kSuspended state it will move to that once it hits a checkpoint so we can still set this.
410*795d594fSAndroid Build Coastguard Worker jvmti_state |= JVMTI_THREAD_STATE_SUSPENDED;
411*795d594fSAndroid Build Coastguard Worker // Note: We do not have data about the previous state. Otherwise we should load the previous
412*795d594fSAndroid Build Coastguard Worker // state here.
413*795d594fSAndroid Build Coastguard Worker }
414*795d594fSAndroid Build Coastguard Worker
415*795d594fSAndroid Build Coastguard Worker if (state.native_thread->IsInterrupted()) {
416*795d594fSAndroid Build Coastguard Worker // Interrupted can be set with any thread state so check it here.
417*795d594fSAndroid Build Coastguard Worker jvmti_state |= JVMTI_THREAD_STATE_INTERRUPTED;
418*795d594fSAndroid Build Coastguard Worker }
419*795d594fSAndroid Build Coastguard Worker
420*795d594fSAndroid Build Coastguard Worker // Enumerate all the thread states and fill in the other bits. This contains the results of
421*795d594fSAndroid Build Coastguard Worker // following the decision tree in the JVMTI spec GetThreadState documentation.
422*795d594fSAndroid Build Coastguard Worker switch (internal_thread_state) {
423*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kRunnable:
424*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingWeakGcRootRead:
425*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kSuspended:
426*795d594fSAndroid Build Coastguard Worker // These are all simply runnable.
427*795d594fSAndroid Build Coastguard Worker // kRunnable is self-explanatory.
428*795d594fSAndroid Build Coastguard Worker // kWaitingWeakGcRootRead is set during some operations with strings due to the intern-table
429*795d594fSAndroid Build Coastguard Worker // so we want to keep it marked as runnable.
430*795d594fSAndroid Build Coastguard Worker // kSuspended we don't mark since if we don't have a user_code_suspend_count then it is done
431*795d594fSAndroid Build Coastguard Worker // by the GC and not a JVMTI suspension, which means it cannot be removed by ResumeThread.
432*795d594fSAndroid Build Coastguard Worker jvmti_state |= JVMTI_THREAD_STATE_RUNNABLE;
433*795d594fSAndroid Build Coastguard Worker break;
434*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kNative:
435*795d594fSAndroid Build Coastguard Worker // kNative means native and runnable. Technically THREAD_STATE_IN_NATIVE can be set with any
436*795d594fSAndroid Build Coastguard Worker // state but we don't have the information to know if it should be present for any but the
437*795d594fSAndroid Build Coastguard Worker // kNative state.
438*795d594fSAndroid Build Coastguard Worker jvmti_state |= (JVMTI_THREAD_STATE_IN_NATIVE |
439*795d594fSAndroid Build Coastguard Worker JVMTI_THREAD_STATE_RUNNABLE);
440*795d594fSAndroid Build Coastguard Worker break;
441*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kBlocked:
442*795d594fSAndroid Build Coastguard Worker // Blocked is one of the top level states so it sits alone.
443*795d594fSAndroid Build Coastguard Worker jvmti_state |= JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
444*795d594fSAndroid Build Coastguard Worker break;
445*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaiting:
446*795d594fSAndroid Build Coastguard Worker // Object.wait() so waiting, indefinitely, in object.wait.
447*795d594fSAndroid Build Coastguard Worker jvmti_state |= (JVMTI_THREAD_STATE_WAITING |
448*795d594fSAndroid Build Coastguard Worker JVMTI_THREAD_STATE_WAITING_INDEFINITELY |
449*795d594fSAndroid Build Coastguard Worker JVMTI_THREAD_STATE_IN_OBJECT_WAIT);
450*795d594fSAndroid Build Coastguard Worker break;
451*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kTimedWaiting:
452*795d594fSAndroid Build Coastguard Worker // Object.wait(long) so waiting, with timeout, in object.wait.
453*795d594fSAndroid Build Coastguard Worker jvmti_state |= (JVMTI_THREAD_STATE_WAITING |
454*795d594fSAndroid Build Coastguard Worker JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT |
455*795d594fSAndroid Build Coastguard Worker JVMTI_THREAD_STATE_IN_OBJECT_WAIT);
456*795d594fSAndroid Build Coastguard Worker break;
457*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kSleeping:
458*795d594fSAndroid Build Coastguard Worker // In object.sleep. This is a timed wait caused by sleep.
459*795d594fSAndroid Build Coastguard Worker jvmti_state |= (JVMTI_THREAD_STATE_WAITING |
460*795d594fSAndroid Build Coastguard Worker JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT |
461*795d594fSAndroid Build Coastguard Worker JVMTI_THREAD_STATE_SLEEPING);
462*795d594fSAndroid Build Coastguard Worker break;
463*795d594fSAndroid Build Coastguard Worker // TODO We might want to print warnings if we have the debugger running while JVMTI agents are
464*795d594fSAndroid Build Coastguard Worker // attached.
465*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForDebuggerSend:
466*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForDebuggerToAttach:
467*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingInMainDebuggerLoop:
468*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForDebuggerSuspension:
469*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForLockInflation:
470*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForTaskProcessor:
471*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForGcToComplete:
472*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForCheckPointsToRun:
473*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingPerformingGc:
474*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForJniOnLoad:
475*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingInMainSignalCatcherLoop:
476*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForSignalCatcherOutput:
477*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForDeoptimization:
478*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForMethodTracingStart:
479*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForVisitObjects:
480*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForGetObjectsAllocated:
481*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForGcThreadFlip:
482*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kNativeForAbort:
483*795d594fSAndroid Build Coastguard Worker // All of these are causing the thread to wait for an indeterminate amount of time but isn't
484*795d594fSAndroid Build Coastguard Worker // caused by sleep, park, or object#wait.
485*795d594fSAndroid Build Coastguard Worker jvmti_state |= (JVMTI_THREAD_STATE_WAITING |
486*795d594fSAndroid Build Coastguard Worker JVMTI_THREAD_STATE_WAITING_INDEFINITELY);
487*795d594fSAndroid Build Coastguard Worker break;
488*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kObsoleteRunnable: // Obsolete value.
489*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kStarting:
490*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kTerminated:
491*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kInvalidState:
492*795d594fSAndroid Build Coastguard Worker // We only call this if we are alive so we shouldn't see either of these states.
493*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Should not be in state " << internal_thread_state;
494*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
495*795d594fSAndroid Build Coastguard Worker }
496*795d594fSAndroid Build Coastguard Worker // TODO: PARKED. We'll have to inspect the stack.
497*795d594fSAndroid Build Coastguard Worker
498*795d594fSAndroid Build Coastguard Worker return jvmti_state;
499*795d594fSAndroid Build Coastguard Worker }
500*795d594fSAndroid Build Coastguard Worker
GetJavaStateFromInternal(const InternalThreadState & state)501*795d594fSAndroid Build Coastguard Worker static jint GetJavaStateFromInternal(const InternalThreadState& state) {
502*795d594fSAndroid Build Coastguard Worker switch (state.art_state) {
503*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kTerminated:
504*795d594fSAndroid Build Coastguard Worker return JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED;
505*795d594fSAndroid Build Coastguard Worker
506*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kRunnable:
507*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kNative:
508*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingWeakGcRootRead:
509*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kSuspended:
510*795d594fSAndroid Build Coastguard Worker return JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE;
511*795d594fSAndroid Build Coastguard Worker
512*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kTimedWaiting:
513*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kSleeping:
514*795d594fSAndroid Build Coastguard Worker return JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING;
515*795d594fSAndroid Build Coastguard Worker
516*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kBlocked:
517*795d594fSAndroid Build Coastguard Worker return JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED;
518*795d594fSAndroid Build Coastguard Worker
519*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kStarting:
520*795d594fSAndroid Build Coastguard Worker return JVMTI_JAVA_LANG_THREAD_STATE_NEW;
521*795d594fSAndroid Build Coastguard Worker
522*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaiting:
523*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForTaskProcessor:
524*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForLockInflation:
525*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForGcToComplete:
526*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingPerformingGc:
527*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForCheckPointsToRun:
528*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForDebuggerSend:
529*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForDebuggerToAttach:
530*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingInMainDebuggerLoop:
531*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForDebuggerSuspension:
532*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForDeoptimization:
533*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForGetObjectsAllocated:
534*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForJniOnLoad:
535*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForSignalCatcherOutput:
536*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingInMainSignalCatcherLoop:
537*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForMethodTracingStart:
538*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForVisitObjects:
539*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kWaitingForGcThreadFlip:
540*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kNativeForAbort:
541*795d594fSAndroid Build Coastguard Worker return JVMTI_JAVA_LANG_THREAD_STATE_WAITING;
542*795d594fSAndroid Build Coastguard Worker
543*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kObsoleteRunnable:
544*795d594fSAndroid Build Coastguard Worker case art::ThreadState::kInvalidState:
545*795d594fSAndroid Build Coastguard Worker break; // Obsolete or invalid value.
546*795d594fSAndroid Build Coastguard Worker }
547*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unreachable";
548*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
549*795d594fSAndroid Build Coastguard Worker }
550*795d594fSAndroid Build Coastguard Worker
551*795d594fSAndroid Build Coastguard Worker // Suspends the current thread if it has any suspend requests on it.
SuspendCheck(art::Thread * self)552*795d594fSAndroid Build Coastguard Worker void ThreadUtil::SuspendCheck(art::Thread* self) {
553*795d594fSAndroid Build Coastguard Worker DCHECK(!self->ReadFlag(art::ThreadFlag::kSuspensionImmune));
554*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(self);
555*795d594fSAndroid Build Coastguard Worker // Really this is only needed if we are in FastJNI and actually have the mutator_lock_ already.
556*795d594fSAndroid Build Coastguard Worker self->FullSuspendCheck();
557*795d594fSAndroid Build Coastguard Worker }
558*795d594fSAndroid Build Coastguard Worker
WouldSuspendForUserCodeLocked(art::Thread * self)559*795d594fSAndroid Build Coastguard Worker bool ThreadUtil::WouldSuspendForUserCodeLocked(art::Thread* self) {
560*795d594fSAndroid Build Coastguard Worker DCHECK(self == art::Thread::Current());
561*795d594fSAndroid Build Coastguard Worker art::MutexLock tscl_mu(self, *art::Locks::thread_suspend_count_lock_);
562*795d594fSAndroid Build Coastguard Worker return self->GetUserCodeSuspendCount() != 0;
563*795d594fSAndroid Build Coastguard Worker }
564*795d594fSAndroid Build Coastguard Worker
WouldSuspendForUserCode(art::Thread * self)565*795d594fSAndroid Build Coastguard Worker bool ThreadUtil::WouldSuspendForUserCode(art::Thread* self) {
566*795d594fSAndroid Build Coastguard Worker DCHECK(self == art::Thread::Current());
567*795d594fSAndroid Build Coastguard Worker art::MutexLock ucsl_mu(self, *art::Locks::user_code_suspension_lock_);
568*795d594fSAndroid Build Coastguard Worker return WouldSuspendForUserCodeLocked(self);
569*795d594fSAndroid Build Coastguard Worker }
570*795d594fSAndroid Build Coastguard Worker
GetThreadState(jvmtiEnv * env,jthread thread,jint * thread_state_ptr)571*795d594fSAndroid Build Coastguard Worker jvmtiError ThreadUtil::GetThreadState([[maybe_unused]] jvmtiEnv* env,
572*795d594fSAndroid Build Coastguard Worker jthread thread,
573*795d594fSAndroid Build Coastguard Worker jint* thread_state_ptr) {
574*795d594fSAndroid Build Coastguard Worker if (thread_state_ptr == nullptr) {
575*795d594fSAndroid Build Coastguard Worker return ERR(NULL_POINTER);
576*795d594fSAndroid Build Coastguard Worker }
577*795d594fSAndroid Build Coastguard Worker
578*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current();
579*795d594fSAndroid Build Coastguard Worker InternalThreadState state = {};
580*795d594fSAndroid Build Coastguard Worker {
581*795d594fSAndroid Build Coastguard Worker ScopedNoUserCodeSuspension snucs(self);
582*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(self);
583*795d594fSAndroid Build Coastguard Worker art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_);
584*795d594fSAndroid Build Coastguard Worker jvmtiError err = ERR(INTERNAL);
585*795d594fSAndroid Build Coastguard Worker art::Thread* target = nullptr;
586*795d594fSAndroid Build Coastguard Worker if (!GetNativeThread(thread, soa, &target, &err)) {
587*795d594fSAndroid Build Coastguard Worker return err;
588*795d594fSAndroid Build Coastguard Worker }
589*795d594fSAndroid Build Coastguard Worker state = GetNativeThreadState(target);
590*795d594fSAndroid Build Coastguard Worker if (state.art_state != art::ThreadState::kStarting) {
591*795d594fSAndroid Build Coastguard Worker DCHECK(state.native_thread != nullptr);
592*795d594fSAndroid Build Coastguard Worker
593*795d594fSAndroid Build Coastguard Worker // Translate internal thread state to JVMTI and Java state.
594*795d594fSAndroid Build Coastguard Worker jint jvmti_state = GetJvmtiThreadStateFromInternal(state);
595*795d594fSAndroid Build Coastguard Worker
596*795d594fSAndroid Build Coastguard Worker // Java state is derived from nativeGetState.
597*795d594fSAndroid Build Coastguard Worker // TODO: Our implementation assigns "runnable" to suspended. As such, we will have slightly
598*795d594fSAndroid Build Coastguard Worker // different mask if a thread got suspended due to user-code. However, this is for
599*795d594fSAndroid Build Coastguard Worker // consistency with the Java view.
600*795d594fSAndroid Build Coastguard Worker jint java_state = GetJavaStateFromInternal(state);
601*795d594fSAndroid Build Coastguard Worker
602*795d594fSAndroid Build Coastguard Worker *thread_state_ptr = jvmti_state | java_state;
603*795d594fSAndroid Build Coastguard Worker
604*795d594fSAndroid Build Coastguard Worker return ERR(NONE);
605*795d594fSAndroid Build Coastguard Worker }
606*795d594fSAndroid Build Coastguard Worker }
607*795d594fSAndroid Build Coastguard Worker
608*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(state.art_state, art::ThreadState::kStarting);
609*795d594fSAndroid Build Coastguard Worker
610*795d594fSAndroid Build Coastguard Worker if (thread == nullptr) {
611*795d594fSAndroid Build Coastguard Worker // No native thread, and no Java thread? We must be starting up. Report as wrong phase.
612*795d594fSAndroid Build Coastguard Worker return ERR(WRONG_PHASE);
613*795d594fSAndroid Build Coastguard Worker }
614*795d594fSAndroid Build Coastguard Worker
615*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(self);
616*795d594fSAndroid Build Coastguard Worker art::StackHandleScope<1> hs(self);
617*795d594fSAndroid Build Coastguard Worker
618*795d594fSAndroid Build Coastguard Worker // Need to read the Java "started" field to know whether this is starting or terminated.
619*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Object> peer(hs.NewHandle(soa.Decode<art::mirror::Object>(thread)));
620*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Class> thread_klass = art::WellKnownClasses::java_lang_Thread.Get();
621*795d594fSAndroid Build Coastguard Worker if (!thread_klass->IsAssignableFrom(peer->GetClass())) {
622*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_THREAD);
623*795d594fSAndroid Build Coastguard Worker }
624*795d594fSAndroid Build Coastguard Worker art::ArtField* started_field = thread_klass->FindDeclaredInstanceField("started", "Z");
625*795d594fSAndroid Build Coastguard Worker CHECK(started_field != nullptr);
626*795d594fSAndroid Build Coastguard Worker bool started = started_field->GetBoolean(peer.Get()) != 0;
627*795d594fSAndroid Build Coastguard Worker constexpr jint kStartedState = JVMTI_JAVA_LANG_THREAD_STATE_NEW;
628*795d594fSAndroid Build Coastguard Worker constexpr jint kTerminatedState = JVMTI_THREAD_STATE_TERMINATED |
629*795d594fSAndroid Build Coastguard Worker JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED;
630*795d594fSAndroid Build Coastguard Worker *thread_state_ptr = started ? kTerminatedState : kStartedState;
631*795d594fSAndroid Build Coastguard Worker return ERR(NONE);
632*795d594fSAndroid Build Coastguard Worker }
633*795d594fSAndroid Build Coastguard Worker
GetAllThreads(jvmtiEnv * env,jint * threads_count_ptr,jthread ** threads_ptr)634*795d594fSAndroid Build Coastguard Worker jvmtiError ThreadUtil::GetAllThreads(jvmtiEnv* env,
635*795d594fSAndroid Build Coastguard Worker jint* threads_count_ptr,
636*795d594fSAndroid Build Coastguard Worker jthread** threads_ptr) {
637*795d594fSAndroid Build Coastguard Worker if (threads_count_ptr == nullptr || threads_ptr == nullptr) {
638*795d594fSAndroid Build Coastguard Worker return ERR(NULL_POINTER);
639*795d594fSAndroid Build Coastguard Worker }
640*795d594fSAndroid Build Coastguard Worker
641*795d594fSAndroid Build Coastguard Worker art::Thread* current = art::Thread::Current();
642*795d594fSAndroid Build Coastguard Worker
643*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(current);
644*795d594fSAndroid Build Coastguard Worker
645*795d594fSAndroid Build Coastguard Worker art::MutexLock mu(current, *art::Locks::thread_list_lock_);
646*795d594fSAndroid Build Coastguard Worker std::list<art::Thread*> thread_list = art::Runtime::Current()->GetThreadList()->GetList();
647*795d594fSAndroid Build Coastguard Worker // We have to be careful with threads exiting while we build this list.
648*795d594fSAndroid Build Coastguard Worker std::vector<art::ThreadExitFlag> tefs(thread_list.size());
649*795d594fSAndroid Build Coastguard Worker auto i = tefs.begin();
650*795d594fSAndroid Build Coastguard Worker for (art::Thread* thd : thread_list) {
651*795d594fSAndroid Build Coastguard Worker thd->NotifyOnThreadExit(&*i++);
652*795d594fSAndroid Build Coastguard Worker }
653*795d594fSAndroid Build Coastguard Worker DCHECK(i == tefs.end());
654*795d594fSAndroid Build Coastguard Worker
655*795d594fSAndroid Build Coastguard Worker std::vector<art::ObjPtr<art::mirror::Object>> peers;
656*795d594fSAndroid Build Coastguard Worker
657*795d594fSAndroid Build Coastguard Worker i = tefs.begin();
658*795d594fSAndroid Build Coastguard Worker for (art::Thread* thread : thread_list) {
659*795d594fSAndroid Build Coastguard Worker art::ThreadExitFlag* tef = &*i++;
660*795d594fSAndroid Build Coastguard Worker // Skip threads that have since exited or are still starting.
661*795d594fSAndroid Build Coastguard Worker if (!tef->HasExited() && !thread->IsStillStarting()) {
662*795d594fSAndroid Build Coastguard Worker // LockedGetPeerFromOtherThreads() may release lock!
663*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> peer = thread->LockedGetPeerFromOtherThread(tef);
664*795d594fSAndroid Build Coastguard Worker if (peer != nullptr) {
665*795d594fSAndroid Build Coastguard Worker peers.push_back(peer);
666*795d594fSAndroid Build Coastguard Worker }
667*795d594fSAndroid Build Coastguard Worker }
668*795d594fSAndroid Build Coastguard Worker thread->UnregisterThreadExitFlag(tef);
669*795d594fSAndroid Build Coastguard Worker }
670*795d594fSAndroid Build Coastguard Worker DCHECK(i == tefs.end());
671*795d594fSAndroid Build Coastguard Worker
672*795d594fSAndroid Build Coastguard Worker if (peers.empty()) {
673*795d594fSAndroid Build Coastguard Worker *threads_count_ptr = 0;
674*795d594fSAndroid Build Coastguard Worker *threads_ptr = nullptr;
675*795d594fSAndroid Build Coastguard Worker } else {
676*795d594fSAndroid Build Coastguard Worker unsigned char* data;
677*795d594fSAndroid Build Coastguard Worker jvmtiError data_result = env->Allocate(peers.size() * sizeof(jthread), &data);
678*795d594fSAndroid Build Coastguard Worker if (data_result != ERR(NONE)) {
679*795d594fSAndroid Build Coastguard Worker return data_result;
680*795d594fSAndroid Build Coastguard Worker }
681*795d594fSAndroid Build Coastguard Worker jthread* threads = reinterpret_cast<jthread*>(data);
682*795d594fSAndroid Build Coastguard Worker for (size_t j = 0; j != peers.size(); ++j) {
683*795d594fSAndroid Build Coastguard Worker threads[j] = soa.AddLocalReference<jthread>(peers[j]);
684*795d594fSAndroid Build Coastguard Worker }
685*795d594fSAndroid Build Coastguard Worker
686*795d594fSAndroid Build Coastguard Worker *threads_count_ptr = static_cast<jint>(peers.size());
687*795d594fSAndroid Build Coastguard Worker *threads_ptr = threads;
688*795d594fSAndroid Build Coastguard Worker }
689*795d594fSAndroid Build Coastguard Worker return ERR(NONE);
690*795d594fSAndroid Build Coastguard Worker }
691*795d594fSAndroid Build Coastguard Worker
RemoveTLSData(art::Thread * target,void * ctx)692*795d594fSAndroid Build Coastguard Worker static void RemoveTLSData(art::Thread* target, void* ctx) REQUIRES(art::Locks::thread_list_lock_) {
693*795d594fSAndroid Build Coastguard Worker jvmtiEnv* env = reinterpret_cast<jvmtiEnv*>(ctx);
694*795d594fSAndroid Build Coastguard Worker art::Locks::thread_list_lock_->AssertHeld(art::Thread::Current());
695*795d594fSAndroid Build Coastguard Worker JvmtiGlobalTLSData* global_tls = ThreadUtil::GetGlobalTLSData(target);
696*795d594fSAndroid Build Coastguard Worker if (global_tls != nullptr) {
697*795d594fSAndroid Build Coastguard Worker global_tls->data.erase(env);
698*795d594fSAndroid Build Coastguard Worker }
699*795d594fSAndroid Build Coastguard Worker }
700*795d594fSAndroid Build Coastguard Worker
RemoveEnvironment(jvmtiEnv * env)701*795d594fSAndroid Build Coastguard Worker void ThreadUtil::RemoveEnvironment(jvmtiEnv* env) {
702*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current();
703*795d594fSAndroid Build Coastguard Worker art::MutexLock mu(self, *art::Locks::thread_list_lock_);
704*795d594fSAndroid Build Coastguard Worker art::ThreadList* list = art::Runtime::Current()->GetThreadList();
705*795d594fSAndroid Build Coastguard Worker list->ForEach(RemoveTLSData, env);
706*795d594fSAndroid Build Coastguard Worker }
707*795d594fSAndroid Build Coastguard Worker
SetThreadLocalStorage(jvmtiEnv * env,jthread thread,const void * data)708*795d594fSAndroid Build Coastguard Worker jvmtiError ThreadUtil::SetThreadLocalStorage(jvmtiEnv* env, jthread thread, const void* data) {
709*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current();
710*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(self);
711*795d594fSAndroid Build Coastguard Worker art::MutexLock mu(self, *art::Locks::thread_list_lock_);
712*795d594fSAndroid Build Coastguard Worker art::Thread* target = nullptr;
713*795d594fSAndroid Build Coastguard Worker jvmtiError err = ERR(INTERNAL);
714*795d594fSAndroid Build Coastguard Worker if (!GetAliveNativeThread(thread, soa, &target, &err)) {
715*795d594fSAndroid Build Coastguard Worker return err;
716*795d594fSAndroid Build Coastguard Worker }
717*795d594fSAndroid Build Coastguard Worker
718*795d594fSAndroid Build Coastguard Worker JvmtiGlobalTLSData* global_tls = GetOrCreateGlobalTLSData(target);
719*795d594fSAndroid Build Coastguard Worker
720*795d594fSAndroid Build Coastguard Worker global_tls->data[env] = data;
721*795d594fSAndroid Build Coastguard Worker
722*795d594fSAndroid Build Coastguard Worker return ERR(NONE);
723*795d594fSAndroid Build Coastguard Worker }
724*795d594fSAndroid Build Coastguard Worker
GetOrCreateGlobalTLSData(art::Thread * thread)725*795d594fSAndroid Build Coastguard Worker JvmtiGlobalTLSData* ThreadUtil::GetOrCreateGlobalTLSData(art::Thread* thread) {
726*795d594fSAndroid Build Coastguard Worker JvmtiGlobalTLSData* data = GetGlobalTLSData(thread);
727*795d594fSAndroid Build Coastguard Worker if (data != nullptr) {
728*795d594fSAndroid Build Coastguard Worker return data;
729*795d594fSAndroid Build Coastguard Worker } else {
730*795d594fSAndroid Build Coastguard Worker thread->SetCustomTLS(kJvmtiTlsKey, new JvmtiGlobalTLSData);
731*795d594fSAndroid Build Coastguard Worker return GetGlobalTLSData(thread);
732*795d594fSAndroid Build Coastguard Worker }
733*795d594fSAndroid Build Coastguard Worker }
734*795d594fSAndroid Build Coastguard Worker
GetGlobalTLSData(art::Thread * thread)735*795d594fSAndroid Build Coastguard Worker JvmtiGlobalTLSData* ThreadUtil::GetGlobalTLSData(art::Thread* thread) {
736*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<JvmtiGlobalTLSData*>(thread->GetCustomTLS(kJvmtiTlsKey));
737*795d594fSAndroid Build Coastguard Worker }
738*795d594fSAndroid Build Coastguard Worker
GetThreadLocalStorage(jvmtiEnv * env,jthread thread,void ** data_ptr)739*795d594fSAndroid Build Coastguard Worker jvmtiError ThreadUtil::GetThreadLocalStorage(jvmtiEnv* env,
740*795d594fSAndroid Build Coastguard Worker jthread thread,
741*795d594fSAndroid Build Coastguard Worker void** data_ptr) {
742*795d594fSAndroid Build Coastguard Worker if (data_ptr == nullptr) {
743*795d594fSAndroid Build Coastguard Worker return ERR(NULL_POINTER);
744*795d594fSAndroid Build Coastguard Worker }
745*795d594fSAndroid Build Coastguard Worker
746*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current();
747*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(self);
748*795d594fSAndroid Build Coastguard Worker art::MutexLock mu(self, *art::Locks::thread_list_lock_);
749*795d594fSAndroid Build Coastguard Worker art::Thread* target = nullptr;
750*795d594fSAndroid Build Coastguard Worker jvmtiError err = ERR(INTERNAL);
751*795d594fSAndroid Build Coastguard Worker if (!GetAliveNativeThread(thread, soa, &target, &err)) {
752*795d594fSAndroid Build Coastguard Worker return err;
753*795d594fSAndroid Build Coastguard Worker }
754*795d594fSAndroid Build Coastguard Worker
755*795d594fSAndroid Build Coastguard Worker JvmtiGlobalTLSData* global_tls = GetGlobalTLSData(target);
756*795d594fSAndroid Build Coastguard Worker if (global_tls == nullptr) {
757*795d594fSAndroid Build Coastguard Worker *data_ptr = nullptr;
758*795d594fSAndroid Build Coastguard Worker return OK;
759*795d594fSAndroid Build Coastguard Worker }
760*795d594fSAndroid Build Coastguard Worker auto it = global_tls->data.find(env);
761*795d594fSAndroid Build Coastguard Worker if (it != global_tls->data.end()) {
762*795d594fSAndroid Build Coastguard Worker *data_ptr = const_cast<void*>(it->second);
763*795d594fSAndroid Build Coastguard Worker } else {
764*795d594fSAndroid Build Coastguard Worker *data_ptr = nullptr;
765*795d594fSAndroid Build Coastguard Worker }
766*795d594fSAndroid Build Coastguard Worker
767*795d594fSAndroid Build Coastguard Worker return ERR(NONE);
768*795d594fSAndroid Build Coastguard Worker }
769*795d594fSAndroid Build Coastguard Worker
770*795d594fSAndroid Build Coastguard Worker struct AgentData {
771*795d594fSAndroid Build Coastguard Worker const void* arg;
772*795d594fSAndroid Build Coastguard Worker jvmtiStartFunction proc;
773*795d594fSAndroid Build Coastguard Worker jthread thread;
774*795d594fSAndroid Build Coastguard Worker JavaVM* java_vm;
775*795d594fSAndroid Build Coastguard Worker jvmtiEnv* jvmti_env;
776*795d594fSAndroid Build Coastguard Worker jint priority;
777*795d594fSAndroid Build Coastguard Worker std::string name;
778*795d594fSAndroid Build Coastguard Worker };
779*795d594fSAndroid Build Coastguard Worker
AgentCallback(void * arg)780*795d594fSAndroid Build Coastguard Worker static void* AgentCallback(void* arg) {
781*795d594fSAndroid Build Coastguard Worker std::unique_ptr<AgentData> data(reinterpret_cast<AgentData*>(arg));
782*795d594fSAndroid Build Coastguard Worker CHECK(data->thread != nullptr);
783*795d594fSAndroid Build Coastguard Worker
784*795d594fSAndroid Build Coastguard Worker // We already have a peer. So call our special Attach function.
785*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Attach(data->name.c_str(), true, data->thread);
786*795d594fSAndroid Build Coastguard Worker CHECK(self != nullptr) << "threads_being_born_ should have ensured thread could be attached.";
787*795d594fSAndroid Build Coastguard Worker // The name in Attach() is only for logging. Set the thread name. This is important so
788*795d594fSAndroid Build Coastguard Worker // that the thread is no longer seen as starting up.
789*795d594fSAndroid Build Coastguard Worker {
790*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(self);
791*795d594fSAndroid Build Coastguard Worker self->SetThreadName(data->name.c_str());
792*795d594fSAndroid Build Coastguard Worker }
793*795d594fSAndroid Build Coastguard Worker
794*795d594fSAndroid Build Coastguard Worker // Release the peer.
795*795d594fSAndroid Build Coastguard Worker JNIEnv* env = self->GetJniEnv();
796*795d594fSAndroid Build Coastguard Worker env->DeleteGlobalRef(data->thread);
797*795d594fSAndroid Build Coastguard Worker data->thread = nullptr;
798*795d594fSAndroid Build Coastguard Worker
799*795d594fSAndroid Build Coastguard Worker {
800*795d594fSAndroid Build Coastguard Worker // The StartThreadBirth was called in the parent thread. We let the runtime know we are up
801*795d594fSAndroid Build Coastguard Worker // before going into the provided code.
802*795d594fSAndroid Build Coastguard Worker art::MutexLock mu(art::Thread::Current(), *art::Locks::runtime_shutdown_lock_);
803*795d594fSAndroid Build Coastguard Worker art::Runtime::Current()->EndThreadBirth();
804*795d594fSAndroid Build Coastguard Worker }
805*795d594fSAndroid Build Coastguard Worker
806*795d594fSAndroid Build Coastguard Worker // Run the agent code.
807*795d594fSAndroid Build Coastguard Worker data->proc(data->jvmti_env, env, const_cast<void*>(data->arg));
808*795d594fSAndroid Build Coastguard Worker
809*795d594fSAndroid Build Coastguard Worker // Detach the thread.
810*795d594fSAndroid Build Coastguard Worker int detach_result = data->java_vm->DetachCurrentThread();
811*795d594fSAndroid Build Coastguard Worker CHECK_EQ(detach_result, 0);
812*795d594fSAndroid Build Coastguard Worker
813*795d594fSAndroid Build Coastguard Worker return nullptr;
814*795d594fSAndroid Build Coastguard Worker }
815*795d594fSAndroid Build Coastguard Worker
RunAgentThread(jvmtiEnv * jvmti_env,jthread thread,jvmtiStartFunction proc,const void * arg,jint priority)816*795d594fSAndroid Build Coastguard Worker jvmtiError ThreadUtil::RunAgentThread(jvmtiEnv* jvmti_env,
817*795d594fSAndroid Build Coastguard Worker jthread thread,
818*795d594fSAndroid Build Coastguard Worker jvmtiStartFunction proc,
819*795d594fSAndroid Build Coastguard Worker const void* arg,
820*795d594fSAndroid Build Coastguard Worker jint priority) {
821*795d594fSAndroid Build Coastguard Worker if (!PhaseUtil::IsLivePhase()) {
822*795d594fSAndroid Build Coastguard Worker return ERR(WRONG_PHASE);
823*795d594fSAndroid Build Coastguard Worker }
824*795d594fSAndroid Build Coastguard Worker if (priority < JVMTI_THREAD_MIN_PRIORITY || priority > JVMTI_THREAD_MAX_PRIORITY) {
825*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_PRIORITY);
826*795d594fSAndroid Build Coastguard Worker }
827*795d594fSAndroid Build Coastguard Worker if (thread == nullptr) {
828*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_THREAD);
829*795d594fSAndroid Build Coastguard Worker }
830*795d594fSAndroid Build Coastguard Worker art::Runtime* runtime = art::Runtime::Current();
831*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current();
832*795d594fSAndroid Build Coastguard Worker std::unique_ptr<AgentData> data;
833*795d594fSAndroid Build Coastguard Worker {
834*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(self);
835*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> othread = soa.Decode<art::mirror::Object>(thread);
836*795d594fSAndroid Build Coastguard Worker if (!othread->InstanceOf(art::WellKnownClasses::java_lang_Thread.Get())) {
837*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_THREAD);
838*795d594fSAndroid Build Coastguard Worker }
839*795d594fSAndroid Build Coastguard Worker if (proc == nullptr) {
840*795d594fSAndroid Build Coastguard Worker return ERR(NULL_POINTER);
841*795d594fSAndroid Build Coastguard Worker }
842*795d594fSAndroid Build Coastguard Worker
843*795d594fSAndroid Build Coastguard Worker {
844*795d594fSAndroid Build Coastguard Worker art::MutexLock mu(soa.Self(), *art::Locks::runtime_shutdown_lock_);
845*795d594fSAndroid Build Coastguard Worker if (runtime->IsShuttingDownLocked()) {
846*795d594fSAndroid Build Coastguard Worker // The runtime is shutting down so we cannot create new threads.
847*795d594fSAndroid Build Coastguard Worker // TODO It's not fully clear from the spec what we should do here. We aren't yet in
848*795d594fSAndroid Build Coastguard Worker // JVMTI_PHASE_DEAD so we cannot return ERR(WRONG_PHASE) but creating new threads is now
849*795d594fSAndroid Build Coastguard Worker // impossible. Existing agents don't seem to generally do anything with this return value so
850*795d594fSAndroid Build Coastguard Worker // it doesn't matter too much. We could do something like sending a fake ThreadStart event
851*795d594fSAndroid Build Coastguard Worker // even though code is never actually run.
852*795d594fSAndroid Build Coastguard Worker return ERR(INTERNAL);
853*795d594fSAndroid Build Coastguard Worker }
854*795d594fSAndroid Build Coastguard Worker runtime->StartThreadBirth();
855*795d594fSAndroid Build Coastguard Worker }
856*795d594fSAndroid Build Coastguard Worker
857*795d594fSAndroid Build Coastguard Worker data.reset(new AgentData);
858*795d594fSAndroid Build Coastguard Worker data->arg = arg;
859*795d594fSAndroid Build Coastguard Worker data->proc = proc;
860*795d594fSAndroid Build Coastguard Worker // We need a global ref for Java objects, as local refs will be invalid.
861*795d594fSAndroid Build Coastguard Worker data->thread = runtime->GetJavaVM()->AddGlobalRef(soa.Self(), othread);
862*795d594fSAndroid Build Coastguard Worker data->java_vm = runtime->GetJavaVM();
863*795d594fSAndroid Build Coastguard Worker data->jvmti_env = jvmti_env;
864*795d594fSAndroid Build Coastguard Worker data->priority = priority;
865*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> name =
866*795d594fSAndroid Build Coastguard Worker art::WellKnownClasses::java_lang_Thread_name->GetObject(
867*795d594fSAndroid Build Coastguard Worker soa.Decode<art::mirror::Object>(thread));
868*795d594fSAndroid Build Coastguard Worker if (name == nullptr) {
869*795d594fSAndroid Build Coastguard Worker data->name = "JVMTI Agent Thread";
870*795d594fSAndroid Build Coastguard Worker } else {
871*795d594fSAndroid Build Coastguard Worker data->name = name->AsString()->ToModifiedUtf8();
872*795d594fSAndroid Build Coastguard Worker }
873*795d594fSAndroid Build Coastguard Worker }
874*795d594fSAndroid Build Coastguard Worker
875*795d594fSAndroid Build Coastguard Worker pthread_t pthread;
876*795d594fSAndroid Build Coastguard Worker int pthread_create_result = pthread_create(&pthread,
877*795d594fSAndroid Build Coastguard Worker nullptr,
878*795d594fSAndroid Build Coastguard Worker &AgentCallback,
879*795d594fSAndroid Build Coastguard Worker reinterpret_cast<void*>(data.get()));
880*795d594fSAndroid Build Coastguard Worker if (pthread_create_result != 0) {
881*795d594fSAndroid Build Coastguard Worker // If the create succeeded the other thread will call EndThreadBirth.
882*795d594fSAndroid Build Coastguard Worker art::MutexLock mu(self, *art::Locks::runtime_shutdown_lock_);
883*795d594fSAndroid Build Coastguard Worker runtime->EndThreadBirth();
884*795d594fSAndroid Build Coastguard Worker return ERR(INTERNAL);
885*795d594fSAndroid Build Coastguard Worker }
886*795d594fSAndroid Build Coastguard Worker data.release(); // NOLINT pthreads API.
887*795d594fSAndroid Build Coastguard Worker
888*795d594fSAndroid Build Coastguard Worker return ERR(NONE);
889*795d594fSAndroid Build Coastguard Worker }
890*795d594fSAndroid Build Coastguard Worker
SuspendOther(art::Thread * self,jthread target_jthread)891*795d594fSAndroid Build Coastguard Worker jvmtiError ThreadUtil::SuspendOther(art::Thread* self,
892*795d594fSAndroid Build Coastguard Worker jthread target_jthread) {
893*795d594fSAndroid Build Coastguard Worker // Loop since we need to bail out and try again if we would end up getting suspended while holding
894*795d594fSAndroid Build Coastguard Worker // the user_code_suspension_lock_ due to a SuspendReason::kForUserCode. In this situation we
895*795d594fSAndroid Build Coastguard Worker // release the lock, wait to get resumed and try again.
896*795d594fSAndroid Build Coastguard Worker do {
897*795d594fSAndroid Build Coastguard Worker ScopedNoUserCodeSuspension snucs(self);
898*795d594fSAndroid Build Coastguard Worker // We are not going to be suspended by user code from now on.
899*795d594fSAndroid Build Coastguard Worker {
900*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(self);
901*795d594fSAndroid Build Coastguard Worker art::MutexLock thread_list_mu(self, *art::Locks::thread_list_lock_);
902*795d594fSAndroid Build Coastguard Worker art::Thread* target = nullptr;
903*795d594fSAndroid Build Coastguard Worker jvmtiError err = ERR(INTERNAL);
904*795d594fSAndroid Build Coastguard Worker if (!GetAliveNativeThread(target_jthread, soa, &target, &err)) {
905*795d594fSAndroid Build Coastguard Worker return err;
906*795d594fSAndroid Build Coastguard Worker }
907*795d594fSAndroid Build Coastguard Worker art::ThreadState state = target->GetState();
908*795d594fSAndroid Build Coastguard Worker if (state == art::ThreadState::kStarting || target->IsStillStarting()) {
909*795d594fSAndroid Build Coastguard Worker return ERR(THREAD_NOT_ALIVE);
910*795d594fSAndroid Build Coastguard Worker } else {
911*795d594fSAndroid Build Coastguard Worker art::MutexLock thread_suspend_count_mu(self, *art::Locks::thread_suspend_count_lock_);
912*795d594fSAndroid Build Coastguard Worker if (target->GetUserCodeSuspendCount() != 0) {
913*795d594fSAndroid Build Coastguard Worker return ERR(THREAD_SUSPENDED);
914*795d594fSAndroid Build Coastguard Worker }
915*795d594fSAndroid Build Coastguard Worker }
916*795d594fSAndroid Build Coastguard Worker }
917*795d594fSAndroid Build Coastguard Worker art::Thread* ret_target = art::Runtime::Current()->GetThreadList()->SuspendThreadByPeer(
918*795d594fSAndroid Build Coastguard Worker target_jthread, art::SuspendReason::kForUserCode);
919*795d594fSAndroid Build Coastguard Worker if (ret_target == nullptr) {
920*795d594fSAndroid Build Coastguard Worker // TODO It would be good to get more information about why exactly the thread failed to
921*795d594fSAndroid Build Coastguard Worker // suspend.
922*795d594fSAndroid Build Coastguard Worker return ERR(INTERNAL);
923*795d594fSAndroid Build Coastguard Worker } else {
924*795d594fSAndroid Build Coastguard Worker return OK;
925*795d594fSAndroid Build Coastguard Worker }
926*795d594fSAndroid Build Coastguard Worker // We timed out. Just go around and try again.
927*795d594fSAndroid Build Coastguard Worker } while (true);
928*795d594fSAndroid Build Coastguard Worker }
929*795d594fSAndroid Build Coastguard Worker
SuspendSelf(art::Thread * self)930*795d594fSAndroid Build Coastguard Worker jvmtiError ThreadUtil::SuspendSelf(art::Thread* self) {
931*795d594fSAndroid Build Coastguard Worker CHECK(self == art::Thread::Current());
932*795d594fSAndroid Build Coastguard Worker {
933*795d594fSAndroid Build Coastguard Worker art::MutexLock mu(self, *art::Locks::user_code_suspension_lock_);
934*795d594fSAndroid Build Coastguard Worker art::MutexLock thread_list_mu(self, *art::Locks::thread_suspend_count_lock_);
935*795d594fSAndroid Build Coastguard Worker if (self->GetUserCodeSuspendCount() != 0) {
936*795d594fSAndroid Build Coastguard Worker // This can only happen if we race with another thread to suspend 'self' and we lose.
937*795d594fSAndroid Build Coastguard Worker return ERR(THREAD_SUSPENDED);
938*795d594fSAndroid Build Coastguard Worker }
939*795d594fSAndroid Build Coastguard Worker {
940*795d594fSAndroid Build Coastguard Worker // IncrementSuspendCount normally needs thread_list_lock_ to ensure the thread stays
941*795d594fSAndroid Build Coastguard Worker // around. In this case we are the target thread, so we fake it.
942*795d594fSAndroid Build Coastguard Worker art::FakeMutexLock fmu(*art::Locks::thread_list_lock_);
943*795d594fSAndroid Build Coastguard Worker self->IncrementSuspendCount(self, nullptr, nullptr, art::SuspendReason::kForUserCode);
944*795d594fSAndroid Build Coastguard Worker }
945*795d594fSAndroid Build Coastguard Worker }
946*795d594fSAndroid Build Coastguard Worker // Once we have requested the suspend we actually go to sleep. We need to do this after releasing
947*795d594fSAndroid Build Coastguard Worker // the suspend_lock to make sure we can be woken up. This call gains the mutator lock causing us
948*795d594fSAndroid Build Coastguard Worker // to go to sleep until we are resumed.
949*795d594fSAndroid Build Coastguard Worker SuspendCheck(self);
950*795d594fSAndroid Build Coastguard Worker return OK;
951*795d594fSAndroid Build Coastguard Worker }
952*795d594fSAndroid Build Coastguard Worker
SuspendThread(jvmtiEnv * env,jthread thread)953*795d594fSAndroid Build Coastguard Worker jvmtiError ThreadUtil::SuspendThread([[maybe_unused]] jvmtiEnv* env, jthread thread) {
954*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current();
955*795d594fSAndroid Build Coastguard Worker bool target_is_self = false;
956*795d594fSAndroid Build Coastguard Worker {
957*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(self);
958*795d594fSAndroid Build Coastguard Worker art::MutexLock mu(self, *art::Locks::thread_list_lock_);
959*795d594fSAndroid Build Coastguard Worker art::Thread* target = nullptr;
960*795d594fSAndroid Build Coastguard Worker jvmtiError err = ERR(INTERNAL);
961*795d594fSAndroid Build Coastguard Worker if (!GetAliveNativeThread(thread, soa, &target, &err)) {
962*795d594fSAndroid Build Coastguard Worker return err;
963*795d594fSAndroid Build Coastguard Worker } else if (target == self) {
964*795d594fSAndroid Build Coastguard Worker target_is_self = true;
965*795d594fSAndroid Build Coastguard Worker }
966*795d594fSAndroid Build Coastguard Worker }
967*795d594fSAndroid Build Coastguard Worker if (target_is_self) {
968*795d594fSAndroid Build Coastguard Worker return SuspendSelf(self);
969*795d594fSAndroid Build Coastguard Worker } else {
970*795d594fSAndroid Build Coastguard Worker return SuspendOther(self, thread);
971*795d594fSAndroid Build Coastguard Worker }
972*795d594fSAndroid Build Coastguard Worker }
973*795d594fSAndroid Build Coastguard Worker
ResumeThread(jvmtiEnv * env,jthread thread)974*795d594fSAndroid Build Coastguard Worker jvmtiError ThreadUtil::ResumeThread([[maybe_unused]] jvmtiEnv* env, jthread thread) {
975*795d594fSAndroid Build Coastguard Worker if (thread == nullptr) {
976*795d594fSAndroid Build Coastguard Worker return ERR(NULL_POINTER);
977*795d594fSAndroid Build Coastguard Worker }
978*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current();
979*795d594fSAndroid Build Coastguard Worker art::Thread* target;
980*795d594fSAndroid Build Coastguard Worker
981*795d594fSAndroid Build Coastguard Worker // Make sure we won't get suspended ourselves while in the middle of resuming another thread.
982*795d594fSAndroid Build Coastguard Worker ScopedNoUserCodeSuspension snucs(self);
983*795d594fSAndroid Build Coastguard Worker // From now on we know we cannot get suspended by user-code.
984*795d594fSAndroid Build Coastguard Worker {
985*795d594fSAndroid Build Coastguard Worker // NB This does a SuspendCheck (during thread state change) so we need to make sure we don't
986*795d594fSAndroid Build Coastguard Worker // have the 'suspend_lock' locked here.
987*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(self);
988*795d594fSAndroid Build Coastguard Worker art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_);
989*795d594fSAndroid Build Coastguard Worker jvmtiError err = ERR(INTERNAL);
990*795d594fSAndroid Build Coastguard Worker if (!GetAliveNativeThread(thread, soa, &target, &err)) {
991*795d594fSAndroid Build Coastguard Worker return err;
992*795d594fSAndroid Build Coastguard Worker } else if (target == self) {
993*795d594fSAndroid Build Coastguard Worker // We would have paused until we aren't suspended anymore due to the ScopedObjectAccess so
994*795d594fSAndroid Build Coastguard Worker // we can just return THREAD_NOT_SUSPENDED. Unfortunately we cannot do any real DCHECKs
995*795d594fSAndroid Build Coastguard Worker // about current state since it's all concurrent.
996*795d594fSAndroid Build Coastguard Worker return ERR(THREAD_NOT_SUSPENDED);
997*795d594fSAndroid Build Coastguard Worker }
998*795d594fSAndroid Build Coastguard Worker // The JVMTI spec requires us to return THREAD_NOT_SUSPENDED if it is alive but we really
999*795d594fSAndroid Build Coastguard Worker // cannot tell why resume failed.
1000*795d594fSAndroid Build Coastguard Worker {
1001*795d594fSAndroid Build Coastguard Worker art::MutexLock thread_suspend_count_mu(self, *art::Locks::thread_suspend_count_lock_);
1002*795d594fSAndroid Build Coastguard Worker if (target->GetUserCodeSuspendCount() == 0) {
1003*795d594fSAndroid Build Coastguard Worker return ERR(THREAD_NOT_SUSPENDED);
1004*795d594fSAndroid Build Coastguard Worker }
1005*795d594fSAndroid Build Coastguard Worker }
1006*795d594fSAndroid Build Coastguard Worker }
1007*795d594fSAndroid Build Coastguard Worker // It is okay that we don't have a thread_list_lock here since we know that the thread cannot
1008*795d594fSAndroid Build Coastguard Worker // die since it is currently held suspended by a SuspendReason::kForUserCode suspend.
1009*795d594fSAndroid Build Coastguard Worker DCHECK(target != self);
1010*795d594fSAndroid Build Coastguard Worker if (!art::Runtime::Current()->GetThreadList()->Resume(target,
1011*795d594fSAndroid Build Coastguard Worker art::SuspendReason::kForUserCode)) {
1012*795d594fSAndroid Build Coastguard Worker // TODO Give a better error.
1013*795d594fSAndroid Build Coastguard Worker // This is most likely THREAD_NOT_SUSPENDED but we cannot really be sure.
1014*795d594fSAndroid Build Coastguard Worker return ERR(INTERNAL);
1015*795d594fSAndroid Build Coastguard Worker } else {
1016*795d594fSAndroid Build Coastguard Worker return OK;
1017*795d594fSAndroid Build Coastguard Worker }
1018*795d594fSAndroid Build Coastguard Worker }
1019*795d594fSAndroid Build Coastguard Worker
IsCurrentThread(jthread thr)1020*795d594fSAndroid Build Coastguard Worker static bool IsCurrentThread(jthread thr) {
1021*795d594fSAndroid Build Coastguard Worker if (thr == nullptr) {
1022*795d594fSAndroid Build Coastguard Worker return true;
1023*795d594fSAndroid Build Coastguard Worker }
1024*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current();
1025*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(self);
1026*795d594fSAndroid Build Coastguard Worker art::MutexLock mu(self, *art::Locks::thread_list_lock_);
1027*795d594fSAndroid Build Coastguard Worker art::Thread* target = nullptr;
1028*795d594fSAndroid Build Coastguard Worker jvmtiError err_unused = ERR(INTERNAL);
1029*795d594fSAndroid Build Coastguard Worker if (ThreadUtil::GetNativeThread(thr, soa, &target, &err_unused)) {
1030*795d594fSAndroid Build Coastguard Worker return target == self;
1031*795d594fSAndroid Build Coastguard Worker } else {
1032*795d594fSAndroid Build Coastguard Worker return false;
1033*795d594fSAndroid Build Coastguard Worker }
1034*795d594fSAndroid Build Coastguard Worker }
1035*795d594fSAndroid Build Coastguard Worker
1036*795d594fSAndroid Build Coastguard Worker // Suspends all the threads in the list at the same time. Getting this behavior is a little tricky
1037*795d594fSAndroid Build Coastguard Worker // since we can have threads in the list multiple times. This generally doesn't matter unless the
1038*795d594fSAndroid Build Coastguard Worker // current thread is present multiple times. In that case we need to suspend only once and either
1039*795d594fSAndroid Build Coastguard Worker // return the same error code in all the other slots if it failed or return ERR(THREAD_SUSPENDED) if
1040*795d594fSAndroid Build Coastguard Worker // it didn't. We also want to handle the current thread last to make the behavior of the code
1041*795d594fSAndroid Build Coastguard Worker // simpler to understand.
SuspendThreadList(jvmtiEnv * env,jint request_count,const jthread * threads,jvmtiError * results)1042*795d594fSAndroid Build Coastguard Worker jvmtiError ThreadUtil::SuspendThreadList(jvmtiEnv* env,
1043*795d594fSAndroid Build Coastguard Worker jint request_count,
1044*795d594fSAndroid Build Coastguard Worker const jthread* threads,
1045*795d594fSAndroid Build Coastguard Worker jvmtiError* results) {
1046*795d594fSAndroid Build Coastguard Worker if (request_count == 0) {
1047*795d594fSAndroid Build Coastguard Worker return ERR(ILLEGAL_ARGUMENT);
1048*795d594fSAndroid Build Coastguard Worker } else if (results == nullptr || threads == nullptr) {
1049*795d594fSAndroid Build Coastguard Worker return ERR(NULL_POINTER);
1050*795d594fSAndroid Build Coastguard Worker }
1051*795d594fSAndroid Build Coastguard Worker // This is the list of the indexes in 'threads' and 'results' that correspond to the currently
1052*795d594fSAndroid Build Coastguard Worker // running thread. These indexes we need to handle specially since we need to only actually
1053*795d594fSAndroid Build Coastguard Worker // suspend a single time.
1054*795d594fSAndroid Build Coastguard Worker std::vector<jint> current_thread_indexes;
1055*795d594fSAndroid Build Coastguard Worker for (jint i = 0; i < request_count; i++) {
1056*795d594fSAndroid Build Coastguard Worker if (IsCurrentThread(threads[i])) {
1057*795d594fSAndroid Build Coastguard Worker current_thread_indexes.push_back(i);
1058*795d594fSAndroid Build Coastguard Worker } else {
1059*795d594fSAndroid Build Coastguard Worker results[i] = env->SuspendThread(threads[i]);
1060*795d594fSAndroid Build Coastguard Worker }
1061*795d594fSAndroid Build Coastguard Worker }
1062*795d594fSAndroid Build Coastguard Worker if (!current_thread_indexes.empty()) {
1063*795d594fSAndroid Build Coastguard Worker jint first_current_thread_index = current_thread_indexes[0];
1064*795d594fSAndroid Build Coastguard Worker // Suspend self.
1065*795d594fSAndroid Build Coastguard Worker jvmtiError res = env->SuspendThread(threads[first_current_thread_index]);
1066*795d594fSAndroid Build Coastguard Worker results[first_current_thread_index] = res;
1067*795d594fSAndroid Build Coastguard Worker // Fill in the rest of the error values as appropriate.
1068*795d594fSAndroid Build Coastguard Worker jvmtiError other_results = (res != OK) ? res : ERR(THREAD_SUSPENDED);
1069*795d594fSAndroid Build Coastguard Worker for (auto it = ++current_thread_indexes.begin(); it != current_thread_indexes.end(); ++it) {
1070*795d594fSAndroid Build Coastguard Worker results[*it] = other_results;
1071*795d594fSAndroid Build Coastguard Worker }
1072*795d594fSAndroid Build Coastguard Worker }
1073*795d594fSAndroid Build Coastguard Worker return OK;
1074*795d594fSAndroid Build Coastguard Worker }
1075*795d594fSAndroid Build Coastguard Worker
ResumeThreadList(jvmtiEnv * env,jint request_count,const jthread * threads,jvmtiError * results)1076*795d594fSAndroid Build Coastguard Worker jvmtiError ThreadUtil::ResumeThreadList(jvmtiEnv* env,
1077*795d594fSAndroid Build Coastguard Worker jint request_count,
1078*795d594fSAndroid Build Coastguard Worker const jthread* threads,
1079*795d594fSAndroid Build Coastguard Worker jvmtiError* results) {
1080*795d594fSAndroid Build Coastguard Worker if (request_count == 0) {
1081*795d594fSAndroid Build Coastguard Worker return ERR(ILLEGAL_ARGUMENT);
1082*795d594fSAndroid Build Coastguard Worker } else if (results == nullptr || threads == nullptr) {
1083*795d594fSAndroid Build Coastguard Worker return ERR(NULL_POINTER);
1084*795d594fSAndroid Build Coastguard Worker }
1085*795d594fSAndroid Build Coastguard Worker for (jint i = 0; i < request_count; i++) {
1086*795d594fSAndroid Build Coastguard Worker results[i] = env->ResumeThread(threads[i]);
1087*795d594fSAndroid Build Coastguard Worker }
1088*795d594fSAndroid Build Coastguard Worker return OK;
1089*795d594fSAndroid Build Coastguard Worker }
1090*795d594fSAndroid Build Coastguard Worker
StopThread(jvmtiEnv * env,jthread thread,jobject exception)1091*795d594fSAndroid Build Coastguard Worker jvmtiError ThreadUtil::StopThread([[maybe_unused]] jvmtiEnv* env,
1092*795d594fSAndroid Build Coastguard Worker jthread thread,
1093*795d594fSAndroid Build Coastguard Worker jobject exception) {
1094*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current();
1095*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(self);
1096*795d594fSAndroid Build Coastguard Worker art::StackHandleScope<1> hs(self);
1097*795d594fSAndroid Build Coastguard Worker if (exception == nullptr) {
1098*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_OBJECT);
1099*795d594fSAndroid Build Coastguard Worker }
1100*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> obj(soa.Decode<art::mirror::Object>(exception));
1101*795d594fSAndroid Build Coastguard Worker if (!obj->GetClass()->IsThrowableClass()) {
1102*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_OBJECT);
1103*795d594fSAndroid Build Coastguard Worker }
1104*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Throwable> exc(hs.NewHandle(obj->AsThrowable()));
1105*795d594fSAndroid Build Coastguard Worker art::Locks::thread_list_lock_->ExclusiveLock(self);
1106*795d594fSAndroid Build Coastguard Worker art::Thread* target = nullptr;
1107*795d594fSAndroid Build Coastguard Worker jvmtiError err = ERR(INTERNAL);
1108*795d594fSAndroid Build Coastguard Worker if (!GetAliveNativeThread(thread, soa, &target, &err)) {
1109*795d594fSAndroid Build Coastguard Worker art::Locks::thread_list_lock_->ExclusiveUnlock(self);
1110*795d594fSAndroid Build Coastguard Worker return err;
1111*795d594fSAndroid Build Coastguard Worker } else if (target->GetState() == art::ThreadState::kStarting || target->IsStillStarting()) {
1112*795d594fSAndroid Build Coastguard Worker art::Locks::thread_list_lock_->ExclusiveUnlock(self);
1113*795d594fSAndroid Build Coastguard Worker return ERR(THREAD_NOT_ALIVE);
1114*795d594fSAndroid Build Coastguard Worker }
1115*795d594fSAndroid Build Coastguard Worker struct StopThreadClosure : public art::Closure {
1116*795d594fSAndroid Build Coastguard Worker public:
1117*795d594fSAndroid Build Coastguard Worker explicit StopThreadClosure(art::Handle<art::mirror::Throwable> except) : exception_(except) { }
1118*795d594fSAndroid Build Coastguard Worker
1119*795d594fSAndroid Build Coastguard Worker void Run(art::Thread* me) override REQUIRES_SHARED(art::Locks::mutator_lock_) {
1120*795d594fSAndroid Build Coastguard Worker // Make sure the thread is prepared to notice the exception.
1121*795d594fSAndroid Build Coastguard Worker DeoptManager::Get()->DeoptimizeThread(me);
1122*795d594fSAndroid Build Coastguard Worker me->SetAsyncException(exception_.Get());
1123*795d594fSAndroid Build Coastguard Worker // Wake up the thread if it is sleeping.
1124*795d594fSAndroid Build Coastguard Worker me->Notify();
1125*795d594fSAndroid Build Coastguard Worker }
1126*795d594fSAndroid Build Coastguard Worker
1127*795d594fSAndroid Build Coastguard Worker private:
1128*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Throwable> exception_;
1129*795d594fSAndroid Build Coastguard Worker };
1130*795d594fSAndroid Build Coastguard Worker StopThreadClosure c(exc);
1131*795d594fSAndroid Build Coastguard Worker // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution.
1132*795d594fSAndroid Build Coastguard Worker if (target->RequestSynchronousCheckpoint(&c)) {
1133*795d594fSAndroid Build Coastguard Worker return OK;
1134*795d594fSAndroid Build Coastguard Worker } else {
1135*795d594fSAndroid Build Coastguard Worker // Something went wrong, probably the thread died.
1136*795d594fSAndroid Build Coastguard Worker return ERR(THREAD_NOT_ALIVE);
1137*795d594fSAndroid Build Coastguard Worker }
1138*795d594fSAndroid Build Coastguard Worker }
1139*795d594fSAndroid Build Coastguard Worker
InterruptThread(jvmtiEnv * env,jthread thread)1140*795d594fSAndroid Build Coastguard Worker jvmtiError ThreadUtil::InterruptThread([[maybe_unused]] jvmtiEnv* env, jthread thread) {
1141*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current();
1142*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(self);
1143*795d594fSAndroid Build Coastguard Worker art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_);
1144*795d594fSAndroid Build Coastguard Worker art::Thread* target = nullptr;
1145*795d594fSAndroid Build Coastguard Worker jvmtiError err = ERR(INTERNAL);
1146*795d594fSAndroid Build Coastguard Worker if (!GetAliveNativeThread(thread, soa, &target, &err)) {
1147*795d594fSAndroid Build Coastguard Worker return err;
1148*795d594fSAndroid Build Coastguard Worker } else if (target->GetState() == art::ThreadState::kStarting || target->IsStillStarting()) {
1149*795d594fSAndroid Build Coastguard Worker return ERR(THREAD_NOT_ALIVE);
1150*795d594fSAndroid Build Coastguard Worker }
1151*795d594fSAndroid Build Coastguard Worker target->Interrupt(self);
1152*795d594fSAndroid Build Coastguard Worker return OK;
1153*795d594fSAndroid Build Coastguard Worker }
1154*795d594fSAndroid Build Coastguard Worker
1155*795d594fSAndroid Build Coastguard Worker } // namespace openjdkjvmti
1156