/*
 * Copyright (c) 2015, 2023, 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.
 *
 * 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 "precompiled.hpp"
#include "gc/g1/g1ServiceThread.hpp"
#include "logging/log.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/timer.hpp"
#include "runtime/os.hpp"

G1SentinelTask::G1SentinelTask() : G1ServiceTask("Sentinel Task") {
  set_time(max_jlong);
  set_next(this);
}

void G1SentinelTask::execute() {
  guarantee(false, "Sentinel service task should never be executed.");
}

G1ServiceThread::G1ServiceThread() :
    ConcurrentGCThread(),
    _monitor(Mutex::nosafepoint, "G1ServiceThread_lock"),
    _task_queue() {
  set_name("G1 Service");
  create_and_start();
}

void G1ServiceThread::register_task(G1ServiceTask* task, jlong delay_ms) {
  guarantee(!task->is_registered(), "Task already registered");
  guarantee(task->next() == nullptr, "Task already in queue");

  // Make sure the service thread is still up and running, there is a race
  // during shutdown where the service thread has been stopped, but other
  // GC threads might still be running and trying to add tasks.
  if (has_terminated()) {
    log_debug(gc, task)("G1 Service Thread (%s) (terminated)", task->name());
    return;
  }

  log_debug(gc, task)("G1 Service Thread (%s) (register)", task->name());

  // Associate the task with the service thread.
  task->set_service_thread(this);

  // Schedule the task to run after the given delay. The service will be
  // notified to check if this task is first in the queue.
  schedule_task(task, delay_ms);
}

void G1ServiceThread::schedule(G1ServiceTask* task, jlong delay_ms, bool notify) {
  guarantee(task->is_registered(), "Must be registered before scheduled");
  guarantee(task->next() == nullptr, "Task already in queue");

  // Schedule task by setting the task time and adding it to queue.
  jlong delay = TimeHelper::millis_to_counter(delay_ms);
  task->set_time(os::elapsed_counter() + delay);

  MonitorLocker ml(&_monitor, Mutex::_no_safepoint_check_flag);
  _task_queue.add_ordered(task);
  if (notify) {
    ml.notify();
  }

  log_trace(gc, task)("G1 Service Thread (%s) (schedule) @%1.3fs",
                      task->name(), TimeHelper::counter_to_seconds(task->time()));
}

void G1ServiceThread::schedule_task(G1ServiceTask* task, jlong delay_ms) {
  schedule(task, delay_ms, true /* notify */);
}

G1ServiceTask* G1ServiceThread::wait_for_task() {
  MonitorLocker ml(&_monitor, Mutex::_no_safepoint_check_flag);
  while (!should_terminate()) {
    if (_task_queue.is_empty()) {
      log_trace(gc, task)("G1 Service Thread (wait for new tasks)");
      ml.wait();
    } else {
      G1ServiceTask* task = _task_queue.front();
      jlong scheduled = task->time();
      jlong now = os::elapsed_counter();
      if (scheduled <= now) {
        _task_queue.remove_front();
        return task;
      } else {
        // Round up to try not to wake up early, and to avoid round down to
        // zero (which has special meaning of wait forever) by conversion.
        double delay = ceil(TimeHelper::counter_to_millis(scheduled - now));
        log_trace(gc, task)("G1 Service Thread (wait %1.3fs)", (delay / 1000.0));
        int64_t delay_ms = static_cast<int64_t>(delay);
        assert(delay_ms > 0, "invariant");
        ml.wait(delay_ms);
      }
    }
  }
  return nullptr;               // Return null when terminating.
}

void G1ServiceThread::run_task(G1ServiceTask* task) {
  jlong start = os::elapsed_counter();
  double vstart = os::elapsedVTime();

  assert(task->time() <= start,
         "task run early: " JLONG_FORMAT " > " JLONG_FORMAT,
         task->time(), start);
  log_debug(gc, task, start)("G1 Service Thread (%s) (run %1.3fms after schedule)",
                             task->name(),
                             TimeHelper::counter_to_millis(start - task->time()));

  task->execute();

  log_debug(gc, task)("G1 Service Thread (%s) (run: %1.3fms) (cpu: %1.3fms)",
                      task->name(),
                      TimeHelper::counter_to_millis(os::elapsed_counter() - start),
                      (os::elapsedVTime() - vstart) * MILLIUNITS);
}

void G1ServiceThread::run_service() {
  while (true) {
    G1ServiceTask* task = wait_for_task();
    if (task == nullptr) break;
    run_task(task);
  }
  assert(should_terminate(), "invariant");
  log_debug(gc, task)("G1 Service Thread (stopping)");
}

void G1ServiceThread::stop_service() {
  MonitorLocker ml(&_monitor, Mutex::_no_safepoint_check_flag);
  ml.notify();
}

G1ServiceTask::G1ServiceTask(const char* name) :
  _time(),
  _name(name),
  _next(nullptr),
  _service_thread(nullptr) { }

void G1ServiceTask::set_service_thread(G1ServiceThread* thread) {
  _service_thread = thread;
}

bool G1ServiceTask::is_registered() {
  return _service_thread != nullptr;
}

void G1ServiceTask::schedule(jlong delay_ms) {
  assert(Thread::current() == _service_thread,
         "Can only be used when already running on the service thread");
  // No need to notify, since we *are* the service thread.
  _service_thread->schedule(this, delay_ms, false /* notify */);
}

const char* G1ServiceTask::name() {
  return _name;
}

void G1ServiceTask::set_time(jlong time) {
  assert(_next == nullptr, "Not allowed to update time while in queue");
  _time = time;
}

jlong G1ServiceTask::time() {
  return _time;
}

void G1ServiceTask::set_next(G1ServiceTask* next) {
  _next = next;
}

G1ServiceTask* G1ServiceTask::next() {
  return _next;
}

G1ServiceTaskQueue::G1ServiceTaskQueue() : _sentinel() { }

void G1ServiceTaskQueue::remove_front() {
  verify_task_queue();

  G1ServiceTask* task = _sentinel.next();
  _sentinel.set_next(task->next());
  task->set_next(nullptr);
}

G1ServiceTask* G1ServiceTaskQueue::front() {
  verify_task_queue();
  return _sentinel.next();
}

bool G1ServiceTaskQueue::is_empty() {
  return &_sentinel == _sentinel.next();
}

void G1ServiceTaskQueue::add_ordered(G1ServiceTask* task) {
  assert(task != nullptr, "not a valid task");
  assert(task->next() == nullptr, "invariant");
  assert(task->time() != max_jlong, "invalid time for task");

  G1ServiceTask* current = &_sentinel;
  while (task->time() >= current->next()->time()) {
    assert(task != current, "Task should only be added once.");
    current = current->next();
  }

  // Update the links.
  task->set_next(current->next());
  current->set_next(task);

  verify_task_queue();
}

#ifdef ASSERT
void G1ServiceTaskQueue::verify_task_queue() {
  G1ServiceTask* cur = _sentinel.next();

  assert(cur != &_sentinel, "Should never try to verify empty queue");
  while (cur != &_sentinel) {
    G1ServiceTask* next = cur->next();
    assert(cur->time() <= next->time(),
           "Tasks out of order, prev: %s (%1.3fs), next: %s (%1.3fs)",
           cur->name(), TimeHelper::counter_to_seconds(cur->time()), next->name(), TimeHelper::counter_to_seconds(next->time()));

    assert(cur != next, "Invariant");
    cur = next;
  }
}
#endif
