// Copyright (c) 2013, 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/thread_interrupter.h"

#include "vm/flags.h"
#include "vm/lockers.h"
#include "vm/os.h"
#include "vm/simulator.h"

namespace dart {

#if defined(DART_INCLUDE_PROFILER)

// Notes:
//
// The ThreadInterrupter interrupts all threads actively running isolates once
// per interrupt period (default is 1 millisecond). While the thread is
// interrupted, the thread's interrupt callback is invoked. Callbacks cannot
// rely on being executed on the interrupted thread.
//
// There are two mechanisms used to interrupt a thread. The first, used on Linux
// and Android, is SIGPROF. The second, used on Windows, Fuchsia, Mac and iOS,
// is explicit suspend and resume thread system calls. (Although Mac supports
// SIGPROF, when the process is attached to lldb, it becomes unusably slow, and
// signal masking is unreliable across fork-exec.) Signal delivery forbids
// taking locks and allocating memory (which takes a lock). Explicit suspend and
// resume means that the interrupt callback will not be executing on the
// interrupted thread, making it meaningless to access TLS from within the
// thread interrupt callback. Combining these limitations, thread interrupt
// callbacks are forbidden from:
//
//   * Accessing TLS.
//   * Allocating memory.
//   * Taking a lock.
//
// The ThreadInterrupter has a single monitor (monitor_). This monitor is used
// to synchronize startup, shutdown, and waking up from a deep sleep.
//

DEFINE_FLAG(bool, trace_thread_interrupter, false, "Trace thread interrupter");

bool ThreadInterrupter::initialized_ = false;
bool ThreadInterrupter::shutdown_ = false;
bool ThreadInterrupter::thread_running_ = false;
bool ThreadInterrupter::woken_up_ = false;
ThreadJoinId ThreadInterrupter::interrupter_thread_id_ =
    OSThread::kInvalidThreadJoinId;
Monitor* ThreadInterrupter::monitor_ = nullptr;
intptr_t ThreadInterrupter::interrupt_period_ = 1000;
intptr_t ThreadInterrupter::current_wait_time_ = Monitor::kNoTimeout;

void ThreadInterrupter::Init(intptr_t period) {
  ASSERT(!initialized_);
  if (monitor_ == nullptr) {
    monitor_ = new Monitor();
  }
  ASSERT(monitor_ != nullptr);
  initialized_ = true;
  shutdown_ = false;
  interrupt_period_ = period;
}

void ThreadInterrupter::Startup() {
  ASSERT(initialized_);
  if (FLAG_trace_thread_interrupter) {
    OS::PrintErr("ThreadInterrupter starting up.\n");
  }
  ASSERT(interrupter_thread_id_ == OSThread::kInvalidThreadJoinId);
  {
    MonitorLocker startup_ml(monitor_);
    OSThread::Start("Dart Profiler ThreadInterrupter", ThreadMain, 0);
    while (!thread_running_) {
      startup_ml.Wait();
    }
  }
  ASSERT(interrupter_thread_id_ != OSThread::kInvalidThreadJoinId);
  if (FLAG_trace_thread_interrupter) {
    OS::PrintErr("ThreadInterrupter running.\n");
  }
}

void ThreadInterrupter::Cleanup() {
  {
    MonitorLocker shutdown_ml(monitor_);
    if (shutdown_) {
      // Already shutdown.
      return;
    }
    shutdown_ = true;
    // Notify.
    shutdown_ml.Notify();
    ASSERT(initialized_);
    if (FLAG_trace_thread_interrupter) {
      OS::PrintErr("ThreadInterrupter shutting down.\n");
    }
  }

  // Join the thread.
  ASSERT(interrupter_thread_id_ != OSThread::kInvalidThreadJoinId);
  OSThread::Join(interrupter_thread_id_);
  interrupter_thread_id_ = OSThread::kInvalidThreadJoinId;
  initialized_ = false;

  if (FLAG_trace_thread_interrupter) {
    OS::PrintErr("ThreadInterrupter shut down.\n");
  }
}

// Delay between interrupts.
void ThreadInterrupter::SetInterruptPeriod(intptr_t period) {
  if (!initialized_) {
    // Profiler may not be enabled.
    return;
  }
  MonitorLocker ml(monitor_);
  if (shutdown_) {
    return;
  }
  ASSERT(initialized_);
  ASSERT(period > 0);
  interrupt_period_ = period;
}

void ThreadInterrupter::WakeUp() {
  if (monitor_ == nullptr) {
    // Early call.
    return;
  }
  {
    MonitorLocker ml(monitor_);
    if (shutdown_) {
      // Late call
      return;
    }
    if (!initialized_) {
      // Early call.
      return;
    }
    woken_up_ = true;
    if (!InDeepSleep()) {
      // No need to notify, regularly waking up.
      return;
    }
    // Notify the interrupter to wake it from its deep sleep.
    ml.Notify();
  }
}

void ThreadInterrupter::ThreadMain(uword parameters) {
  ASSERT(initialized_);
  InstallSignalHandler();
  if (FLAG_trace_thread_interrupter) {
    OS::PrintErr("ThreadInterrupter thread running.\n");
  }
  {
    // Signal to main thread we are ready.
    MonitorLocker startup_ml(monitor_);
    OSThread* os_thread = OSThread::Current();
    ASSERT(os_thread != nullptr);
    interrupter_thread_id_ = OSThread::GetCurrentThreadJoinId(os_thread);
    thread_running_ = true;
    startup_ml.Notify();
  }
  {
    intptr_t interrupted_thread_count = 0;
    MonitorLocker wait_ml(monitor_);
    current_wait_time_ = interrupt_period_;
    while (!shutdown_) {
      intptr_t r = wait_ml.WaitMicros(current_wait_time_);

      if (shutdown_) {
        break;
      }

      if ((r == Monitor::kNotified) && InDeepSleep()) {
        // Woken up from deep sleep.
        ASSERT(interrupted_thread_count == 0);
        // Return to regular interrupts.
        current_wait_time_ = interrupt_period_;
      } else if (current_wait_time_ != interrupt_period_) {
        // The interrupt period may have been updated via the service protocol.
        current_wait_time_ = interrupt_period_;
      }

      // Reset count before interrupting any threads.
      interrupted_thread_count = 0;

      // Temporarily drop the monitor while we interrupt threads.
      wait_ml.Exit();

      {
        OSThreadIterator it;
        while (it.HasNext()) {
          OSThread* thread = it.Next();
          if (thread->ThreadInterruptsEnabled()) {
            interrupted_thread_count++;
            InterruptThread(thread);
          }
        }
      }

      // Take the monitor lock again.
      wait_ml.Enter();

      // Now that we have the lock, check if we were signaled to wake up while
      // interrupting threads.
      if (!woken_up_ && (interrupted_thread_count == 0)) {
        // No threads were interrupted and we were not signaled to interrupt
        // new threads. In order to reduce unnecessary CPU load, we will wait
        // until we are notified before attempting to interrupt again.
        current_wait_time_ = Monitor::kNoTimeout;
        continue;
      }

      woken_up_ = false;

      ASSERT(current_wait_time_ != Monitor::kNoTimeout);
    }
  }
  RemoveSignalHandler();
  if (FLAG_trace_thread_interrupter) {
    OS::PrintErr("ThreadInterrupter thread exiting.\n");
  }
  {
    // Signal to main thread we are exiting.
    MonitorLocker shutdown_ml(monitor_);
    thread_running_ = false;
    shutdown_ml.Notify();
  }
}

#if !defined(DART_HOST_OS_ANDROID)
void* ThreadInterrupter::PrepareCurrentThread() {
  return nullptr;
}

void ThreadInterrupter::CleanupCurrentThreadState(void* state) {}
#endif

#endif  // defined(DART_INCLUDE_PROFILER)

}  // namespace dart
