/* Copyright (C) 2017 The Android Open Source Project
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This file implements interfaces from the file jvmti.h. This implementation
 * is licensed under the same terms as the file jvmti.h.  The
 * copyright and license information for the file jvmti.h follows.
 *
 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#include "ti_thread.h"

#include <android-base/logging.h>
#include <android-base/strings.h>

#include "art_field-inl.h"
#include "art_jvmti.h"
#include "base/mutex.h"
#include "events-inl.h"
#include "gc/system_weak.h"
#include "gc/collector_type.h"
#include "gc/gc_cause.h"
#include "gc/scoped_gc_critical_section.h"
#include "gc_root-inl.h"
#include "jni/jni_internal.h"
#include "mirror/class.h"
#include "mirror/object-inl.h"
#include "mirror/string.h"
#include "mirror/throwable.h"
#include "nativehelper/scoped_local_ref.h"
#include "nativehelper/scoped_utf_chars.h"
#include "obj_ptr.h"
#include "runtime.h"
#include "runtime_callbacks.h"
#include "scoped_thread_state_change-inl.h"
#include "thread-current-inl.h"
#include "thread_list.h"
#include "ti_phase.h"
#include "well_known_classes.h"

namespace openjdkjvmti {

static const char* kJvmtiTlsKey = "JvmtiTlsKey";

art::ArtField* ThreadUtil::context_class_loader_ = nullptr;

struct ThreadCallback : public art::ThreadLifecycleCallback {
  jthread GetThreadObject(art::Thread* self) REQUIRES_SHARED(art::Locks::mutator_lock_) {
    if (self->GetPeer() == nullptr) {
      return nullptr;
    }
    return self->GetJniEnv()->AddLocalReference<jthread>(self->GetPeer());
  }

  template <ArtJvmtiEvent kEvent>
  void Post(art::Thread* self) REQUIRES_SHARED(art::Locks::mutator_lock_) {
    DCHECK_EQ(self, art::Thread::Current());
    ScopedLocalRef<jthread> thread(self->GetJniEnv(), GetThreadObject(self));
    art::ScopedThreadSuspension sts(self, art::ThreadState::kNative);
    event_handler->DispatchEvent<kEvent>(self,
                                         reinterpret_cast<JNIEnv*>(self->GetJniEnv()),
                                         thread.get());
  }

  void ThreadStart(art::Thread* self) override REQUIRES_SHARED(art::Locks::mutator_lock_) {
    // Needs to be checked first because we might start these threads before we actually send the
    // VMInit event.
    if (self->IsSystemDaemon()) {
      // System daemon threads are things like the finalizer or gc thread. It would be dangerous to
      // allow agents to get in the way of these threads starting up. These threads include things
      // like the HeapTaskDaemon and the finalizer daemon.
      //
      // This event can happen during the time before VMInit or just after zygote fork. Since the
      // second is hard to distinguish we unfortunately cannot really check the state here.
      return;
    }
    if (!started) {
      // Runtime isn't started. We only expect at most the signal handler or JIT threads to be
      // started here.
      if (art::kIsDebugBuild) {
        std::string name;
        self->GetThreadName(name);
        if (name != "JDWP" &&
            name != "Signal Catcher" &&
            !android::base::StartsWith(name, "Jit thread pool") &&
            !android::base::StartsWith(name, "Runtime worker thread")) {
          LOG(FATAL) << "Unexpected thread before start: " << name << " id: "
                     << self->GetThreadId();
        }
      }
      return;
    }
    Post<ArtJvmtiEvent::kThreadStart>(self);
  }

  void ThreadDeath(art::Thread* self) override REQUIRES_SHARED(art::Locks::mutator_lock_) {
    Post<ArtJvmtiEvent::kThreadEnd>(self);
  }

  EventHandler* event_handler = nullptr;
  bool started = false;
};

ThreadCallback gThreadCallback;

void ThreadUtil::Register(EventHandler* handler) {
  art::Runtime* runtime = art::Runtime::Current();

  gThreadCallback.started = runtime->IsStarted();
  gThreadCallback.event_handler = handler;

  art::ScopedThreadStateChange stsc(art::Thread::Current(),
                                    art::ThreadState::kWaitingForDebuggerToAttach);
  art::ScopedSuspendAll ssa("Add thread callback");
  runtime->GetRuntimeCallbacks()->AddThreadLifecycleCallback(&gThreadCallback);
}

void ThreadUtil::VMInitEventSent() {
  // We should have already started.
  DCHECK(gThreadCallback.started);
  // We moved to VMInit. Report the main thread as started (it was attached early, and must not be
  // reported until Init.
  gThreadCallback.Post<ArtJvmtiEvent::kThreadStart>(art::Thread::Current());
}


static void WaitForSystemDaemonStart(art::Thread* self) REQUIRES_SHARED(art::Locks::mutator_lock_) {
  {
    art::ScopedThreadStateChange strc(self, art::kNative);
    JNIEnv* jni = self->GetJniEnv();
    jni->CallStaticVoidMethod(art::WellKnownClasses::java_lang_Daemons,
                              art::WellKnownClasses::java_lang_Daemons_waitForDaemonStart);
  }
  if (self->IsExceptionPending()) {
    LOG(WARNING) << "Exception occurred when waiting for system daemons to start: "
                 << self->GetException()->Dump();
    self->ClearException();
  }
}

void ThreadUtil::CacheData() {
  // We must have started since it is now safe to cache our data;
  gThreadCallback.started = true;
  art::Thread* self = art::Thread::Current();
  art::ScopedObjectAccess soa(self);
  art::ObjPtr<art::mirror::Class> thread_class =
      soa.Decode<art::mirror::Class>(art::WellKnownClasses::java_lang_Thread);
  CHECK(thread_class != nullptr);
  context_class_loader_ = thread_class->FindDeclaredInstanceField("contextClassLoader",
                                                                  "Ljava/lang/ClassLoader;");
  CHECK(context_class_loader_ != nullptr);
  // Now wait for all required system threads to come up before allowing the rest of loading to
  // continue.
  WaitForSystemDaemonStart(self);
}

void ThreadUtil::Unregister() {
  art::ScopedThreadStateChange stsc(art::Thread::Current(),
                                    art::ThreadState::kWaitingForDebuggerToAttach);
  art::ScopedSuspendAll ssa("Remove thread callback");
  art::Runtime* runtime = art::Runtime::Current();
  runtime->GetRuntimeCallbacks()->RemoveThreadLifecycleCallback(&gThreadCallback);
}

jvmtiError ThreadUtil::GetCurrentThread(jvmtiEnv* env ATTRIBUTE_UNUSED, jthread* thread_ptr) {
  art::Thread* self = art::Thread::Current();

  art::ScopedObjectAccess soa(self);

  jthread thread_peer;
  if (self->IsStillStarting()) {
    thread_peer = nullptr;
  } else {
    thread_peer = soa.AddLocalReference<jthread>(self->GetPeer());
  }

  *thread_ptr = thread_peer;
  return ERR(NONE);
}

// Get the native thread. The spec says a null object denotes the current thread.
bool ThreadUtil::GetNativeThread(jthread thread,
                                 const art::ScopedObjectAccessAlreadyRunnable& soa,
                                 /*out*/ art::Thread** thr,
                                 /*out*/ jvmtiError* err) {
  if (thread == nullptr) {
    *thr = art::Thread::Current();
    return true;
  } else if (!soa.Env()->IsInstanceOf(thread, art::WellKnownClasses::java_lang_Thread)) {
    *err = ERR(INVALID_THREAD);
    return false;
  } else {
    *thr = art::Thread::FromManagedThread(soa, thread);
    return true;
  }
}

