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

#include <atomic>
#include <chrono>
#include <condition_variable>
#include <mutex>

#include "art_jvmti.h"
#include "monitor.h"
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
#include "thread-current-inl.h"
#include "ti_thread.h"
#include "thread.h"
#include "thread_pool.h"

namespace openjdkjvmti {

// We cannot use ART monitors, as they require the mutator lock for contention locking. We
// also cannot use pthread mutexes and condition variables (or C++11 abstractions) directly,
// as the do not have the right semantics for recursive mutexes and waiting (wait only unlocks
// the mutex once).
// So go ahead and use a wrapper that does the counting explicitly.

class JvmtiMonitor {
 public:
  JvmtiMonitor() : owner_(nullptr), count_(0) { }

  static bool Destroy(art::Thread* self, JvmtiMonitor* monitor) NO_THREAD_SAFETY_ANALYSIS {
    // Check whether this thread holds the monitor, or nobody does.
    art::Thread* owner_thread = monitor->owner_.load(std::memory_order_relaxed);
    if (owner_thread != nullptr && self != owner_thread) {
      return false;
    }

    if (monitor->count_ > 0) {
      monitor->count_ = 0;
      monitor->owner_.store(nullptr, std::memory_order_relaxed);
      monitor->mutex_.unlock();
    }

    delete monitor;
    return true;
  }

  void MonitorEnter(art::Thread* self) NO_THREAD_SAFETY_ANALYSIS {
    // Perform a suspend-check. The spec doesn't require this but real-world agents depend on this
    // behavior. We do this by performing a suspend-check then retrying if the thread is suspended
    // before or after locking the internal mutex.
    do {
      ThreadUtil::SuspendCheck(self);
      if (ThreadUtil::WouldSuspendForUserCode(self)) {
        continue;
      }

      // Check for recursive enter.
      if (IsOwner(self)) {
        count_++;
        return;
      }

      // Checking for user-code suspension takes acquiring 2 art::Mutexes so we want to avoid doing
      // that if possible. To avoid it we try to get the internal mutex without sleeping. If we do
      // this we don't bother doing another suspend check since it can linearize after the lock.
      if (mutex_.try_lock()) {
        break;
      } else {
        // Lock with sleep. We will need to check for suspension after this to make sure that agents
        // won't deadlock.
        mutex_.lock();
        if (!ThreadUtil::WouldSuspendForUserCode(self)) {
          break;
        } else {
          // We got suspended in the middle of waiting for the mutex. We should release the mutex
          // and try again so we can get it while not suspended. This lets some other
          // (non-suspended) thread acquire the mutex in case it's waiting to wake us up.
          mutex_.unlock();
          continue;
        }
      }
    } while (true);

    DCHECK(owner_.load(std::memory_order_relaxed) == nullptr);
    owner_.store(self, std::memory_order_relaxed);
    DCHECK_EQ(0u, count_);
    count_ = 1;
  }

  bool MonitorExit(art::Thread* self) NO_THREAD_SAFETY_ANALYSIS {
    if (!IsOwner(self)) {
      return false;
    }

    --count_;
    if (count_ == 0u) {
      owner_.store(nullptr, std::memory_order_relaxed);
      mutex_.unlock();
    }

    return true;
  }

  bool Wait(art::Thread* self) {
    auto wait_without_timeout = [&](std::unique_lock<std::mutex>& lk) {
      cond_.wait(lk);
    };
    return Wait(self, wait_without_timeout);
  }

  bool Wait(art::Thread* self, uint64_t timeout_in_ms) {
    auto wait_with_timeout = [&](std::unique_lock<std::mutex>& lk) {
      cond_.wait_for(lk, std::chrono::milliseconds(timeout_in_ms));
    };
    return Wait(self, wait_with_timeout);
  }

  bool Notify(art::Thread* self) {
    return Notify(self, [&]() { cond_.notify_one(); });
  }

  bool NotifyAll(art::Thread* self) {
    return Notify(self, [&]() { cond_.notify_all(); });
  }

