/*
 * Copyright (c) 2021, 2025, 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 "gc/shared/barrierSet.hpp"
#include "gc/shared/gcId.hpp"
#include "jvm_io.h"
#include "runtime/atomic.hpp"
#include "runtime/javaThread.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/nonJavaThread.hpp"
#include "runtime/osThread.hpp"
#include "runtime/task.hpp"
#include "sanitizers/leak.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/singleWriterSynchronizer.hpp"
#include "utilities/vmError.hpp"
#if INCLUDE_JFR
#include "jfr/jfr.hpp"
#endif

// List of all NonJavaThreads and safe iteration over that list.

class NonJavaThread::List {
public:
  NonJavaThread* volatile _head;
  SingleWriterSynchronizer _protect;

  List() : _head(nullptr), _protect() {}
};

NonJavaThread::List NonJavaThread::_the_list;

NonJavaThread::Iterator::Iterator() :
  _protect_enter(_the_list._protect.enter()),
  _current(Atomic::load_acquire(&_the_list._head))
{}

NonJavaThread::Iterator::~Iterator() {
  _the_list._protect.exit(_protect_enter);
}

void NonJavaThread::Iterator::step() {
  assert(!end(), "precondition");
  _current = Atomic::load_acquire(&_current->_next);
}

NonJavaThread::NonJavaThread() : Thread(), _next(nullptr) {
  assert(BarrierSet::barrier_set() != nullptr, "NonJavaThread created too soon!");
}

NonJavaThread::~NonJavaThread() { }

void NonJavaThread::add_to_the_list() {
  MutexLocker ml(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag);
  // Initialize BarrierSet-related data before adding to list.
  BarrierSet::barrier_set()->on_thread_attach(this);
  Atomic::release_store(&_next, _the_list._head);
  Atomic::release_store(&_the_list._head, this);
}

void NonJavaThread::remove_from_the_list() {
  {
    MutexLocker ml(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag);
    // Cleanup BarrierSet-related data before removing from list.
    BarrierSet::barrier_set()->on_thread_detach(this);
    NonJavaThread* volatile* p = &_the_list._head;
    for (NonJavaThread* t = *p; t != nullptr; p = &t->_next, t = *p) {
      if (t == this) {
        *p = _next;
        break;
      }
    }
  }
  // Wait for any in-progress iterators.  Concurrent synchronize is not
  // allowed, so do it while holding a dedicated lock.  Outside and distinct
  // from NJTList_lock in case an iteration attempts to lock it.
  MutexLocker ml(NonJavaThreadsListSync_lock, Mutex::_no_safepoint_check_flag);
  _the_list._protect.synchronize();
  _next = nullptr;                 // Safe to drop the link now.
}

void NonJavaThread::pre_run() {
  add_to_the_list();

  // This is slightly odd in that NamedThread is a subclass, but
  // in fact name() is defined in Thread
  assert(this->name() != nullptr, "thread name was not set before it was started");
  this->set_native_thread_name(this->name());
}

void NonJavaThread::post_run() {
  JFR_ONLY(Jfr::on_thread_exit(this);)
  remove_from_the_list();
  unregister_thread_stack_with_NMT();
  // Ensure thread-local-storage is cleared before termination.
  Thread::clear_thread_current();
  osthread()->set_state(ZOMBIE);
}

// NamedThread --  non-JavaThread subclasses with multiple
// uniquely named instances should derive from this.
NamedThread::NamedThread() :
  NonJavaThread(),
  _name(nullptr),
  _processed_thread(nullptr),
  _gc_id(GCId::undefined())
{}

NamedThread::~NamedThread() {
  FREE_C_HEAP_ARRAY(char, _name);
}

void NamedThread::set_name(const char* format, ...) {
  guarantee(_name == nullptr, "Only get to set name once.");
  _name = NEW_C_HEAP_ARRAY(char, max_name_len, mtThread);
  va_list ap;
  va_start(ap, format);
  jio_vsnprintf(_name, max_name_len, format, ap);
  va_end(ap);
}

void NamedThread::print_on(outputStream* st) const {
  st->print("\"%s\" ", name());
  Thread::print_on(st);
  st->cr();
}


// ======= WatcherThread ========

// The watcher thread exists to simulate timer interrupts.  It should
// be replaced by an abstraction over whatever native support for
// timer interrupts exists on the platform.

WatcherThread* WatcherThread::_watcher_thread   = nullptr;
bool WatcherThread::_run_all_tasks = false;
volatile bool  WatcherThread::_should_terminate = false;

WatcherThread::WatcherThread() : NonJavaThread() {
  assert(watcher_thread() == nullptr, "we can only allocate one WatcherThread");
  if (os::create_thread(this, os::watcher_thread)) {
    _watcher_thread = this;

    // Set the watcher thread to the highest OS priority which should not be
    // used, unless a Java thread with priority java.lang.Thread.MAX_PRIORITY
    // is created. The only normal thread using this priority is the reference
    // handler thread, which runs for very short intervals only.
    // If the VMThread's priority is not lower than the WatcherThread profiling
    // will be inaccurate.
    os::set_priority(this, MaxPriority);
    os::start_thread(this);
  }
}

int WatcherThread::sleep() const {
  // The WatcherThread does not participate in the safepoint protocol
  // for the PeriodicTask_lock because it is not a JavaThread.
  MonitorLocker ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag);

  if (_should_terminate) {
    // check for termination before we do any housekeeping or wait
    return 0;  // we did not sleep.
  }

  if (!_run_all_tasks) {
    ml.wait(100);
    return 0;
  }

  // remaining will be zero if there are no tasks,
  // causing the WatcherThread to sleep until a task is
  // enrolled
  int remaining = PeriodicTask::time_to_wait();
  int time_slept = 0;

  // we expect this to timeout - we only ever get unparked when
  // we should terminate or when a new task has been enrolled
  OSThreadWaitState osts(this->osthread(), false /* not Object.wait() */);

  jlong time_before_loop = os::javaTimeNanos();

  while (true) {
    bool timedout = ml.wait(remaining);
    jlong now = os::javaTimeNanos();

    if (remaining == 0) {
      // if we didn't have any tasks we could have waited for a long time
      // consider the time_slept zero and reset time_before_loop
      time_slept = 0;
      time_before_loop = now;
    } else {
      // need to recalculate since we might have new tasks in _tasks
      time_slept = (int) ((now - time_before_loop) / 1000000);
    }

    // Change to task list or spurious wakeup of some kind
    if (timedout || _should_terminate) {
      break;
    }

    remaining = PeriodicTask::time_to_wait();
    if (remaining == 0) {
      // Last task was just disenrolled so loop around and wait until
      // another task gets enrolled
      continue;
    }

    remaining -= time_slept;
    if (remaining <= 0) {
      break;
    }
  }

  return time_slept;
}