bool ThreadUtil::GetAliveNativeThread(jthread thread,
                                      const art::ScopedObjectAccessAlreadyRunnable& soa,
                                      /*out*/ art::Thread** thr,
                                      /*out*/ jvmtiError* err) {
  if (!GetNativeThread(thread, soa, thr, err)) {
    return false;
  } else if (*thr == nullptr || (*thr)->GetState() == art::ThreadState::kTerminated) {
    *err = ERR(THREAD_NOT_ALIVE);
    return false;
  } else {
    return true;
  }
}

jvmtiError ThreadUtil::GetThreadInfo(jvmtiEnv* env, jthread thread, jvmtiThreadInfo* info_ptr) {
  if (info_ptr == nullptr) {
    return ERR(NULL_POINTER);
  }
  if (!PhaseUtil::IsLivePhase()) {
    return JVMTI_ERROR_WRONG_PHASE;
  }

  art::Thread* self = art::Thread::Current();
  art::ScopedObjectAccess soa(self);
  art::MutexLock mu(self, *art::Locks::thread_list_lock_);

  art::Thread* target;
  jvmtiError err = ERR(INTERNAL);
  if (!GetNativeThread(thread, soa, &target, &err)) {
    return err;
  }

  JvmtiUniquePtr<char[]> name_uptr;
  if (target != nullptr) {
    // Have a native thread object, this thread is alive.
    std::string name;
    target->GetThreadName(name);
    jvmtiError name_result;
    name_uptr = CopyString(env, name.c_str(), &name_result);
    if (name_uptr == nullptr) {
      return name_result;
    }
    info_ptr->name = name_uptr.get();

    info_ptr->priority = target->GetNativePriority();

    info_ptr->is_daemon = target->IsDaemon();

    art::ObjPtr<art::mirror::Object> peer = target->GetPeerFromOtherThread();

    // ThreadGroup.
    if (peer != nullptr) {
      art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_group);
      CHECK(f != nullptr);
      art::ObjPtr<art::mirror::Object> group = f->GetObject(peer);
      info_ptr->thread_group = group == nullptr
                                   ? nullptr
                                   : soa.AddLocalReference<jthreadGroup>(group);
    } else {
      info_ptr->thread_group = nullptr;
    }

    // Context classloader.
    DCHECK(context_class_loader_ != nullptr);
    art::ObjPtr<art::mirror::Object> ccl = peer != nullptr
        ? context_class_loader_->GetObject(peer)
        : nullptr;
    info_ptr->context_class_loader = ccl == nullptr
                                         ? nullptr
                                         : soa.AddLocalReference<jobject>(ccl);
  } else {
    // Only the peer. This thread has either not been started, or is dead. Read things from
    // the Java side.
    art::ObjPtr<art::mirror::Object> peer = soa.Decode<art::mirror::Object>(thread);

    // Name.
    {
      art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_name);
      CHECK(f != nullptr);
      art::ObjPtr<art::mirror::Object> name = f->GetObject(peer);
      std::string name_cpp;
      const char* name_cstr;
      if (name != nullptr) {
        name_cpp = name->AsString()->ToModifiedUtf8();
        name_cstr = name_cpp.c_str();
      } else {
        name_cstr = "";
      }
      jvmtiError name_result;
      name_uptr = CopyString(env, name_cstr, &name_result);
      if (name_uptr == nullptr) {
        return name_result;
      }
      info_ptr->name = name_uptr.get();
    }

    // Priority.
    {
      art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_priority);
      CHECK(f != nullptr);
      info_ptr->priority = static_cast<jint>(f->GetInt(peer));
    }

    // Daemon.
    {
      art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_daemon);
      CHECK(f != nullptr);
      info_ptr->is_daemon = f->GetBoolean(peer) == 0 ? JNI_FALSE : JNI_TRUE;
    }

    // ThreadGroup.
    {
      art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_group);
      CHECK(f != nullptr);
      art::ObjPtr<art::mirror::Object> group = f->GetObject(peer);
      info_ptr->thread_group = group == nullptr
                                   ? nullptr
                                   : soa.AddLocalReference<jthreadGroup>(group);
    }

    // Context classloader.
    DCHECK(context_class_loader_ != nullptr);
    art::ObjPtr<art::mirror::Object> ccl = peer != nullptr
        ? context_class_loader_->GetObject(peer)
        : nullptr;
    info_ptr->context_class_loader = ccl == nullptr
                                         ? nullptr
                                         : soa.AddLocalReference<jobject>(ccl);
  }

  name_uptr.release();

  return ERR(NONE);
}

