/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "java_lang_Thread.h"

#include "android-base/logging.h"
#include "android-base/macros.h"
#include "art_field-inl.h"
#include "art_field.h"
#include "art_method.h"
#include "base/casts.h"
#include "base/utils.h"
#include "class_linker.h"
#include "class_root-inl.h"
#include "common_throws.h"
#include "handle_scope-inl.h"
#include "handle_scope.h"
#include "interpreter/shadow_frame-inl.h"
#include "interpreter/shadow_frame.h"
#include "jni.h"
#include "jni/jni_internal.h"
#include "mirror/class-alloc-inl.h"
#include "mirror/class.h"
#include "mirror/object-inl.h"
#include "mirror/object.h"
#include "mirror/object_array-alloc-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/object_array.h"
#include "mirror/object_reference.h"
#include "mirror/throwable.h"
#include "monitor.h"
#include "native_util.h"
#include "nativehelper/jni_macros.h"
#include "nativehelper/scoped_utf_chars.h"
#include "obj_ptr.h"
#include "runtime.h"
#include "scoped_fast_native_object_access-inl.h"
#include "scoped_thread_state_change-inl.h"
#include "stack.h"
#include "stack_reference.h"
#include "thread.h"
#include "thread_list.h"
#include "verify_object.h"
#include "virtual_thread_common.h"
#include "well_known_classes.h"

