| // 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. |
| |
| #ifndef VM_THREAD_INTERRUPTER_H_ |
| #define VM_THREAD_INTERRUPTER_H_ |
| |
| #include "vm/allocation.h" |
| #include "vm/signal_handler.h" |
| #include "vm/os_thread.h" |
| |
| |
| namespace dart { |
| |
| struct InterruptedThreadState { |
| ThreadId tid; |
| uintptr_t pc; |
| uintptr_t csp; |
| uintptr_t dsp; |
| uintptr_t fp; |
| uintptr_t lr; |
| }; |
| |
| // When a thread is interrupted the thread specific interrupt callback will be |
| // invoked. Each callback is given an InterruptedThreadState and the user data |
| // pointer. When inside a thread interrupt callback doing any of the following |
| // is forbidden: |
| // * Accessing TLS. |
| // * Allocating memory. |
| // * Taking a lock. |
| typedef void (*ThreadInterruptCallback)(const InterruptedThreadState& state, |
| void* data); |
| |
| // State stored per registered thread. |
| class InterruptableThreadState { |
| public: |
| ThreadId id; |
| ThreadInterruptCallback callback; |
| void* data; |
| }; |
| |
| class ThreadInterrupter : public AllStatic { |
| public: |
| static void InitOnce(); |
| |
| static void Startup(); |
| static void Shutdown(); |
| |
| // Delay between interrupts. |
| static void SetInterruptPeriod(intptr_t period); |
| |
| // Wake up the thread interrupter thread. |
| static void WakeUp(); |
| |
| // Register the currently running thread for interrupts. If the current thread |
| // is already registered, callback and data will be updated. |
| static InterruptableThreadState* Register(ThreadInterruptCallback callback, |
| void* data); |
| // Unregister the currently running thread for interrupts. |
| static void Unregister(); |
| |
| // Get the current thread state. Will create a thread state if one hasn't |
| // been allocated. |
| static InterruptableThreadState* GetCurrentThreadState(); |
| // Get the current thread state. Will not create one if one doesn't exist. |
| static InterruptableThreadState* CurrentThreadState(); |
| |
| // Interrupt a thread. |
| static void InterruptThread(InterruptableThreadState* thread_state); |
| |
| private: |
| static const intptr_t kMaxThreads = 4096; |
| static bool initialized_; |
| static bool shutdown_; |
| static bool thread_running_; |
| static ThreadId interrupter_thread_id_; |
| static Monitor* monitor_; |
| static intptr_t interrupt_period_; |
| static intptr_t current_wait_time_; |
| static ThreadLocalKey thread_state_key_; |
| |
| static bool InDeepSleep() { |
| return current_wait_time_ == Monitor::kNoTimeout; |
| } |
| |
| static InterruptableThreadState* _EnsureThreadStateCreated(); |
| static void UpdateStateObject(ThreadInterruptCallback callback, void* data); |
| |
| static void SetCurrentThreadState(InterruptableThreadState* state); |
| |
| static void ThreadMain(uword parameters); |
| |
| static void InstallSignalHandler(); |
| |
| friend class ThreadInterrupterVisitIsolates; |
| }; |
| |
| void ThreadInterruptNoOp(const InterruptedThreadState& state, void* data); |
| |
| } // namespace dart |
| |
| #endif // VM_THREAD_INTERRUPTER_H_ |