/* 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 "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_) {
    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")) {
          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());
}

void ThreadUtil::CacheData() {
  // We must have started since it is now safe to cache our data;
  gThreadCallback.started = true;
  art::ScopedObjectAccess soa(art::Thread::Current());
  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);
}

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