namespace art HIDDEN {

static jobject Thread_currentCarrierThread(JNIEnv* env, jclass) {
  ScopedFastNativeObjectAccess soa(env);
  return soa.AddLocalReference<jobject>(soa.Self()->GetPeer());
}

static jobject Thread_currentThread(JNIEnv* env, jclass) {
  ScopedFastNativeObjectAccess soa(env);
  return soa.AddLocalReference<jobject>(soa.Self()->GetCurrentPeer());
}

static void Thread_setCurrentThreadNative(JNIEnv* env, jclass, jobject java_thread) {
  ScopedFastNativeObjectAccess soa(env);
  ObjPtr<mirror::Object> new_current_thread = soa.Decode<mirror::Object>(java_thread);
  soa.Self()->SetCurrentPeer(new_current_thread.Ptr());
}

static jboolean Thread_interrupted() {
  return Thread::Current()->Interrupted() ? JNI_TRUE : JNI_FALSE;
}

static jboolean Thread_isInterrupted(JNIEnv* env, jobject java_thread) {
  ScopedFastNativeObjectAccess soa(env);
  MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
  Thread* thread = Thread::FromManagedThread(soa, java_thread);
  return (thread != nullptr) ? thread->IsInterrupted() : JNI_FALSE;
}

static void Thread_nativeCreate(JNIEnv* env, jclass, jobject java_thread, jlong stack_size,
                                jboolean daemon) {
  // There are sections in the zygote that forbid thread creation.
  Runtime* runtime = Runtime::Current();
  if (runtime->IsZygote() && runtime->IsZygoteNoThreadSection()) {
    jclass internal_error = env->FindClass("java/lang/InternalError");
    CHECK(internal_error != nullptr);
    env->ThrowNew(internal_error, "Cannot create threads in zygote");
    return;
  }

  Thread::CreateNativeThread(env, java_thread, stack_size, daemon == JNI_TRUE);
}

static jint Thread_nativeGetStatus(JNIEnv* env, jobject java_thread, jboolean has_been_started) {
  // Ordinals from Java's Thread.State.
  const jint kJavaNew = 0;
  const jint kJavaRunnable = 1;
  const jint kJavaBlocked = 2;
  const jint kJavaWaiting = 3;
  const jint kJavaTimedWaiting = 4;
  const jint kJavaTerminated = 5;

  ScopedObjectAccess soa(env);
  ThreadState internal_thread_state =
      (has_been_started ? ThreadState::kTerminated : ThreadState::kStarting);
  MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
  Thread* thread = Thread::FromManagedThread(soa, java_thread);
  if (thread != nullptr) {
    internal_thread_state = thread->GetState();
  }
  switch (internal_thread_state) {
    case ThreadState::kTerminated:                     return kJavaTerminated;
    case ThreadState::kRunnable:                       return kJavaRunnable;
    case ThreadState::kObsoleteRunnable:               break;  // Obsolete value.
    case ThreadState::kTimedWaiting:                   return kJavaTimedWaiting;
    case ThreadState::kSleeping:                       return kJavaTimedWaiting;
    case ThreadState::kBlocked:                        return kJavaBlocked;
    case ThreadState::kWaiting:                        return kJavaWaiting;
    case ThreadState::kStarting:                       return kJavaNew;
    case ThreadState::kNative:                         return kJavaRunnable;
    case ThreadState::kWaitingForTaskProcessor:        return kJavaWaiting;
    case ThreadState::kWaitingForLockInflation:        return kJavaWaiting;
    case ThreadState::kWaitingForGcToComplete:         return kJavaWaiting;
    case ThreadState::kWaitingPerformingGc:            return kJavaWaiting;
    case ThreadState::kWaitingForCheckPointsToRun:     return kJavaWaiting;
    case ThreadState::kWaitingForDebuggerSend:         return kJavaWaiting;
    case ThreadState::kWaitingForDebuggerToAttach:     return kJavaWaiting;
    case ThreadState::kWaitingInMainDebuggerLoop:      return kJavaWaiting;
    case ThreadState::kWaitingForDebuggerSuspension:   return kJavaWaiting;
    case ThreadState::kWaitingForDeoptimization:       return kJavaWaiting;
    case ThreadState::kWaitingForGetObjectsAllocated:  return kJavaWaiting;
    case ThreadState::kWaitingForJniOnLoad:            return kJavaWaiting;
    case ThreadState::kWaitingForSignalCatcherOutput:  return kJavaWaiting;
    case ThreadState::kWaitingInMainSignalCatcherLoop: return kJavaWaiting;
    case ThreadState::kWaitingForMethodTracingStart:   return kJavaWaiting;
    case ThreadState::kWaitingForVisitObjects:         return kJavaWaiting;
    case ThreadState::kWaitingWeakGcRootRead:          return kJavaRunnable;
    case ThreadState::kWaitingForGcThreadFlip:         return kJavaWaiting;
    case ThreadState::kNativeForAbort:                 return kJavaWaiting;
    case ThreadState::kSuspended:                      return kJavaRunnable;
    case ThreadState::kInvalidState:                   break;
    // Don't add a 'default' here so the compiler can spot incompatible enum changes.
  }
  LOG(ERROR) << "Unexpected thread state: " << internal_thread_state;
  return -1;  // Unreachable.
}

static jboolean Thread_holdsLock(JNIEnv* env, jclass, jobject java_object) {
  ScopedFastNativeObjectAccess soa(env);
  ObjPtr<mirror::Object> object = soa.Decode<mirror::Object>(java_object);
  if (object == nullptr) {
    ThrowNullPointerException("object == null");
    return JNI_FALSE;
  }
  Thread* thread = soa.Self();
  return thread->HoldsLock(object);
}

static void Thread_interrupt0(JNIEnv* env, jobject java_thread) {
  ScopedFastNativeObjectAccess soa(env);
  MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
  Thread* thread = Thread::FromManagedThread(soa, java_thread);
  if (thread != nullptr) {
    thread->Interrupt(soa.Self());
  }
}

static void Thread_setNativeName(JNIEnv* env, jobject peer, jstring java_name) {
  ScopedUtfChars name(env, java_name);
  {
    ScopedObjectAccess soa(env);
    if (soa.Decode<mirror::Object>(peer) == soa.Self()->GetPeer()) {
      soa.Self()->SetThreadName(name.c_str());
      return;
    }
  }
  // Suspend thread to avoid it from killing itself while we set its name. We don't just hold the
  // thread list lock to avoid this, as setting the thread name causes mutator to lock/unlock
  // in the DDMS send code.
  ThreadList* thread_list = Runtime::Current()->GetThreadList();
  // Take suspend thread lock to avoid races with threads trying to suspend this one.
  Thread* thread = thread_list->SuspendThreadByPeer(peer, SuspendReason::kInternal);
  if (thread != nullptr) {
    {
      ScopedObjectAccess soa(env);
      thread->SetThreadName(name.c_str());
    }
    bool resumed = thread_list->Resume(thread, SuspendReason::kInternal);
    DCHECK(resumed);
  }
}

/*
 * Change Linux niceness priority for the given thread, returning errno.
 */
static int Thread_setNiceness0([[maybe_unused]] JNIEnv* env, jobject java_thread, jint new_niceness)
    REQUIRES_SHARED(art::Locks::mutator_lock_) {
  Thread* self = Thread::Current();
  MutexLock mu(self, *Locks::thread_list_lock_);
  Thread* thread = Thread::FromManagedThread(self, self->DecodeJObject(java_thread));
  if (thread != nullptr) {
    return thread->SetNativeNiceness(new_niceness);
  }
  return 0;
}

/*
 * Alter the priority of the specified thread.  "new_priority" will range
 * from Thread.MIN_PRIORITY to Thread.MAX_PRIORITY (1-10), with "normal"
 * threads at Thread.NORM_PRIORITY (5). Returns corresponding niceness.
 */
static void Thread_setPriority0([[maybe_unused]] JNIEnv* env,
                                jobject java_thread,
                                jint new_priority,
                                jint new_niceness) REQUIRES_SHARED(art::Locks::mutator_lock_) {
  // We should just do the conversion and call the above. But that would bypass the
  // Android S workaround in SetNativePriority. So we have a separate code path.
  Thread* self = Thread::Current();
  MutexLock mu(self, *Locks::thread_list_lock_);
  Thread* thread = Thread::FromManagedThread(self, self->DecodeJObject(java_thread));
  if (thread != nullptr) {
    thread->SetNativePriority(new_priority, new_niceness);
  }
}

static int Thread_priorityForNiceness(int niceness) {
  return (Thread::NicenessToPriority(niceness));
}

static int Thread_nicenessForPriority(int priority) {
  return (Thread::PriorityToNiceness(priority));
}

static void Thread_sleep(JNIEnv* env, jclass, jobject java_lock, jlong ms, jint ns) {
  ScopedFastNativeObjectAccess soa(env);
  ObjPtr<mirror::Object> lock = soa.Decode<mirror::Object>(java_lock);
  Monitor::Wait(Thread::Current(), lock.Ptr(), ms, ns, true, ThreadState::kSleeping);
}

/*
 * Causes the thread to temporarily pause and allow other threads to execute.
 *
 * The exact behavior is poorly defined.  Some discussion here:
 *   http://www.cs.umd.edu/~pugh/java/memoryModel/archive/0944.html
 */
static void Thread_yield0(JNIEnv*, jobject) { sched_yield(); }

static void Thread_parkVirtualInternal(
    JNIEnv* env, jobject, jobject v_context, jobject parked_states, jobject vm_error) {
  CHECK(kIsVirtualThreadEnabled);
  ScopedObjectAccess soa(env);
  PinningReason reason;
  VirtualThreadPark(soa.Decode<mirror::VirtualThreadContext>(v_context),
                    soa.Decode<mirror::Object>(parked_states),
                    soa.Decode<mirror::Throwable>(vm_error),
                    /* is_continuation_api= */ false,
                    reason);
}

static jint Thread_acquireThinLockId(JNIEnv*, jobject) {
  CHECK(kIsVirtualThreadEnabled);
  ThreadList* thread_list = Runtime::Current()->GetThreadList();
  uint32_t thread_id = thread_list->AllocThreadId(Thread::Current());
  DCHECK_NE(thread_id, ThreadList::kInvalidThreadId);
  thread_list->AllocVirtualThreadSuspendCount(thread_id);
  return thread_id;
}

static void Thread_releaseThinLockId(JNIEnv*, jobject, jint thread_id) {
  CHECK(kIsVirtualThreadEnabled);
  ThreadList* thread_list = Runtime::Current()->GetThreadList();
  thread_list->ReleaseVirtualThreadSuspendCount(thread_id);
  thread_list->ReleaseThreadId(Thread::Current(), thread_id);
}

static JNINativeMethod gMethods[] = {
    FAST_NATIVE_METHOD(Thread, currentCarrierThread, "()Ljava/lang/Thread;"),
    FAST_NATIVE_METHOD(Thread, currentThread, "()Ljava/lang/Thread;"),
    FAST_NATIVE_METHOD(Thread, setCurrentThreadNative, "(Ljava/lang/Thread;)V"),
    CRITICAL_NATIVE_METHOD(Thread, interrupted, "()Z"),
    FAST_NATIVE_METHOD(Thread, isInterrupted, "()Z"),
    NATIVE_METHOD(Thread, nativeCreate, "(Ljava/lang/Thread;JZ)V"),
    NATIVE_METHOD(Thread, nativeGetStatus, "(Z)I"),
    CRITICAL_NATIVE_METHOD(Thread, nicenessForPriority, "(I)I"),
    FAST_NATIVE_METHOD(Thread, holdsLock, "(Ljava/lang/Object;)Z"),
    FAST_NATIVE_METHOD(Thread, interrupt0, "()V"),
    CRITICAL_NATIVE_METHOD(Thread, priorityForNiceness, "(I)I"),
    NATIVE_METHOD(Thread, setNativeName, "(Ljava/lang/String;)V"),
    NATIVE_METHOD(Thread, setNiceness0, "(I)I"),
    NATIVE_METHOD(Thread, setPriority0, "(II)V"),
    FAST_NATIVE_METHOD(Thread, sleep, "(Ljava/lang/Object;JI)V"),
    NATIVE_METHOD(Thread, yield0, "()V"),
    NATIVE_METHOD(Thread,
                  parkVirtualInternal,
                  "(Ldalvik/system/VirtualThreadContext;Ldalvik/system/"
                  "VirtualThreadParkedStates;Ldalvik/system/VirtualThreadParkingError;)V"),
    FAST_NATIVE_METHOD(Thread, acquireThinLockId, "()I"),
    FAST_NATIVE_METHOD(Thread, releaseThinLockId, "(I)V"),
};

void register_java_lang_Thread(JNIEnv* env) {
  REGISTER_NATIVE_METHODS("java/lang/Thread");
}

}  // namespace art