struct InternalThreadState {
  art::Thread* native_thread;
  art::ThreadState art_state;
  int thread_user_code_suspend_count;
};

// Return the thread's (or current thread, if null) thread state.
static InternalThreadState GetNativeThreadState(art::Thread* target)
    REQUIRES_SHARED(art::Locks::mutator_lock_)
    REQUIRES(art::Locks::thread_list_lock_, art::Locks::user_code_suspension_lock_) {
  InternalThreadState thread_state = {};
  art::MutexLock tscl_mu(art::Thread::Current(), *art::Locks::thread_suspend_count_lock_);
  thread_state.native_thread = target;
  if (target == nullptr || target->IsStillStarting()) {
    thread_state.art_state = art::ThreadState::kStarting;
    thread_state.thread_user_code_suspend_count = 0;
  } else {
    thread_state.art_state = target->GetState();
    thread_state.thread_user_code_suspend_count = target->GetUserCodeSuspendCount();
  }
  return thread_state;
}

static jint GetJvmtiThreadStateFromInternal(const InternalThreadState& state) {
  art::ThreadState internal_thread_state = state.art_state;
  jint jvmti_state = JVMTI_THREAD_STATE_ALIVE;

  if (state.thread_user_code_suspend_count != 0) {
    // Suspended can be set with any thread state so check it here. Even if the thread isn't in
    // kSuspended state it will move to that once it hits a checkpoint so we can still set this.
    jvmti_state |= JVMTI_THREAD_STATE_SUSPENDED;
    // Note: We do not have data about the previous state. Otherwise we should load the previous
    //       state here.
  }

  if (state.native_thread->IsInterrupted()) {
    // Interrupted can be set with any thread state so check it here.
    jvmti_state |= JVMTI_THREAD_STATE_INTERRUPTED;
  }

  // Enumerate all the thread states and fill in the other bits. This contains the results of
  // following the decision tree in the JVMTI spec GetThreadState documentation.
  switch (internal_thread_state) {
    case art::ThreadState::kRunnable:
    case art::ThreadState::kWaitingWeakGcRootRead:
    case art::ThreadState::kSuspended:
      // These are all simply runnable.
      // kRunnable is self-explanatory.
      // kWaitingWeakGcRootRead is set during some operations with strings due to the intern-table
      // so we want to keep it marked as runnable.
      // kSuspended we don't mark since if we don't have a user_code_suspend_count then it is done
      // by the GC and not a JVMTI suspension, which means it cannot be removed by ResumeThread.
      jvmti_state |= JVMTI_THREAD_STATE_RUNNABLE;
      break;
    case art::ThreadState::kNative:
      // kNative means native and runnable. Technically THREAD_STATE_IN_NATIVE can be set with any
      // state but we don't have the information to know if it should be present for any but the
      // kNative state.
      jvmti_state |= (JVMTI_THREAD_STATE_IN_NATIVE |
                      JVMTI_THREAD_STATE_RUNNABLE);
      break;
    case art::ThreadState::kBlocked:
      // Blocked is one of the top level states so it sits alone.
      jvmti_state |= JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
      break;
    case art::ThreadState::kWaiting:
      // Object.wait() so waiting, indefinitely, in object.wait.
      jvmti_state |= (JVMTI_THREAD_STATE_WAITING |
                      JVMTI_THREAD_STATE_WAITING_INDEFINITELY |
                      JVMTI_THREAD_STATE_IN_OBJECT_WAIT);
      break;
    case art::ThreadState::kTimedWaiting:
      // Object.wait(long) so waiting, with timeout, in object.wait.
      jvmti_state |= (JVMTI_THREAD_STATE_WAITING |
                      JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT |
                      JVMTI_THREAD_STATE_IN_OBJECT_WAIT);
      break;
    case art::ThreadState::kSleeping:
      // In object.sleep. This is a timed wait caused by sleep.
      jvmti_state |= (JVMTI_THREAD_STATE_WAITING |
                      JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT |
                      JVMTI_THREAD_STATE_SLEEPING);
      break;
    // TODO We might want to print warnings if we have the debugger running while JVMTI agents are
    // attached.
    case art::ThreadState::kWaitingForDebuggerSend:
    case art::ThreadState::kWaitingForDebuggerToAttach:
    case art::ThreadState::kWaitingInMainDebuggerLoop:
    case art::ThreadState::kWaitingForDebuggerSuspension:
    case art::ThreadState::kWaitingForLockInflation:
    case art::ThreadState::kWaitingForTaskProcessor:
    case art::ThreadState::kWaitingForGcToComplete:
    case art::ThreadState::kWaitingForCheckPointsToRun:
    case art::ThreadState::kWaitingPerformingGc:
    case art::ThreadState::kWaitingForJniOnLoad:
    case art::ThreadState::kWaitingInMainSignalCatcherLoop:
    case art::ThreadState::kWaitingForSignalCatcherOutput:
    case art::ThreadState::kWaitingForDeoptimization:
    case art::ThreadState::kWaitingForMethodTracingStart:
    case art::ThreadState::kWaitingForVisitObjects:
    case art::ThreadState::kWaitingForGetObjectsAllocated:
    case art::ThreadState::kWaitingForGcThreadFlip:
      // All of these are causing the thread to wait for an indeterminate amount of time but isn't
      // caused by sleep, park, or object#wait.
      jvmti_state |= (JVMTI_THREAD_STATE_WAITING |
                      JVMTI_THREAD_STATE_WAITING_INDEFINITELY);
      break;
    case art::ThreadState::kStarting:
    case art::ThreadState::kTerminated:
      // We only call this if we are alive so we shouldn't see either of these states.
      LOG(FATAL) << "Should not be in state " << internal_thread_state;
      UNREACHABLE();
  }
  // TODO: PARKED. We'll have to inspect the stack.

  return jvmti_state;
}

