Chromium Code Reviews| Index: runtime/vm/thread_interrupter_win.cc |
| diff --git a/runtime/vm/thread_interrupter_win.cc b/runtime/vm/thread_interrupter_win.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..7183f9bff6a2bfa0ba729c6c7ddc6a0b562237bf |
| --- /dev/null |
| +++ b/runtime/vm/thread_interrupter_win.cc |
| @@ -0,0 +1,125 @@ |
| +// 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_WINDOWS) |
| + |
| +#include "vm/thread_interrupter.h" |
| + |
| +namespace dart { |
| + |
| +DECLARE_FLAG(bool, thread_interrupter); |
| +DECLARE_FLAG(bool, trace_thread_interrupter); |
| + |
| +#define kThreadError -1 |
| + |
| +class ThreadInterrupterWin : public AllStatic { |
| + public: |
| + static bool GrabRegisters(ThreadId thread, InterruptedThreadState* state) { |
| + CONTEXT context; |
| + memset(&context, 0, sizeof(context)); |
| + context.ContextFlags = CONTEXT_FULL; |
| + if (GetThreadContext(thread, &context) != 0) { |
| +#if defined(TARGET_ARCH_IA32) |
| + state->pc = static_cast<uintptr_t>(context.Eip); |
| + state->fp = static_cast<uintptr_t>(context.Ebp); |
| + state->sp = static_cast<uintptr_t>(context.Esp); |
| +#elif defined(TARGET_ARCH_X64) |
| + state->pc = reinterpret_cast<uintptr_t>(context.Rip); |
| + state->fp = reinterpret_cast<uintptr_t>(context.Rbp); |
| + state->sp = reinterpret_cast<uintptr_t>(context.Rsp); |
| +#else |
| + UNIMPLEMENTED(); |
| +#endif |
| + return true; |
| + } |
| + return false; |
| + } |
| + |
| + static void Interrupt(ThreadInterrupter::ThreadState* state) { |
| + ASSERT(GetCurrentThread() != state->id); |
| + DWORD result = SuspendThread(state->id); |
| + if (result == kThreadError) { |
| + if (FLAG_trace_thread_interrupter) { |
| + OS::Print("ThreadInterrupted failed to suspend thread %p\n", |
| + reinterpret_cast<void*>(state->id)); |
| + } |
| + return; |
| + } |
| + InterruptedThreadState its; |
| + its.tid = state->id; |
| + if (!GrabRegisters(state->id, &its)) { |
| + // Failed to get thread registers. |
| + ResumeThread(state->id); |
| + if (FLAG_trace_thread_interrupter) { |
| + OS::Print("ThreadInterrupted failed to get registers for %p\n", |
| + reinterpret_cast<void*>(state->id)); |
| + } |
| + return; |
| + } |
| + if (state->callback == NULL) { |
| + // No callback registered. |
| + ResumeThread(state->id); |
| + return; |
| + } |
| + state->callback(its, state->data); |
| + ResumeThread(state->id); |
| + } |
| +}; |
| + |
| + |
| +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 suspending %p\n", |
| + reinterpret_cast<void*>(state->id)); |
| + } |
| + ThreadInterrupterWin::Interrupt(state); |
| + if (FLAG_trace_thread_interrupter) { |
| + OS::Print("ThreadInterrupter resuming %p\n", |
| + reinterpret_cast<void*>(state->id)); |
| + } |
| + } |
| +} |
| + |
| + |
| +void ThreadInterrupter::ThreadMain(uword parameters) { |
| + ASSERT(FLAG_thread_interrupter); |
| + ASSERT(initialized_); |
| + if (FLAG_trace_thread_interrupter) { |
| + OS::Print("ThreadInterrupter Windows 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(); |
| + } |
| + monitor_->Enter(); |
| + while (!shutdown_) { |
| + int64_t current_time = OS::GetCurrentTimeMicros(); |
| + InterruptThreads(current_time); |
| + monitor_->Exit(); |
| + OS::SleepMicros(interrupt_period_); |
| + monitor_->Enter(); |
| + } |
|
siva
2013/12/11 02:52:21
Why is the pattern different here?
We have a Mutex
|
| + if (FLAG_trace_thread_interrupter) { |
| + OS::Print("ThreadInterrupter Windows 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_WINDOWS) |
| + |