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