static jint GetJavaStateFromInternal(const InternalThreadState& state) {
  switch (state.art_state) {
    case art::ThreadState::kTerminated:
      return JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED;

    case art::ThreadState::kRunnable:
    case art::ThreadState::kNative:
    case art::ThreadState::kWaitingWeakGcRootRead:
    case art::ThreadState::kSuspended:
      return JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE;

    case art::ThreadState::kTimedWaiting:
    case art::ThreadState::kSleeping:
      return JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING;

    case art::ThreadState::kBlocked:
      return JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED;

    case art::ThreadState::kStarting:
      return JVMTI_JAVA_LANG_THREAD_STATE_NEW;

    case art::ThreadState::kWaiting:
    case art::ThreadState::kWaitingForTaskProcessor:
    case art::ThreadState::kWaitingForLockInflation:
    case art::ThreadState::kWaitingForGcToComplete:
    case art::ThreadState::kWaitingPerformingGc:
    case art::ThreadState::kWaitingForCheckPointsToRun:
    case art::ThreadState::kWaitingForDebuggerSend:
    case art::ThreadState::kWaitingForDebuggerToAttach:
    case art::ThreadState::kWaitingInMainDebuggerLoop:
    case art::ThreadState::kWaitingForDebuggerSuspension:
    case art::ThreadState::kWaitingForDeoptimization:
    case art::ThreadState::kWaitingForGetObjectsAllocated:
    case art::ThreadState::kWaitingForJniOnLoad:
    case art::ThreadState::kWaitingForSignalCatcherOutput:
    case art::ThreadState::kWaitingInMainSignalCatcherLoop:
    case art::ThreadState::kWaitingForMethodTracingStart:
    case art::ThreadState::kWaitingForVisitObjects:
    case art::ThreadState::kWaitingForGcThreadFlip:
      return JVMTI_JAVA_LANG_THREAD_STATE_WAITING;
  }
  LOG(FATAL) << "Unreachable";
  UNREACHABLE();
}

// Suspends the current thread if it has any suspend requests on it.
void ThreadUtil::SuspendCheck(art::Thread* self) {
  art::ScopedObjectAccess soa(self);
  // Really this is only needed if we are in FastJNI and actually have the mutator_lock_ already.
  self->FullSuspendCheck();
}

bool ThreadUtil::WouldSuspendForUserCodeLocked(art::Thread* self) {
  DCHECK(self == art::Thread::Current());
  art::MutexLock tscl_mu(self, *art::Locks::thread_suspend_count_lock_);
  return self->GetUserCodeSuspendCount() != 0;
}

bool ThreadUtil::WouldSuspendForUserCode(art::Thread* self) {
  DCHECK(self == art::Thread::Current());
  art::MutexLock ucsl_mu(self, *art::Locks::user_code_suspension_lock_);
  return WouldSuspendForUserCodeLocked(self);
}

jvmtiError ThreadUtil::GetThreadState(jvmtiEnv* env ATTRIBUTE_UNUSED,
                                      jthread thread,
                                      jint* thread_state_ptr) {
  if (thread_state_ptr == nullptr) {
    return ERR(NULL_POINTER);
  }

  art::Thread* self = art::Thread::Current();
  InternalThreadState state = {};
  // Loop since we need to bail out and try again if we would end up getting suspended while holding
  // the user_code_suspension_lock_ due to a SuspendReason::kForUserCode. In this situation we
  // release the lock, wait to get resumed and try again.
  do {
    SuspendCheck(self);
    art::MutexLock ucsl_mu(self, *art::Locks::user_code_suspension_lock_);
    if (WouldSuspendForUserCodeLocked(self)) {
      // Make sure we won't be suspended in the middle of holding the thread_suspend_count_lock_ by
      // a user-code suspension. We retry and do another SuspendCheck to clear this.
      continue;
    }
    art::ScopedObjectAccess soa(self);
    art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_);
    jvmtiError err = ERR(INTERNAL);
    art::Thread* target = nullptr;
    if (!GetNativeThread(thread, soa, &target, &err)) {
      return err;
    }
    state = GetNativeThreadState(target);
    if (state.art_state == art::ThreadState::kStarting) {
      break;
    }
    DCHECK(state.native_thread != nullptr);

    // Translate internal thread state to JVMTI and Java state.
    jint jvmti_state = GetJvmtiThreadStateFromInternal(state);

    // Java state is derived from nativeGetState.
    // TODO: Our implementation assigns "runnable" to suspended. As such, we will have slightly
    //       different mask if a thread got suspended due to user-code. However, this is for
    //       consistency with the Java view.
    jint java_state = GetJavaStateFromInternal(state);

    *thread_state_ptr = jvmti_state | java_state;

    return ERR(NONE);
  } while (true);

  DCHECK_EQ(state.art_state, art::ThreadState::kStarting);

  if (thread == nullptr) {
    // No native thread, and no Java thread? We must be starting up. Report as wrong phase.
    return ERR(WRONG_PHASE);
  }

  art::ScopedObjectAccess soa(self);
  art::StackHandleScope<1> hs(self);

  // Need to read the Java "started" field to know whether this is starting or terminated.
  art::Handle<art::mirror::Object> peer(hs.NewHandle(soa.Decode<art::mirror::Object>(thread)));
  art::ObjPtr<art::mirror::Class> thread_klass =
      soa.Decode<art::mirror::Class>(art::WellKnownClasses::java_lang_Thread);
  if (!thread_klass->IsAssignableFrom(peer->GetClass())) {
    return ERR(INVALID_THREAD);
  }
  art::ArtField* started_field = thread_klass->FindDeclaredInstanceField("started", "Z");
  CHECK(started_field != nullptr);
  bool started = started_field->GetBoolean(peer.Get()) != 0;
  constexpr jint kStartedState = JVMTI_JAVA_LANG_THREAD_STATE_NEW;
  constexpr jint kTerminatedState = JVMTI_THREAD_STATE_TERMINATED |
                                    JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED;
  *thread_state_ptr = started ? kTerminatedState : kStartedState;
  return ERR(NONE);
}

