/* 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_threadgroup.h"

#include "art_field-inl.h"
#include "art_jvmti.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/mutex.h"
#include "handle_scope-inl.h"
#include "jni/jni_internal.h"
#include "mirror/class.h"
#include "mirror/object-inl.h"
#include "mirror/string.h"
#include "obj_ptr.h"
#include "object_lock.h"
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
#include "thread-current-inl.h"
#include "thread_list.h"
#include "well_known_classes-inl.h"

namespace openjdkjvmti {


jvmtiError ThreadGroupUtil::GetTopThreadGroups(jvmtiEnv* env,
                                               jint* group_count_ptr,
                                               jthreadGroup** groups_ptr) {
  // We only have a single top group. So we can take the current thread and move upwards.
  if (group_count_ptr == nullptr || groups_ptr == nullptr) {
    return ERR(NULL_POINTER);
  }

  art::Runtime* runtime = art::Runtime::Current();
  if (runtime == nullptr) {
    // Must be starting the runtime, or dying.
    return ERR(WRONG_PHASE);
  }

  jobject sys_thread_group = runtime->GetSystemThreadGroup();
  if (sys_thread_group == nullptr) {
    // Seems we're still starting up.
    return ERR(WRONG_PHASE);
  }

  unsigned char* data;
  jvmtiError result = env->Allocate(sizeof(jthreadGroup), &data);
  if (result != ERR(NONE)) {
    return result;
  }

  jthreadGroup* groups = reinterpret_cast<jthreadGroup*>(data);
  *groups =
      reinterpret_cast<JNIEnv*>(art::Thread::Current()->GetJniEnv())->NewLocalRef(sys_thread_group);
  *groups_ptr = groups;
  *group_count_ptr = 1;

  return ERR(NONE);
}

jvmtiError ThreadGroupUtil::GetThreadGroupInfo(jvmtiEnv* env,
                                               jthreadGroup group,
                                               jvmtiThreadGroupInfo* info_ptr) {
  if (group == nullptr) {
    return ERR(INVALID_THREAD_GROUP);
  }

  art::ScopedObjectAccess soa(art::Thread::Current());
  art::StackHandleScope<2> hs(soa.Self());
  art::Handle<art::mirror::Class> tg_class =
      hs.NewHandle(art::WellKnownClasses::java_lang_ThreadGroup.Get());
  art::Handle<art::mirror::Object> thread_group =
      hs.NewHandle(soa.Decode<art::mirror::Object>(group));
  if (!thread_group->InstanceOf(tg_class.Get())) {
    return ERR(INVALID_THREAD_GROUP);
  }

  // Do the name first. It's the only thing that can fail.
  {
    art::ArtField* name_field = art::WellKnownClasses::java_lang_ThreadGroup_name;
    CHECK(name_field != nullptr);
    art::ObjPtr<art::mirror::String> name_obj =
        art::ObjPtr<art::mirror::String>::DownCast(name_field->GetObject(thread_group.Get()));
    std::string tmp_str;
    const char* tmp_cstr;
    if (name_obj == nullptr) {
      tmp_cstr = "";
    } else {
      tmp_str = name_obj->ToModifiedUtf8();
      tmp_cstr = tmp_str.c_str();
    }
    jvmtiError result;
    JvmtiUniquePtr<char[]> copy = CopyString(env, tmp_cstr, &result);
    if (copy == nullptr) {
      return result;
    }
    info_ptr->name = copy.release();
  }

  // Parent.
  {
    art::ArtField* parent_field = art::WellKnownClasses::java_lang_ThreadGroup_parent;
    CHECK(parent_field != nullptr);
    art::ObjPtr<art::mirror::Object> parent_group = parent_field->GetObject(thread_group.Get());
    info_ptr->parent = parent_group == nullptr
                           ? nullptr
                           : soa.AddLocalReference<jthreadGroup>(parent_group);
  }

  // Max priority.
  {
    art::ArtField* prio_field = tg_class->FindDeclaredInstanceField("maxPriority", "I");
    CHECK(prio_field != nullptr);
    info_ptr->max_priority = static_cast<jint>(prio_field->GetInt(thread_group.Get()));
  }

  // Daemon.
  {
    art::ArtField* daemon_field = tg_class->FindDeclaredInstanceField("daemon", "Z");
    CHECK(daemon_field != nullptr);
    info_ptr->is_daemon = daemon_field->GetBoolean(thread_group.Get()) == 0 ? JNI_FALSE : JNI_TRUE;
  }

  return ERR(NONE);
}


static bool IsInDesiredThreadGroup(art::Handle<art::mirror::Object> desired_thread_group,
                                   art::ObjPtr<art::mirror::Object> peer)
    REQUIRES_SHARED(art::Locks::mutator_lock_) {
  CHECK(desired_thread_group != nullptr);

  art::ArtField* thread_group_field = art::WellKnownClasses::java_lang_Thread_group;
  DCHECK(thread_group_field != nullptr);
  art::ObjPtr<art::mirror::Object> group = thread_group_field->GetObject(peer);
  return (group == desired_thread_group.Get());
}

static void GetThreads(art::Handle<art::mirror::Object> thread_group,
                       std::vector<art::ObjPtr<art::mirror::Object>>* thread_peers)
    REQUIRES_SHARED(art::Locks::mutator_lock_) REQUIRES(!art::Locks::thread_list_lock_) {
  CHECK(thread_group != nullptr);

  art::MutexLock mu(art::Thread::Current(), *art::Locks::thread_list_lock_);
  for (art::Thread* t : art::Runtime::Current()->GetThreadList()->GetList()) {
    if (t->IsStillStarting()) {
      continue;
    }
    art::ObjPtr<art::mirror::Object> peer = t->GetPeerFromOtherThread();
    if (peer == nullptr) {
      continue;
    }
    if (IsInDesiredThreadGroup(thread_group, peer)) {
      thread_peers->push_back(peer);
    }
  }
}

static void GetChildThreadGroups(art::Handle<art::mirror::Object> thread_group,
                                 std::vector<art::ObjPtr<art::mirror::Object>>* thread_groups)
    REQUIRES_SHARED(art::Locks::mutator_lock_) {
  CHECK(thread_group != nullptr);

  // Get the ThreadGroup[] "groups" out of this thread group...
  art::ArtField* groups_field = art::WellKnownClasses::java_lang_ThreadGroup_groups;
  art::ObjPtr<art::mirror::Object> groups_array = groups_field->GetObject(thread_group.Get());

  if (groups_array == nullptr) {
    return;
  }
  CHECK(groups_array->IsObjectArray());

  art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> groups_array_as_array =
      groups_array->AsObjectArray<art::mirror::Object>();

  // Copy all non-null elements.
  for (auto entry : groups_array_as_array->Iterate()) {
    if (entry != nullptr) {
      thread_groups->push_back(entry);
    }
  }
}

jvmtiError ThreadGroupUtil::GetThreadGroupChildren(jvmtiEnv* env,
                                                   jthreadGroup group,
                                                   jint* thread_count_ptr,
                                                   jthread** threads_ptr,
                                                   jint* group_count_ptr,
                                                   jthreadGroup** groups_ptr) {
  if (group == nullptr) {
    return ERR(INVALID_THREAD_GROUP);
  }

  art::ScopedObjectAccess soa(art::Thread::Current());
  art::StackHandleScope<1> hs(soa.Self());
  art::Handle<art::mirror::Object> thread_group =
      hs.NewHandle(soa.Decode<art::mirror::Object>(group));
  if (!thread_group->InstanceOf(art::WellKnownClasses::java_lang_ThreadGroup.Get())) {
    return ERR(INVALID_THREAD_GROUP);
  }


  art::ObjectLock<art::mirror::Object> thread_group_lock(soa.Self(), thread_group);

  std::vector<art::ObjPtr<art::mirror::Object>> thread_peers;
  GetThreads(thread_group, &thread_peers);

  std::vector<art::ObjPtr<art::mirror::Object>> thread_groups;
  GetChildThreadGroups(thread_group, &thread_groups);

  JvmtiUniquePtr<jthread[]> peers_uptr;
  if (!thread_peers.empty()) {
    jvmtiError res;
    peers_uptr = AllocJvmtiUniquePtr<jthread[]>(env, thread_peers.size(), &res);
    if (peers_uptr == nullptr) {
      return res;
    }
  }

  JvmtiUniquePtr<jthreadGroup[]> group_uptr;
  if (!thread_groups.empty()) {
    jvmtiError res;
    group_uptr = AllocJvmtiUniquePtr<jthreadGroup[]>(env, thread_groups.size(), &res);
    if (group_uptr == nullptr) {
      return res;
    }
  }

  // Can't fail anymore from here on.

  // Copy data into out buffers.
  for (size_t i = 0; i != thread_peers.size(); ++i) {
    peers_uptr[i] = soa.AddLocalReference<jthread>(thread_peers[i]);
  }
  for (size_t i = 0; i != thread_groups.size(); ++i) {
    group_uptr[i] = soa.AddLocalReference<jthreadGroup>(thread_groups[i]);
  }

  *thread_count_ptr = static_cast<jint>(thread_peers.size());
  *threads_ptr = peers_uptr.release();
  *group_count_ptr = static_cast<jint>(thread_groups.size());
  *groups_ptr = group_uptr.release();

  return ERR(NONE);
}

}  // namespace openjdkjvmti