 private:
  bool IsOwner(art::Thread* self) const {
    // There's a subtle correctness argument here for a relaxed load outside the critical section.
    // A thread is guaranteed to see either its own latest store or another thread's store. If a
    // thread sees another thread's store than it cannot be holding the lock.
    art::Thread* owner_thread = owner_.load(std::memory_order_relaxed);
    return self == owner_thread;
  }

  template <typename T>
  bool Wait(art::Thread* self, T how_to_wait) {
    if (!IsOwner(self)) {
      return false;
    }

    size_t old_count = count_;

    count_ = 0;
    owner_.store(nullptr, std::memory_order_relaxed);

    {
      std::unique_lock<std::mutex> lk(mutex_, std::adopt_lock);
      how_to_wait(lk);
      lk.release();  // Do not unlock the mutex.
    }

    DCHECK(owner_.load(std::memory_order_relaxed) == nullptr);
    owner_.store(self, std::memory_order_relaxed);
    DCHECK_EQ(0u, count_);
    count_ = old_count;

    return true;
  }

  template <typename T>
  bool Notify(art::Thread* self, T how_to_notify) {
    if (!IsOwner(self)) {
      return false;
    }

    how_to_notify();

    return true;
  }

  std::mutex mutex_;
  std::condition_variable cond_;
  std::atomic<art::Thread*> owner_;
  size_t count_;
};

static jrawMonitorID EncodeMonitor(JvmtiMonitor* monitor) {
  return reinterpret_cast<jrawMonitorID>(monitor);
}

static JvmtiMonitor* DecodeMonitor(jrawMonitorID id) {
  return reinterpret_cast<JvmtiMonitor*>(id);
}

jvmtiError MonitorUtil::CreateRawMonitor(jvmtiEnv* env ATTRIBUTE_UNUSED,
                                         const char* name,
                                         jrawMonitorID* monitor_ptr) {
  if (name == nullptr || monitor_ptr == nullptr) {
    return ERR(NULL_POINTER);
  }

  JvmtiMonitor* monitor = new JvmtiMonitor();
  *monitor_ptr = EncodeMonitor(monitor);

  return ERR(NONE);
}

jvmtiError MonitorUtil::DestroyRawMonitor(jvmtiEnv* env ATTRIBUTE_UNUSED, jrawMonitorID id) {
  if (id == nullptr) {
    return ERR(INVALID_MONITOR);
  }

  JvmtiMonitor* monitor = DecodeMonitor(id);
  art::Thread* self = art::Thread::Current();

  if (!JvmtiMonitor::Destroy(self, monitor)) {
    return ERR(NOT_MONITOR_OWNER);
  }

  return ERR(NONE);
}

jvmtiError MonitorUtil::RawMonitorEnter(jvmtiEnv* env ATTRIBUTE_UNUSED, jrawMonitorID id) {
  if (id == nullptr) {
    return ERR(INVALID_MONITOR);
  }

  JvmtiMonitor* monitor = DecodeMonitor(id);
  art::Thread* self = art::Thread::Current();

  monitor->MonitorEnter(self);

  return ERR(NONE);
}

jvmtiError MonitorUtil::RawMonitorExit(jvmtiEnv* env ATTRIBUTE_UNUSED, jrawMonitorID id) {
  if (id == nullptr) {
    return ERR(INVALID_MONITOR);
  }

  JvmtiMonitor* monitor = DecodeMonitor(id);
  art::Thread* self = art::Thread::Current();

  if (!monitor->MonitorExit(self)) {
    return ERR(NOT_MONITOR_OWNER);
  }

  return ERR(NONE);
}

jvmtiError MonitorUtil::RawMonitorWait(jvmtiEnv* env ATTRIBUTE_UNUSED,
                                       jrawMonitorID id,
                                       jlong millis) {
  if (id == nullptr) {
    return ERR(INVALID_MONITOR);
  }

  JvmtiMonitor* monitor = DecodeMonitor(id);
  art::Thread* self = art::Thread::Current();

  // What millis < 0 means is not defined in the spec. Real world agents seem to assume that it is a
  // valid call though. We treat it as though it was 0 and wait indefinitely.
  bool result = (millis > 0)
      ? monitor->Wait(self, static_cast<uint64_t>(millis))
      : monitor->Wait(self);

  if (!result) {
    return ERR(NOT_MONITOR_OWNER);
  }

  // TODO: Make sure that is really what we should be checking here.
  if (self->IsInterrupted()) {
    return ERR(INTERRUPT);
  }

  return ERR(NONE);
}

jvmtiError MonitorUtil::RawMonitorNotify(jvmtiEnv* env ATTRIBUTE_UNUSED, jrawMonitorID id) {
  if (id == nullptr) {
    return ERR(INVALID_MONITOR);
  }

  JvmtiMonitor* monitor = DecodeMonitor(id);
  art::Thread* self = art::Thread::Current();

  if (!monitor->Notify(self)) {
    return ERR(NOT_MONITOR_OWNER);
  }

  return ERR(NONE);
}

jvmtiError MonitorUtil::RawMonitorNotifyAll(jvmtiEnv* env ATTRIBUTE_UNUSED, jrawMonitorID id) {
  if (id == nullptr) {
    return ERR(INVALID_MONITOR);
  }

  JvmtiMonitor* monitor = DecodeMonitor(id);
  art::Thread* self = art::Thread::Current();

  if (!monitor->NotifyAll(self)) {
    return ERR(NOT_MONITOR_OWNER);
  }

  return ERR(NONE);
}

jvmtiError MonitorUtil::GetCurrentContendedMonitor(jvmtiEnv* env ATTRIBUTE_UNUSED,
                                                   jthread thread,
                                                   jobject* monitor) {
  if (monitor == nullptr) {
    return ERR(NULL_POINTER);
  }
  art::Thread* self = art::Thread::Current();
  art::ScopedObjectAccess soa(self);
  art::Locks::thread_list_lock_->ExclusiveLock(self);
  art::Thread* target = nullptr;
  jvmtiError err = ERR(INTERNAL);
  if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) {
    art::Locks::thread_list_lock_->ExclusiveUnlock(self);
    return err;
  }
  struct GetContendedMonitorClosure : public art::Closure {
   public:
    explicit GetContendedMonitorClosure(art::Thread* current, jobject* out)
        : result_thread_(current), out_(out) {}