void WatcherThread::run() {
  assert(this == watcher_thread(), "just checking");

  while (true) {
    assert(watcher_thread() == Thread::current(), "thread consistency check");
    assert(watcher_thread() == this, "thread consistency check");

    // Calculate how long it'll be until the next PeriodicTask work
    // should be done, and sleep that amount of time.
    int time_waited = sleep();

    if (VMError::is_error_reported()) {
      // A fatal error has happened, the error handler(VMError::report_and_die)
      // should abort JVM after creating an error log file. However in some
      // rare cases, the error handler itself might deadlock. Here periodically
      // check for error reporting timeouts, and if it happens, just proceed to
      // abort the VM.

      // This code is in WatcherThread because WatcherThread wakes up
      // periodically so the fatal error handler doesn't need to do anything;
      // also because the WatcherThread is less likely to crash than other
      // threads.

      for (;;) {
        // Note: we use naked sleep in this loop because we want to avoid using
        // any kind of VM infrastructure which may be broken at this point.
        if (VMError::check_timeout()) {
          // We hit error reporting timeout. Error reporting was interrupted and
          // will be wrapping things up now (closing files etc). Give it some more
          // time, then quit the VM.
          os::naked_short_sleep(200);
          // Print a message to stderr.
          fdStream err(defaultStream::output_fd());
          err.print_raw_cr("# [ timer expired, abort... ]");
          // skip atexit/vm_exit/vm_abort hooks
          os::die();
        }

        // Wait a bit, then recheck for timeout.
        os::naked_short_sleep(250);
      }
    }

    if (_should_terminate) {
      // check for termination before posting the next tick
      break;
    }

    // Don't process enrolled tasks until VM is fully initialized.
    if (_run_all_tasks) {
      PeriodicTask::real_time_tick(time_waited);
    }
  }

  // Signal that it is terminated
  {
    MutexLocker mu(Terminator_lock, Mutex::_no_safepoint_check_flag);
    LSAN_IGNORE_OBJECT(_watcher_thread);
    _watcher_thread = nullptr;
    Terminator_lock->notify_all();
  }
}

void WatcherThread::start() {
  MonitorLocker ml(PeriodicTask_lock);
  _should_terminate = false;
  // Create the single instance of WatcherThread
  new WatcherThread();
}

void WatcherThread::run_all_tasks() {
  MonitorLocker ml(PeriodicTask_lock);
  _run_all_tasks = true;
  ml.notify();
}

void WatcherThread::stop() {
  {
    // Follow normal safepoint aware lock enter protocol since the
    // WatcherThread is stopped by another JavaThread.
    MutexLocker ml(PeriodicTask_lock);
    _should_terminate = true;

    WatcherThread* watcher = watcher_thread();
    if (watcher != nullptr) {
      // unpark the WatcherThread so it can see that it should terminate
      watcher->unpark();
    }
  }

  MonitorLocker mu(Terminator_lock);

  while (watcher_thread() != nullptr) {
    // This wait should make safepoint checks and wait without a timeout.
    mu.wait(0);
  }
}

void WatcherThread::unpark() {
  assert(PeriodicTask_lock->owned_by_self(), "PeriodicTask_lock required");
  PeriodicTask_lock->notify();
}

void WatcherThread::print_on(outputStream* st) const {
  st->print("\"%s\" ", name());
  Thread::print_on(st);
  st->cr();
}

