/* 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>                                       // NOLINT [build/c++11] [5]
#include <condition_variable>                           // NOLINT [build/c++11] [5]
#include <mutex>                                        // NOLINT [build/c++11] [5]

#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