    void Run(art::Thread* target_thread) REQUIRES_SHARED(art::Locks::mutator_lock_) {
      switch (target_thread->GetState()) {
        // These three we are actually currently waiting on a monitor and have sent the appropriate
        // events (if anyone is listening).
        case art::kBlocked:
        case art::kTimedWaiting:
        case art::kWaiting: {
          art::mirror::Object* mon = art::Monitor::GetContendedMonitor(target_thread);
          *out_ = (mon == nullptr) ? nullptr
                                   : result_thread_->GetJniEnv()->AddLocalReference<jobject>(mon);
          return;
        }
        case art::kTerminated:
        case art::kRunnable:
        case art::kSleeping:
        case art::kWaitingForLockInflation:
        case art::kWaitingForTaskProcessor:
        case art::kWaitingForGcToComplete:
        case art::kWaitingForCheckPointsToRun:
        case art::kWaitingPerformingGc:
        case art::kWaitingForDebuggerSend:
        case art::kWaitingForDebuggerToAttach:
        case art::kWaitingInMainDebuggerLoop:
        case art::kWaitingForDebuggerSuspension:
        case art::kWaitingForJniOnLoad:
        case art::kWaitingForSignalCatcherOutput:
        case art::kWaitingInMainSignalCatcherLoop:
        case art::kWaitingForDeoptimization:
        case art::kWaitingForMethodTracingStart:
        case art::kWaitingForVisitObjects:
        case art::kWaitingForGetObjectsAllocated:
        case art::kWaitingWeakGcRootRead:
        case art::kWaitingForGcThreadFlip:
        case art::kStarting:
        case art::kNative:
        case art::kSuspended: {
          // We aren't currently (explicitly) waiting for a monitor anything so just return null.
          *out_ = nullptr;
          return;
        }
      }
    }

   private:
    art::Thread* result_thread_;
    jobject* out_;
  };
  GetContendedMonitorClosure closure(self, monitor);
  // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution.
  if (!ThreadUtil::RequestGCSafeSynchronousCheckpoint(target, &closure)) {
    return ERR(THREAD_NOT_ALIVE);
  }
  return OK;
}

}  // namespace openjdkjvmti