jvmtiError ThreadUtil::GetAllThreads(jvmtiEnv* env,
                                     jint* threads_count_ptr,
                                     jthread** threads_ptr) {
  if (threads_count_ptr == nullptr || threads_ptr == nullptr) {
    return ERR(NULL_POINTER);
  }

  art::Thread* current = art::Thread::Current();

  art::ScopedObjectAccess soa(current);

  art::MutexLock mu(current, *art::Locks::thread_list_lock_);
  std::list<art::Thread*> thread_list = art::Runtime::Current()->GetThreadList()->GetList();

  std::vector<art::ObjPtr<art::mirror::Object>> peers;

  for (art::Thread* thread : thread_list) {
    // Skip threads that are still starting.
    if (thread->IsStillStarting()) {
      continue;
    }

    art::ObjPtr<art::mirror::Object> peer = thread->GetPeerFromOtherThread();
    if (peer != nullptr) {
      peers.push_back(peer);
    }
  }

  if (peers.empty()) {
    *threads_count_ptr = 0;
    *threads_ptr = nullptr;
  } else {
    unsigned char* data;
    jvmtiError data_result = env->Allocate(peers.size() * sizeof(jthread), &data);
    if (data_result != ERR(NONE)) {
      return data_result;
    }
    jthread* threads = reinterpret_cast<jthread*>(data);
    for (size_t i = 0; i != peers.size(); ++i) {
      threads[i] = soa.AddLocalReference<jthread>(peers[i]);
    }

    *threads_count_ptr = static_cast<jint>(peers.size());
    *threads_ptr = threads;
  }
  return ERR(NONE);
}

static void RemoveTLSData(art::Thread* target, void* ctx) REQUIRES(art::Locks::thread_list_lock_) {
  jvmtiEnv* env = reinterpret_cast<jvmtiEnv*>(ctx);
  art::Locks::thread_list_lock_->AssertHeld(art::Thread::Current());
  JvmtiGlobalTLSData* global_tls = ThreadUtil::GetGlobalTLSData(target);
  if (global_tls != nullptr) {
    global_tls->data.erase(env);
  }
}

void ThreadUtil::RemoveEnvironment(jvmtiEnv* env) {
  art::Thread* self = art::Thread::Current();
  art::MutexLock mu(self, *art::Locks::thread_list_lock_);
  art::ThreadList* list = art::Runtime::Current()->GetThreadList();
  list->ForEach(RemoveTLSData, env);
}

jvmtiError ThreadUtil::SetThreadLocalStorage(jvmtiEnv* env, jthread thread, const void* data) {
  art::Thread* self = art::Thread::Current();
  art::ScopedObjectAccess soa(self);
  art::MutexLock mu(self, *art::Locks::thread_list_lock_);
  art::Thread* target = nullptr;
  jvmtiError err = ERR(INTERNAL);
  if (!GetAliveNativeThread(thread, soa, &target, &err)) {
    return err;
  }

  JvmtiGlobalTLSData* global_tls = GetOrCreateGlobalTLSData(target);

  global_tls->data[env] = data;

  return ERR(NONE);
}

JvmtiGlobalTLSData* ThreadUtil::GetOrCreateGlobalTLSData(art::Thread* thread) {
  JvmtiGlobalTLSData* data = GetGlobalTLSData(thread);
  if (data != nullptr) {
    return data;
  } else {
    thread->SetCustomTLS(kJvmtiTlsKey, new JvmtiGlobalTLSData);
    return GetGlobalTLSData(thread);
  }
}

JvmtiGlobalTLSData* ThreadUtil::GetGlobalTLSData(art::Thread* thread) {
  return reinterpret_cast<JvmtiGlobalTLSData*>(thread->GetCustomTLS(kJvmtiTlsKey));
}

jvmtiError ThreadUtil::GetThreadLocalStorage(jvmtiEnv* env,
                                             jthread thread,
                                             void** data_ptr) {
  if (data_ptr == nullptr) {
    return ERR(NULL_POINTER);
  }

  art::Thread* self = art::Thread::Current();
  art::ScopedObjectAccess soa(self);
  art::MutexLock mu(self, *art::Locks::thread_list_lock_);
  art::Thread* target = nullptr;
  jvmtiError err = ERR(INTERNAL);
  if (!GetAliveNativeThread(thread, soa, &target, &err)) {
    return err;
  }

  JvmtiGlobalTLSData* global_tls = GetGlobalTLSData(target);
  if (global_tls == nullptr) {
    *data_ptr = nullptr;
    return OK;
  }
  auto it = global_tls->data.find(env);
  if (it != global_tls->data.end()) {
    *data_ptr = const_cast<void*>(it->second);
  } else {
    *data_ptr = nullptr;
  }

  return ERR(NONE);
}

