Chromium Code Reviews| Index: runtime/vm/thread_interrupter_linux.cc |
| diff --git a/runtime/vm/thread_interrupter_linux.cc b/runtime/vm/thread_interrupter_linux.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..f738834a255578dcfa2a3eb27d33e9c4f56d7ef0 |
| --- /dev/null |
| +++ b/runtime/vm/thread_interrupter_linux.cc |
| @@ -0,0 +1,89 @@ |
| +// 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 "platform/globals.h" |
| +#if defined(TARGET_OS_LINUX) |
| + |
| +#include "vm/signal_handler.h" |
| +#include "vm/thread_interrupter.h" |
| + |
| +namespace dart { |
| + |
| +DECLARE_FLAG(bool, thread_interrupter); |
| +DECLARE_FLAG(bool, trace_thread_interrupter); |
| + |
| +class ThreadInterrupterLinux : public AllStatic { |
| + public: |
| + static void ThreadInterruptSignalHandler(int signal, siginfo_t* info, |
| + void* context_) { |
| + if (signal != SIGPROF) { |
| + return; |
| + } |
| + ThreadInterrupter::ThreadState* state = |
| + ThreadInterrupter::CurrentThreadState(); |
| + if ((state == NULL) || (state->callback == NULL)) { |
| + // No interrupter state or callback. |
| + return; |
| + } |
| + ASSERT(Thread::Compare(state->id, Thread::GetCurrentThreadId())); |
| + // Extract thread state. |
| + ucontext_t* context = reinterpret_cast<ucontext_t*>(context_); |
| + mcontext_t mcontext = context->uc_mcontext; |
| + InterruptedThreadState its; |
| + its.tid = state->id; |
| + its.pc = SignalHandler::GetProgramCounter(mcontext); |
| + its.fp = SignalHandler::GetFramePointer(mcontext); |
| + its.sp = SignalHandler::GetStackPointer(mcontext); |
| + state->callback(its, state->data); |
| + } |
| +}; |
| + |
| + |
| +void ThreadInterrupter::InterruptThreads(int64_t current_time) { |
| + for (intptr_t i = 0; i < threads_size_; i++) { |
| + ThreadState* state = threads_[i]; |
| + ASSERT(state->id != Thread::kInvalidThreadId); |
| + if (FLAG_trace_thread_interrupter) { |
| + OS::Print("ThreadInterrupter interrupting %p\n", |
| + reinterpret_cast<void*>(state->id)); |
| + } |
| + pthread_kill(state->id, SIGPROF); |
| + } |
| +} |
| + |
| +void ThreadInterrupter::ThreadMain(uword parameters) { |
| + ASSERT(FLAG_thread_interrupter); |
| + ASSERT(initialized_); |
| + SignalHandler::Install(ThreadInterrupterLinux::ThreadInterruptSignalHandler); |
|
siva
2013/12/11 02:52:21
The ThreadMain function in the 4 versions seem ide
Cutch
2013/12/11 17:44:56
Done.
|
| + if (FLAG_trace_thread_interrupter) { |
| + OS::Print("ThreadInterrupter Linux ready.\n"); |
| + } |
| + { |
| + // Signal to main thread we are ready. |
| + MonitorLocker startup_ml(start_stop_monitor_); |
| + thread_running_ = true; |
| + interrupter_thread_id_ = Thread::GetCurrentThreadId(); |
| + startup_ml.Notify(); |
| + } |
| + MonitorLocker ml(monitor_); |
| + while (!shutdown_) { |
| + int64_t current_time = OS::GetCurrentTimeMicros(); |
| + InterruptThreads(current_time); |
| + ml.WaitMicros(interrupt_period_); |
| + } |
| + if (FLAG_trace_thread_interrupter) { |
| + OS::Print("ThreadInterrupter Linux exiting.\n"); |
| + } |
| + { |
| + // Signal to main thread we are exiting. |
| + MonitorLocker shutdown_ml(start_stop_monitor_); |
| + thread_running_ = false; |
| + shutdown_ml.Notify(); |
| + } |
| +} |
| + |
| + |
| +} // namespace dart |
| + |
| +#endif // defined(TARGET_OS_LINUX) |