// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/heap/safepoint.h"

#include "vm/heap/heap.h"
#include "vm/thread.h"
#include "vm/thread_barrier.h"
#include "vm/thread_registry.h"

namespace dart {

DEFINE_FLAG(bool, trace_safepoint, false, "Trace Safepoint logic.");

SafepointOperationScope::SafepointOperationScope(Thread* T,
                                                 SafepointLevel level)
    : ThreadStackResource(T), level_(level) {
  ASSERT(T != nullptr && T->isolate_group() != nullptr);

  auto handler = T->isolate_group()->safepoint_handler();
  handler->SafepointThreads(T, level_);
}

SafepointOperationScope::~SafepointOperationScope() {
  Thread* T = thread();
  ASSERT(T != nullptr && T->isolate_group() != nullptr);

  auto handler = T->isolate_group()->safepoint_handler();
  handler->ResumeThreads(T, level_);
}

ForceGrowthSafepointOperationScope::ForceGrowthSafepointOperationScope(
    Thread* T,
    SafepointLevel level)
    : ThreadStackResource(T), level_(level) {
  ASSERT(T != nullptr);
  IsolateGroup* IG = T->isolate_group();
  ASSERT(IG != nullptr);

  T->IncrementForceGrowthScopeDepth();

  auto handler = IG->safepoint_handler();
  handler->SafepointThreads(T, level_);
}

ForceGrowthSafepointOperationScope::~ForceGrowthSafepointOperationScope() {
  Thread* T = thread();
  ASSERT(T != nullptr);
  IsolateGroup* IG = T->isolate_group();
  ASSERT(IG != nullptr);

  auto handler = IG->safepoint_handler();
  handler->ResumeThreads(T, level_);

  T->DecrementForceGrowthScopeDepth();
  if (!T->force_growth()) {
    // Check if we passed the growth limit during the scope.
    T->heap()->CheckCatchUp(T);
  }
}

SafepointHandler::SafepointHandler(IsolateGroup* isolate_group)
    : isolate_group_(isolate_group), tasks_() {
  handlers_[SafepointLevel::kGC] =
      new LevelHandler(isolate_group, SafepointLevel::kGC);
  handlers_[SafepointLevel::kGCAndDeopt] =
      new LevelHandler(isolate_group, SafepointLevel::kGCAndDeopt);
  handlers_[SafepointLevel::kGCAndDeoptAndReload] =
      new LevelHandler(isolate_group, SafepointLevel::kGCAndDeoptAndReload);
}

SafepointHandler::~SafepointHandler() {
  ASSERT(tasks_.IsEmpty());
  for (intptr_t level = 0; level < SafepointLevel::kNumLevels; ++level) {
    ASSERT(handlers_[level]->owner_ == nullptr);
    delete handlers_[level];
  }
}

void SafepointHandler::SafepointThreads(Thread* T, SafepointLevel level) {
  ASSERT(T->no_safepoint_scope_depth() == 0);
  ASSERT(T->execution_state() == Thread::kThreadInVM);
  ASSERT(T->current_safepoint_level() >= level);

  MallocGrowableArray<Dart_Port> oob_isolates;
  {
    MonitorLocker tl(threads_lock());

    // Allow recursive deopt safepoint operation.
    if (handlers_[level]->owner_ == T) {
      // If we own this safepoint level already we have to own the lower levels
      // as well.
      AssertWeOwnLowerLevelSafepoints(T, level);

      for (intptr_t i = 0; i <= level; ++i) {
        handlers_[i]->operation_count_++;
      }
      return;
    }

    // This level of nesting is not allowed (this thread cannot own lower levels
    // and then later try acquire higher levels).
    AssertWeDoNotOwnLowerLevelSafepoints(T, level);

    // Mark this thread at safepoint and possibly notify waiting threads.
    {
      MonitorLocker tl(T->thread_lock());
      // We only enter [level] here. That means a higher level that is waiting
      // for us to check-in will not consider us as not parked. This is required
      // since we are not actually parked (we can finish running this method and
      // then caller continues).
      EnterSafepointLocked(T, &tl, level);
    }

    // Wait until other safepoint operations are done & mark us as owning
    // the safepoint - so no other thread can.
    while (handlers_[level]->SafepointInProgress()) {
      tl.Wait();
    }
    handlers_[level]->SetSafepointInProgress(T);

    // Ensure a thread is at a safepoint or notify it to get to one.
    handlers_[level]->NotifyThreadsToGetToSafepointLevel(T, &oob_isolates);
  }

  for (auto main_port : oob_isolates) {
    Isolate::SendInternalLibMessage(main_port, Isolate::kCheckForReload,
                                    /*capability=*/-1);
  }

  // Now wait for all threads that are not already at a safepoint to check-in.
  handlers_[level]->WaitUntilThreadsReachedSafepointLevel();

  // No other mutator is running at this point. We'll set ourselves as owners of
  // all the lower levels as well - since higher levels provide even more
  // guarantees that lower levels (e.g. others being stopped at places where
  // one can deopt also implies one can gc)
  AcquireLowerLevelSafepoints(T, level);

  // The current thread owns the safepoint, but it will continue to run and as
  // such is not at any "point" that can be considered safe.
  {
    MonitorLocker tl(T->thread_lock());
    ExitSafepointLocked(T, &tl, level);
  }
}

void SafepointHandler::AssertWeOwnLowerLevelSafepoints(Thread* T,
                                                       SafepointLevel level) {
  for (intptr_t lower_level = level - 1; lower_level >= 0; --lower_level) {
    RELEASE_ASSERT(handlers_[lower_level]->owner_ == T);
  }
}

void SafepointHandler::AssertWeDoNotOwnLowerLevelSafepoints(
    Thread* T,
    SafepointLevel level) {
  for (intptr_t lower_level = level - 1; lower_level >= 0; --lower_level) {
    RELEASE_ASSERT(handlers_[lower_level]->owner_ != T);
  }
}

void SafepointHandler::LevelHandler::NotifyThreadsToGetToSafepointLevel(
    Thread* T,
    MallocGrowableArray<Dart_Port>* oob_isolates) {
  ASSERT(num_threads_not_parked_ == 0);
  for (auto current = isolate_group()->thread_registry()->active_list();
       current != nullptr; current = current->next()) {
    MonitorLocker tl(current->thread_lock());
    if (!current->BypassSafepoints() && current != T) {
      const uint32_t state = current->SetSafepointRequested(level_, true);
      if (!Thread::IsAtSafepoint(level_, state)) {
        if (level_ == SafepointLevel::kGCAndDeoptAndReload) {
          // Interrupt the mutator by sending an reload OOB message. The
          // mutator will only check-in once it's handling the reload OOB
          // message.
          //
          // If there's no isolate, it may be a helper thread that has entered
          // via `Thread::EnterIsolateGroupAsHelper()`. In that case we cannot
          // send an OOB message. Instead we'll have to wait until that thread
          // de-schedules itself.
          auto isolate = current->scheduled_dart_mutator_isolate();
          if (isolate != nullptr) {
            oob_isolates->Add(isolate->main_port());
          }
        } else {
          // Interrupt the mutator and ask it to block at any interruption
          // point.
          if (current->IsDartMutatorThread()) {
            current->ScheduleInterrupts(Thread::kVMInterrupt);
          }
        }
        MonitorLocker sl(&parked_lock_);
        num_threads_not_parked_++;
      }
    }
  }
}

void SafepointHandler::ResumeThreads(Thread* T, SafepointLevel level) {
  {
    MonitorLocker sl(threads_lock());

    ASSERT(handlers_[level]->SafepointInProgress());
    ASSERT(handlers_[level]->owner_ == T);
    AssertWeOwnLowerLevelSafepoints(T, level);

    // We allow recursive safepoints.
    if (handlers_[level]->operation_count_ > 1) {
      for (intptr_t i = 0; i <= level; ++i) {
        handlers_[i]->operation_count_--;
      }
      return;
    }

    ReleaseLowerLevelSafepoints(T, level);
    handlers_[level]->ResetSafepointInProgress(T);
    handlers_[level]->NotifyThreadsToContinue(T);
    sl.NotifyAll();
  }
}

void SafepointHandler::LevelHandler::WaitUntilThreadsReachedSafepointLevel() {
  MonitorLocker sl(&parked_lock_);
  intptr_t num_attempts = 0;
  while (num_threads_not_parked_ > 0) {
    Monitor::WaitResult retval = sl.Wait(1000);
    if (retval == Monitor::kTimedOut) {
      num_attempts += 1;
      if (FLAG_trace_safepoint && num_attempts > 10) {
        for (auto current = isolate_group()->thread_registry()->active_list();
             current != nullptr; current = current->next()) {
          if (!current->IsAtSafepoint(level_)) {
            OS::PrintErr("Attempt:%" Pd " waiting for thread %s to check in\n",
                         num_attempts, current->os_thread()->name());
          }
        }
      }
    }
  }
}

void SafepointHandler::AcquireLowerLevelSafepoints(Thread* T,
                                                   SafepointLevel level) {
  MonitorLocker tl(threads_lock());
  ASSERT(handlers_[level]->owner_ == T);
  for (intptr_t lower_level = level - 1; lower_level >= 0; --lower_level) {
    ASSERT(!handlers_[lower_level]->SafepointInProgress());
    handlers_[lower_level]->SetSafepointInProgress(T);
    ASSERT(handlers_[lower_level]->owner_ == T);
  }
}

void SafepointHandler::ReleaseLowerLevelSafepoints(Thread* T,
                                                   SafepointLevel level) {
  for (intptr_t lower_level = 0; lower_level < level; ++lower_level) {
    handlers_[lower_level]->ResetSafepointInProgress(T);
  }
}

void SafepointHandler::LevelHandler::NotifyThreadsToContinue(Thread* T) {
  for (auto current = isolate_group()->thread_registry()->active_list();
       current != nullptr; current = current->next()) {
    MonitorLocker tl(current->thread_lock());
    if (!current->BypassSafepoints() && current != T) {
      bool resume = false;
      for (intptr_t lower_level = level_; lower_level >= 0; --lower_level) {
        if (Thread::IsBlockedForSafepoint(current->SetSafepointRequested(
                static_cast<SafepointLevel>(lower_level), false))) {
          resume = true;
        }
      }
      if (resume) {
        tl.Notify();
      }
    }
  }
}

void SafepointHandler::EnterSafepointUsingLock(Thread* T) {
  MonitorLocker tl(T->thread_lock());
  EnterSafepointLocked(T, &tl, T->current_safepoint_level());
}

void SafepointHandler::ExitSafepointUsingLock(Thread* T) {
  MonitorLocker tl(T->thread_lock());
  ASSERT(T->IsAtSafepoint());
  ExitSafepointLocked(T, &tl, T->current_safepoint_level());
  ASSERT(!T->IsSafepointRequestedLocked(T->current_safepoint_level()));
}

SafepointLevel SafepointHandler::InnermostSafepointOperation(
    const Thread* current_thread) const {
  // The [current_thread] may not own the active safepoint.
  intptr_t last_count = -1;
  SafepointLevel last_level = SafepointLevel::kNoSafepoint;

  // Notice: We access SafepointLevel::{owner_,operation_count_} fields
  // without lock. This is ok since:
  //
  //   * If the current thread is the owner, then it will be the one that has
  //     last written `Thread::Current()` to the `owner_` field (as well as
  //     updated the `operation_count_`) - nobody else can update those fields
  //     in the meantime. Once the current thread exits we set it to `nullptr`.
  //
  //   * If there's no owner or another thread is the owner the value cannot be
  //     `Thread::Current()`: only our thread can write that particular value.
  //
  //   => Even if there's racy writes by another thread, the logic is still
  //      safe.
  //
  for (intptr_t level = 0; level < SafepointLevel::kNumLevels; ++level) {
    if (handlers_[level]->owner_ == current_thread) {
      const intptr_t count = handlers_[level]->operation_count_;
      if (count < last_count) return last_level;
      last_count = count;
      last_level = static_cast<SafepointLevel>(level);
    } else {
      return last_level;
    }
  }
  return last_level;
}

void SafepointHandler::BlockForSafepoint(Thread* T) {
  ASSERT(!T->BypassSafepoints());
  MonitorLocker tl(T->thread_lock());
  // This takes into account the safepoint level the thread can participate in.
  const SafepointLevel level = T->current_safepoint_level();
  if (T->IsSafepointRequestedLocked(level)) {
    EnterSafepointLocked(T, &tl, level);
    ExitSafepointLocked(T, &tl, level);
    ASSERT(!T->IsSafepointRequestedLocked(level));
  }
}

void SafepointHandler::EnterSafepointLocked(Thread* T,
                                            MonitorLocker* tl,
                                            SafepointLevel level) {
  T->SetAtSafepoint(true, level);
  // Several safepointing operations (at different) levels may happen at same
  // time. Ensure we notify all of them that we are parked now.
  for (intptr_t i = 0; i <= level; ++i) {
    if (T->IsSafepointLevelRequestedLocked(static_cast<SafepointLevel>(i))) {
      handlers_[i]->NotifyWeAreParked(T);
    }
  }
}

void SafepointHandler::LevelHandler::NotifyWeAreParked(Thread* T) {
  ASSERT(owner_ != nullptr);
  MonitorLocker sl(&parked_lock_);
  ASSERT(num_threads_not_parked_ > 0);
  num_threads_not_parked_ -= 1;
  if (num_threads_not_parked_ == 0) {
    sl.Notify();
  }
}

void SafepointHandler::ExitSafepointLocked(Thread* T,
                                           MonitorLocker* tl,
                                           SafepointLevel level) {
  ASSERT(T == Thread::Current());
  while (T->IsSafepointRequestedLocked(level)) {
    T->SetBlockedForSafepoint(true);
    tl->Wait();
    T->SetBlockedForSafepoint(false);

    MonitorLeaveScope mls(tl);
    SafepointTask* task = nullptr;
    {
      MonitorLocker ml(threads_lock());
      if (!tasks_.IsEmpty()) {
        task = tasks_.RemoveFirst();
      }
    }
    if (task != nullptr) {
      Thread::ExecutionState execution_state = T->execution_state();
      T->set_execution_state(Thread::kThreadInVM);
      task->RunBlockedAtSafepoint();
      delete task;
      T->set_execution_state(execution_state);
    }
  }
  T->SetAtSafepoint(false, level);
}

void SafepointHandler::RunTasks(IntrusiveDList<SafepointTask>* tasks) {
  ASSERT(Thread::Current()->OwnsSafepoint());

  // Withold one task for the main thread.
  ASSERT(!tasks->IsEmpty());
  SafepointTask* main = tasks->RemoveFirst();

  // First use threads blocked at this safepoint.
  {
    MonitorLocker tl(threads_lock());
    ASSERT(tasks_.IsEmpty());
    for (auto current = isolate_group()->thread_registry()->active_list();
         current != nullptr; current = current->next()) {
      if (tasks->IsEmpty()) break;

      MonitorLocker tl(current->thread_lock());
      if (current->IsBlockedForSafepoint()) {
        tasks_.Append(tasks->RemoveFirst());
        tl.Notify();
      }
    }
  }

  // Then use thread pool workers.
  while (!tasks->IsEmpty()) {
    bool result = Dart::thread_pool()->Run(tasks->RemoveFirst());
    ASSERT(result);
  }

  // Run one task on the main thread.
  main->RunMain();
  delete main;

  // Clean up any tasks that took too long to start.
  {
    MonitorLocker tl(threads_lock());
    while (!tasks_.IsEmpty()) {
      delete tasks_.RemoveFirst();
    }
  }
}

SafepointTask::~SafepointTask() {
  barrier_->Release();
}

void SafepointTask::Run() {
  if (!barrier_->TryEnter()) {
    return;
  }

  Thread::EnterIsolateGroupAsHelper(isolate_group_, kind_,
                                    /*bypass_safepoint=*/true);

  RunEnteredIsolateGroup();

  Thread::ExitIsolateGroupAsHelper(/*bypass_safepoint=*/true);

  barrier_->Sync();
}

void SafepointTask::RunBlockedAtSafepoint() {
  if (!barrier_->TryEnter()) {
    return;
  }

  Thread* thread = Thread::Current();
  Thread::TaskKind saved_task_kind = thread->task_kind();
  thread->set_task_kind(kind_);

  RunEnteredIsolateGroup();

  thread->set_task_kind(saved_task_kind);

  barrier_->Sync();
}

void SafepointTask::RunMain() {
  RunEnteredIsolateGroup();

  barrier_->Sync();
}

}  // namespace dart