struct AgentData {
  const void* arg;
  jvmtiStartFunction proc;
  jthread thread;
  JavaVM* java_vm;
  jvmtiEnv* jvmti_env;
  jint priority;
  std::string name;
};

static void* AgentCallback(void* arg) {
  std::unique_ptr<AgentData> data(reinterpret_cast<AgentData*>(arg));
  CHECK(data->thread != nullptr);

  // We already have a peer. So call our special Attach function.
  art::Thread* self = art::Thread::Attach(data->name.c_str(), true, data->thread);
  CHECK(self != nullptr) << "threads_being_born_ should have ensured thread could be attached.";
  // The name in Attach() is only for logging. Set the thread name. This is important so
  // that the thread is no longer seen as starting up.
  {
    art::ScopedObjectAccess soa(self);
    self->SetThreadName(data->name.c_str());
  }

  // Release the peer.
  JNIEnv* env = self->GetJniEnv();
  env->DeleteGlobalRef(data->thread);
  data->thread = nullptr;

  {
    // The StartThreadBirth was called in the parent thread. We let the runtime know we are up
    // before going into the provided code.
    art::MutexLock mu(art::Thread::Current(), *art::Locks::runtime_shutdown_lock_);
    art::Runtime::Current()->EndThreadBirth();
  }

  // Run the agent code.
  data->proc(data->jvmti_env, env, const_cast<void*>(data->arg));

  // Detach the thread.
  int detach_result = data->java_vm->DetachCurrentThread();
  CHECK_EQ(detach_result, 0);

  return nullptr;
}

jvmtiError ThreadUtil::RunAgentThread(jvmtiEnv* jvmti_env,
                                      jthread thread,
                                      jvmtiStartFunction proc,
                                      const void* arg,
                                      jint priority) {
  if (!PhaseUtil::IsLivePhase()) {
    return ERR(WRONG_PHASE);
  }
  if (priority < JVMTI_THREAD_MIN_PRIORITY || priority > JVMTI_THREAD_MAX_PRIORITY) {
    return ERR(INVALID_PRIORITY);
  }
  JNIEnv* env = art::Thread::Current()->GetJniEnv();
  if (thread == nullptr || !env->IsInstanceOf(thread, art::WellKnownClasses::java_lang_Thread)) {
    return ERR(INVALID_THREAD);
  }
  if (proc == nullptr) {
    return ERR(NULL_POINTER);
  }

  {
    art::Runtime* runtime = art::Runtime::Current();
    art::MutexLock mu(art::Thread::Current(), *art::Locks::runtime_shutdown_lock_);
    if (runtime->IsShuttingDownLocked()) {
      // The runtime is shutting down so we cannot create new threads.
      // TODO It's not fully clear from the spec what we should do here. We aren't yet in
      // JVMTI_PHASE_DEAD so we cannot return ERR(WRONG_PHASE) but creating new threads is now
      // impossible. Existing agents don't seem to generally do anything with this return value so
      // it doesn't matter too much. We could do something like sending a fake ThreadStart event
      // even though code is never actually run.
      return ERR(INTERNAL);
    }
    runtime->StartThreadBirth();
  }

  std::unique_ptr<AgentData> data(new AgentData);
  data->arg = arg;
  data->proc = proc;
  // We need a global ref for Java objects, as local refs will be invalid.
  data->thread = env->NewGlobalRef(thread);
  data->java_vm = art::Runtime::Current()->GetJavaVM();
  data->jvmti_env = jvmti_env;
  data->priority = priority;
  ScopedLocalRef<jstring> s(
      env,
      reinterpret_cast<jstring>(
          env->GetObjectField(thread, art::WellKnownClasses::java_lang_Thread_name)));
  if (s == nullptr) {
    data->name = "JVMTI Agent Thread";
  } else {
    ScopedUtfChars name(env, s.get());
    data->name = name.c_str();
  }

  pthread_t pthread;
  int pthread_create_result = pthread_create(&pthread,
                                            nullptr,
                                            &AgentCallback,
                                            reinterpret_cast<void*>(data.get()));
  if (pthread_create_result != 0) {
    // If the create succeeded the other thread will call EndThreadBirth.
    art::Runtime* runtime = art::Runtime::Current();
    art::MutexLock mu(art::Thread::Current(), *art::Locks::runtime_shutdown_lock_);
    runtime->EndThreadBirth();
    return ERR(INTERNAL);
  }
  data.release();  // NOLINT pthreads API.

  return ERR(NONE);
}

