/* 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 "deopt_manager.h"
#include "events-inl.h"
#include "gc/collector_type.h"
#include "gc/gc_cause.h"
#include "gc/scoped_gc_critical_section.h"
#include "gc/system_weak.h"
#include "gc_root-inl.h"
#include "jni/jni_internal.h"
#include "metrics/reporter.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;

ScopedNoUserCodeSuspension::ScopedNoUserCodeSuspension(art::Thread* self) : self_(self) {
  DCHECK_EQ(self, art::Thread::Current());
  // Loop until we both have the user_code_suspension_locK_ and don't have any pending user_code
  // suspensions.
  do {
    art::Locks::user_code_suspension_lock_->AssertNotHeld(self_);
    ThreadUtil::SuspendCheck(self_);

    art::Locks::user_code_suspension_lock_->ExclusiveLock(self_);
    if (ThreadUtil::WouldSuspendForUserCodeLocked(self_)) {
      art::Locks::user_code_suspension_lock_->ExclusiveUnlock(self_);
      continue;
    }

    art::Locks::user_code_suspension_lock_->AssertHeld(self_);

    return;
  } while (true);
}

ScopedNoUserCodeSuspension::~ScopedNoUserCodeSuspension() {
  art::Locks::user_code_suspension_lock_->ExclusiveUnlock(self_);
}

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; this includes the perfetto_hprof_listener signal handler thread for
      // perfetto_hprof, as well as the metrics background reporting thread.
      if (art::kIsDebugBuild) {
        std::string name;
        self->GetThreadName(name);
        if (name != "JDWP" && name != "Signal Catcher" && name != "perfetto_hprof_listener" &&
            name != art::metrics::MetricsReporter::kBackgroundThreadName &&
            !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) {
  art::ScopedExceptionStorage sse(soa.Self());
  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:
    case art::ThreadState::kNativeForAbort:
      // 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:
    case art::ThreadState::kNativeForAbort:
      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 = {};
  {
    ScopedNoUserCodeSuspension snucs(self);
    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) {
      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);
    }
  }

  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 {
    ScopedNoUserCodeSuspension snucs(self);
    // 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,
        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;

  // Make sure we won't get suspended ourselves while in the middle of resuming another thread.
  ScopedNoUserCodeSuspension snucs(self);
  // 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;
  }
}

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.
      DeoptManager::Get()->DeoptimizeThread(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