jvmtiError ThreadUtil::SuspendOther(art::Thread* self,
                                    jthread target_jthread) {
  // Loop since we need to bail out and try again if we would end up getting suspended while holding
  // the user_code_suspension_lock_ due to a SuspendReason::kForUserCode. In this situation we
  // release the lock, wait to get resumed and try again.
  do {
    // Suspend ourself if we have any outstanding suspends. This is so we won't suspend due to
    // another SuspendThread in the middle of suspending something else potentially causing a
    // deadlock. We need to do this in the loop because if we ended up back here then we had
    // outstanding SuspendReason::kForUserCode suspensions and we should wait for them to be cleared
    // before continuing.
    SuspendCheck(self);
    art::MutexLock mu(self, *art::Locks::user_code_suspension_lock_);
    if (WouldSuspendForUserCodeLocked(self)) {
      // Make sure we won't be suspended in the middle of holding the thread_suspend_count_lock_ by
      // a user-code suspension. We retry and do another SuspendCheck to clear this.
      continue;
    }
    // We are not going to be suspended by user code from now on.
    {
      art::ScopedObjectAccess soa(self);
      art::MutexLock thread_list_mu(self, *art::Locks::thread_list_lock_);
      art::Thread* target = nullptr;
      jvmtiError err = ERR(INTERNAL);
      if (!GetAliveNativeThread(target_jthread, soa, &target, &err)) {
        return err;
      }
      art::ThreadState state = target->GetState();
      if (state == art::ThreadState::kStarting || target->IsStillStarting()) {
        return ERR(THREAD_NOT_ALIVE);
      } else {
        art::MutexLock thread_suspend_count_mu(self, *art::Locks::thread_suspend_count_lock_);
        if (target->GetUserCodeSuspendCount() != 0) {
          return ERR(THREAD_SUSPENDED);
        }
      }
    }
    bool timeout = true;
    art::Thread* ret_target = art::Runtime::Current()->GetThreadList()->SuspendThreadByPeer(
        target_jthread,
        /* request_suspension= */ true,
        art::SuspendReason::kForUserCode,
        &timeout);
    if (ret_target == nullptr && !timeout) {
      // TODO It would be good to get more information about why exactly the thread failed to
      // suspend.
      return ERR(INTERNAL);
    } else if (!timeout) {
      // we didn't time out and got a result.
      return OK;
    }
    // We timed out. Just go around and try again.
  } while (true);
  UNREACHABLE();
}

jvmtiError ThreadUtil::SuspendSelf(art::Thread* self) {
  CHECK(self == art::Thread::Current());
  {
    art::MutexLock mu(self, *art::Locks::user_code_suspension_lock_);
    art::MutexLock thread_list_mu(self, *art::Locks::thread_suspend_count_lock_);
    if (self->GetUserCodeSuspendCount() != 0) {
      // This can only happen if we race with another thread to suspend 'self' and we lose.
      return ERR(THREAD_SUSPENDED);
    }
    // We shouldn't be able to fail this.
    if (!self->ModifySuspendCount(self, +1, nullptr, art::SuspendReason::kForUserCode)) {
      // TODO More specific error would be nice.
      return ERR(INTERNAL);
    }
  }
  // Once we have requested the suspend we actually go to sleep. We need to do this after releasing
  // the suspend_lock to make sure we can be woken up. This call gains the mutator lock causing us
  // to go to sleep until we are resumed.
  SuspendCheck(self);
  return OK;
}

jvmtiError ThreadUtil::SuspendThread(jvmtiEnv* env ATTRIBUTE_UNUSED, jthread thread) {
  art::Thread* self = art::Thread::Current();
  bool target_is_self = false;
  {
    art::ScopedObjectAccess soa(self);
    art::MutexLock mu(self, *art::Locks::thread_list_lock_);
    art::Thread* target = nullptr;
    jvmtiError err = ERR(INTERNAL);
    if (!GetAliveNativeThread(thread, soa, &target, &err)) {
      return err;
    } else if (target == self) {
      target_is_self = true;
    }
  }
  if (target_is_self) {
    return SuspendSelf(self);
  } else {
    return SuspendOther(self, thread);
  }
}

jvmtiError ThreadUtil::ResumeThread(jvmtiEnv* env ATTRIBUTE_UNUSED,
                                    jthread thread) {
  if (thread == nullptr) {
    return ERR(NULL_POINTER);
  }
  art::Thread* self = art::Thread::Current();
  art::Thread* target;
  // Retry until we know we won't get suspended by user code while resuming something.
  do {
    SuspendCheck(self);
    art::MutexLock ucsl_mu(self, *art::Locks::user_code_suspension_lock_);
    if (WouldSuspendForUserCodeLocked(self)) {
      // Make sure we won't be suspended in the middle of holding the thread_suspend_count_lock_ by
      // a user-code suspension. We retry and do another SuspendCheck to clear this.
      continue;
    }
    // From now on we know we cannot get suspended by user-code.
    {
      // NB This does a SuspendCheck (during thread state change) so we need to make sure we don't
      // have the 'suspend_lock' locked here.
      art::ScopedObjectAccess soa(self);
      art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_);
      jvmtiError err = ERR(INTERNAL);
      if (!GetAliveNativeThread(thread, soa, &target, &err)) {
        return err;
      } else if (target == self) {
        // We would have paused until we aren't suspended anymore due to the ScopedObjectAccess so
        // we can just return THREAD_NOT_SUSPENDED. Unfortunately we cannot do any real DCHECKs
        // about current state since it's all concurrent.
        return ERR(THREAD_NOT_SUSPENDED);
      }
      // The JVMTI spec requires us to return THREAD_NOT_SUSPENDED if it is alive but we really
      // cannot tell why resume failed.
      {
        art::MutexLock thread_suspend_count_mu(self, *art::Locks::thread_suspend_count_lock_);
        if (target->GetUserCodeSuspendCount() == 0) {
          return ERR(THREAD_NOT_SUSPENDED);
        }
      }
    }
    // It is okay that we don't have a thread_list_lock here since we know that the thread cannot
    // die since it is currently held suspended by a SuspendReason::kForUserCode suspend.
    DCHECK(target != self);
    if (!art::Runtime::Current()->GetThreadList()->Resume(target,
                                                          art::SuspendReason::kForUserCode)) {
      // TODO Give a better error.
      // This is most likely THREAD_NOT_SUSPENDED but we cannot really be sure.
      return ERR(INTERNAL);
    } else {
      return OK;
    }
  } while (true);
}

static bool IsCurrentThread(jthread thr) {
  if (thr == nullptr) {
    return true;
  }
  art::Thread* self = art::Thread::Current();
  art::ScopedObjectAccess soa(self);
  art::MutexLock mu(self, *art::Locks::thread_list_lock_);
  art::Thread* target = nullptr;
  jvmtiError err_unused = ERR(INTERNAL);
  if (ThreadUtil::GetNativeThread(thr, soa, &target, &err_unused)) {
    return target == self;
  } else {
    return false;
  }
}

// Suspends all the threads in the list at the same time. Getting this behavior is a little tricky
// since we can have threads in the list multiple times. This generally doesn't matter unless the
// current thread is present multiple times. In that case we need to suspend only once and either
// return the same error code in all the other slots if it failed or return ERR(THREAD_SUSPENDED) if
// it didn't. We also want to handle the current thread last to make the behavior of the code
// simpler to understand.
jvmtiError ThreadUtil::SuspendThreadList(jvmtiEnv* env,
                                         jint request_count,
                                         const jthread* threads,
                                         jvmtiError* results) {
  if (request_count == 0) {
    return ERR(ILLEGAL_ARGUMENT);
  } else if (results == nullptr || threads == nullptr) {
    return ERR(NULL_POINTER);
  }
  // This is the list of the indexes in 'threads' and 'results' that correspond to the currently
  // running thread. These indexes we need to handle specially since we need to only actually
  // suspend a single time.
  std::vector<jint> current_thread_indexes;
  for (jint i = 0; i < request_count; i++) {
    if (IsCurrentThread(threads[i])) {
      current_thread_indexes.push_back(i);
    } else {
      results[i] = env->SuspendThread(threads[i]);
    }
  }
  if (!current_thread_indexes.empty()) {
    jint first_current_thread_index = current_thread_indexes[0];
    // Suspend self.
    jvmtiError res = env->SuspendThread(threads[first_current_thread_index]);
    results[first_current_thread_index] = res;
    // Fill in the rest of the error values as appropriate.
    jvmtiError other_results = (res != OK) ? res : ERR(THREAD_SUSPENDED);
    for (auto it = ++current_thread_indexes.begin(); it != current_thread_indexes.end(); ++it) {
      results[*it] = other_results;
    }
  }
  return OK;
}

jvmtiError ThreadUtil::ResumeThreadList(jvmtiEnv* env,
                                        jint request_count,
                                        const jthread* threads,
                                        jvmtiError* results) {
  if (request_count == 0) {
    return ERR(ILLEGAL_ARGUMENT);
  } else if (results == nullptr || threads == nullptr) {
    return ERR(NULL_POINTER);
  }
  for (jint i = 0; i < request_count; i++) {
    results[i] = env->ResumeThread(threads[i]);
  }
  return OK;
}

jvmtiError ThreadUtil::StopThread(jvmtiEnv* env ATTRIBUTE_UNUSED,
                                  jthread thread,
                                  jobject exception) {
  art::Thread* self = art::Thread::Current();
  art::ScopedObjectAccess soa(self);
  art::StackHandleScope<1> hs(self);
  if (exception == nullptr) {
    return ERR(INVALID_OBJECT);
  }
  art::ObjPtr<art::mirror::Object> obj(soa.Decode<art::mirror::Object>(exception));
  if (!obj->GetClass()->IsThrowableClass()) {
    return ERR(INVALID_OBJECT);
  }
  art::Handle<art::mirror::Throwable> exc(hs.NewHandle(obj->AsThrowable()));
  art::Locks::thread_list_lock_->ExclusiveLock(self);
  art::Thread* target = nullptr;
  jvmtiError err = ERR(INTERNAL);
  if (!GetAliveNativeThread(thread, soa, &target, &err)) {
    art::Locks::thread_list_lock_->ExclusiveUnlock(self);
    return err;
  } else if (target->GetState() == art::ThreadState::kStarting || target->IsStillStarting()) {
    art::Locks::thread_list_lock_->ExclusiveUnlock(self);
    return ERR(THREAD_NOT_ALIVE);
  }
  struct StopThreadClosure : public art::Closure {
   public:
    explicit StopThreadClosure(art::Handle<art::mirror::Throwable> except) : exception_(except) { }

    void Run(art::Thread* me) override REQUIRES_SHARED(art::Locks::mutator_lock_) {
      // Make sure the thread is prepared to notice the exception.
      art::Runtime::Current()->GetInstrumentation()->InstrumentThreadStack(me);
      me->SetAsyncException(exception_.Get());
      // Wake up the thread if it is sleeping.
      me->Notify();
    }

   private:
    art::Handle<art::mirror::Throwable> exception_;
  };
  StopThreadClosure c(exc);
  // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution.
  if (target->RequestSynchronousCheckpoint(&c)) {
    return OK;
  } else {
    // Something went wrong, probably the thread died.
    return ERR(THREAD_NOT_ALIVE);
  }
}

jvmtiError ThreadUtil::InterruptThread(jvmtiEnv* env ATTRIBUTE_UNUSED, jthread thread) {
  art::Thread* self = art::Thread::Current();
  art::ScopedObjectAccess soa(self);
  art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_);
  art::Thread* target = nullptr;
  jvmtiError err = ERR(INTERNAL);
  if (!GetAliveNativeThread(thread, soa, &target, &err)) {
    return err;
  } else if (target->GetState() == art::ThreadState::kStarting || target->IsStillStarting()) {
    return ERR(THREAD_NOT_ALIVE);
  }
  target->Interrupt(self);
  return OK;
}

}  // namespace openjdkjvmti
