Chromium Code Reviews| Index: runtime/vm/thread_interrupter.cc |
| diff --git a/runtime/vm/thread_interrupter.cc b/runtime/vm/thread_interrupter.cc |
| index 2d44208739fd38bdf776c603fa8100bd170e51dc..d32a9ee13ae29f53893d6523e310de6839e19230 100644 |
| --- a/runtime/vm/thread_interrupter.cc |
| +++ b/runtime/vm/thread_interrupter.cc |
| @@ -52,19 +52,20 @@ Monitor* ThreadInterrupter::monitor_ = NULL; |
| intptr_t ThreadInterrupter::interrupt_period_ = 1000; |
| ThreadLocalKey ThreadInterrupter::thread_state_key_ = |
| Thread::kUnsetThreadLocalKey; |
| -ThreadInterrupter::ThreadState** ThreadInterrupter::threads_ = NULL; |
| -intptr_t ThreadInterrupter::threads_capacity_ = 0; |
| -intptr_t ThreadInterrupter::threads_size_ = 0; |
| void ThreadInterrupter::InitOnce() { |
| ASSERT(!initialized_); |
| - initialized_ = true; |
| ASSERT(thread_state_key_ == Thread::kUnsetThreadLocalKey); |
| thread_state_key_ = Thread::CreateThreadLocal(); |
| ASSERT(thread_state_key_ != Thread::kUnsetThreadLocalKey); |
| monitor_ = new Monitor(); |
|
siva
2014/02/06 00:37:24
ASSERT(monitor_ != NULL);
Cutch
2014/02/06 17:51:51
Done.
|
| - ResizeThreads(16); |
| + initialized_ = true; |
| +} |
| + |
| + |
| +void ThreadInterrupter::Startup() { |
| + ASSERT(initialized_); |
| if (FLAG_trace_thread_interrupter) { |
| OS::Print("ThreadInterrupter starting up.\n"); |
| } |
| @@ -92,15 +93,9 @@ void ThreadInterrupter::Shutdown() { |
| if (FLAG_trace_thread_interrupter) { |
| OS::Print("ThreadInterrupter shutting down.\n"); |
| } |
| - intptr_t size_at_shutdown = 0; |
| { |
| MonitorLocker ml(monitor_); |
| shutdown_ = true; |
| - size_at_shutdown = threads_size_; |
| - threads_size_ = 0; |
| - threads_capacity_ = 0; |
| - free(threads_); |
| - threads_ = NULL; |
| } |
| { |
| MonitorLocker shutdown_ml(monitor_); |
| @@ -110,7 +105,7 @@ void ThreadInterrupter::Shutdown() { |
| } |
| interrupter_thread_id_ = Thread::kInvalidThreadId; |
| if (FLAG_trace_thread_interrupter) { |
| - OS::Print("ThreadInterrupter shut down (%" Pd ").\n", size_at_shutdown); |
| + OS::Print("ThreadInterrupter shut down.\n"); |
| } |
| } |
| @@ -121,27 +116,22 @@ void ThreadInterrupter::SetInterruptPeriod(intptr_t period) { |
| } |
| ASSERT(initialized_); |
| ASSERT(period > 0); |
| - { |
| - MonitorLocker ml(monitor_); |
| - interrupt_period_ = period; |
| - } |
| + interrupt_period_ = period; |
| } |
| // Register the currently running thread for interrupts. If the current thread |
| // is already registered, callback and data will be updated. |
| -void ThreadInterrupter::Register(ThreadInterruptCallback callback, void* data) { |
| +InterruptableThreadState* ThreadInterrupter::Register( |
| + ThreadInterruptCallback callback, void* data) { |
| if (shutdown_) { |
| - return; |
| + return NULL; |
| } |
| ASSERT(initialized_); |
| - { |
| - MonitorLocker ml(monitor_); |
| - _EnsureThreadStateCreated(); |
| - // Set callback and data. |
| - UpdateStateObject(callback, data); |
| - _Enable(); |
| - } |
| + InterruptableThreadState* state = _EnsureThreadStateCreated(); |
| + // Set callback and data. |
| + UpdateStateObject(callback, data); |
| + return state; |
| } |
| @@ -151,44 +141,14 @@ void ThreadInterrupter::Unregister() { |
| return; |
| } |
| ASSERT(initialized_); |
| - { |
| - MonitorLocker ml(monitor_); |
| - _EnsureThreadStateCreated(); |
| - // Clear callback and data. |
| - UpdateStateObject(NULL, NULL); |
| - _Disable(); |
| - } |
| + _EnsureThreadStateCreated(); |
| + // Clear callback and data. |
| + UpdateStateObject(NULL, NULL); |
| } |
| -void ThreadInterrupter::Enable() { |
| - if (shutdown_) { |
| - return; |
| - } |
| - ASSERT(initialized_); |
| - { |
| - MonitorLocker ml(monitor_); |
| - _EnsureThreadStateCreated(); |
| - _Enable(); |
| - } |
| -} |
| - |
| - |
| -void ThreadInterrupter::Disable() { |
| - if (shutdown_) { |
| - return; |
| - } |
| - ASSERT(initialized_); |
| - { |
| - MonitorLocker ml(monitor_); |
| - _EnsureThreadStateCreated(); |
| - _Disable(); |
| - } |
| -} |
| - |
| - |
| -void ThreadInterrupter::_EnsureThreadStateCreated() { |
| - ThreadState* state = CurrentThreadState(); |
| +InterruptableThreadState* ThreadInterrupter::_EnsureThreadStateCreated() { |
| + InterruptableThreadState* state = CurrentThreadState(); |
| if (state == NULL) { |
| // Create thread state object lazily. |
| ThreadId current_thread = Thread::GetCurrentThreadId(); |
| @@ -197,56 +157,19 @@ void ThreadInterrupter::_EnsureThreadStateCreated() { |
| OS::Print("ThreadInterrupter Tracking %p\n", |
| reinterpret_cast<void*>(tid)); |
| } |
| - state = new ThreadState(); |
| + state = new InterruptableThreadState(); |
|
siva
2014/02/06 00:37:24
ASSERT(state != NULL);
Cutch
2014/02/06 17:51:51
Done.
|
| state->callback = NULL; |
| state->data = NULL; |
| state->id = current_thread; |
| SetCurrentThreadState(state); |
| } |
| + return state; |
| } |
| -void ThreadInterrupter::_Enable() { |
| - // Must be called with monitor_ locked. |
| - ThreadId current_thread = Thread::GetCurrentThreadId(); |
| - if (Thread::Compare(current_thread, interrupter_thread_id_)) { |
| - return; |
| - } |
| - intptr_t i = FindThreadIndex(current_thread); |
| - if (i >= 0) { |
| - return; |
| - } |
| - AddThread(current_thread); |
| - if (FLAG_trace_thread_interrupter) { |
| - intptr_t tid = Thread::ThreadIdToIntPtr(current_thread); |
| - OS::Print("ThreadInterrupter Added %p\n", reinterpret_cast<void*>(tid)); |
| - } |
| -} |
| - |
| -void ThreadInterrupter::_Disable() { |
| - // Must be called with monitor_ locked. |
| - ThreadId current_thread = Thread::GetCurrentThreadId(); |
| - if (Thread::Compare(current_thread, interrupter_thread_id_)) { |
| - return; |
| - } |
| - intptr_t index = FindThreadIndex(current_thread); |
| - if (index < 0) { |
| - // Not registered. |
| - return; |
| - } |
| - ThreadState* state = RemoveThread(index); |
| - ASSERT(state != NULL); |
| - ASSERT(state == ThreadInterrupter::CurrentThreadState()); |
| - if (FLAG_trace_thread_interrupter) { |
| - intptr_t tid = Thread::ThreadIdToIntPtr(current_thread); |
| - OS::Print("ThreadInterrupter Removed %p\n", reinterpret_cast<void*>(tid)); |
| - } |
| -} |
| - |
| void ThreadInterrupter::UpdateStateObject(ThreadInterruptCallback callback, |
| void* data) { |
| - // Must be called with monitor_ locked. |
| - ThreadState* state = CurrentThreadState(); |
| + InterruptableThreadState* state = CurrentThreadState(); |
| ThreadId current_thread = Thread::GetCurrentThreadId(); |
| ASSERT(state != NULL); |
| ASSERT(Thread::Compare(state->id, Thread::GetCurrentThreadId())); |
| @@ -267,90 +190,40 @@ void ThreadInterrupter::UpdateStateObject(ThreadInterruptCallback callback, |
| } |
| -ThreadInterrupter::ThreadState* ThreadInterrupter::CurrentThreadState() { |
| - ThreadState* state = reinterpret_cast<ThreadState*>( |
| - Thread::GetThreadLocal(thread_state_key_)); |
| - return state; |
| +InterruptableThreadState* ThreadInterrupter::GetCurrentThreadState() { |
| + return _EnsureThreadStateCreated(); |
| } |
| -void ThreadInterrupter::SetCurrentThreadState(ThreadState* state) { |
| - Thread::SetThreadLocal(thread_state_key_, reinterpret_cast<uword>(state)); |
| +InterruptableThreadState* ThreadInterrupter::CurrentThreadState() { |
| + InterruptableThreadState* state = reinterpret_cast<InterruptableThreadState*>( |
| + Thread::GetThreadLocal(thread_state_key_)); |
| + return state; |
| } |
| -void ThreadInterrupter::ResizeThreads(intptr_t new_capacity) { |
| - // Must be called with monitor_ locked. |
| - ASSERT(new_capacity < kMaxThreads); |
| - ASSERT(new_capacity > threads_capacity_); |
| - ThreadState* state = NULL; |
| - threads_ = reinterpret_cast<ThreadState**>( |
| - realloc(threads_, sizeof(state) * new_capacity)); |
| - for (intptr_t i = threads_capacity_; i < new_capacity; i++) { |
| - threads_[i] = NULL; |
| - } |
| - threads_capacity_ = new_capacity; |
| +void ThreadInterrupter::SetCurrentThreadState(InterruptableThreadState* state) { |
| + Thread::SetThreadLocal(thread_state_key_, reinterpret_cast<uword>(state)); |
| } |
| -void ThreadInterrupter::AddThread(ThreadId id) { |
| - // Must be called with monitor_ locked. |
| - if (threads_ == NULL) { |
| - // We are shutting down. |
| - return; |
| - } |
| - ThreadState* state = CurrentThreadState(); |
| - if (state->callback == NULL) { |
| - // No callback. |
| - return; |
| - } |
| - if (threads_size_ == threads_capacity_) { |
| - ResizeThreads(threads_capacity_ == 0 ? 16 : threads_capacity_ * 2); |
| - } |
| - threads_[threads_size_] = state; |
| - threads_size_++; |
| +void ThreadInterruptNoOp(const InterruptedThreadState& state, void* data) { |
| + // NoOp. |
| } |
| -intptr_t ThreadInterrupter::FindThreadIndex(ThreadId id) { |
| - // Must be called with monitor_ locked. |
| - if (threads_ == NULL) { |
| - // We are shutting down. |
| - return -1; |
| - } |
| - for (intptr_t i = 0; i < threads_size_; i++) { |
| - if (threads_[i]->id == id) { |
| - return i; |
| +class ThreadInterrupterVisitIsolates : public IsolateVisitor { |
| + public: |
| + void VisitIsolate(Isolate* isolate) { |
| + ASSERT(isolate != NULL); |
| + InterruptableThreadState* state = isolate->thread_state(); |
| + if (state == NULL) { |
| + return; |
| } |
| + ASSERT(state->id != Thread::kInvalidThreadId); |
| + ThreadInterrupter::InterruptThread(state); |
| } |
| - return -1; |
| -} |
| - |
| - |
| -ThreadInterrupter::ThreadState* ThreadInterrupter::RemoveThread(intptr_t i) { |
| - // Must be called with monitor_ locked. |
| - if (threads_ == NULL) { |
| - // We are shutting down. |
| - return NULL; |
| - } |
| - ASSERT(i < threads_size_); |
| - ThreadState* state = threads_[i]; |
| - ASSERT(state != NULL); |
| - intptr_t last = threads_size_ - 1; |
| - if (i != last) { |
| - threads_[i] = threads_[last]; |
| - } |
| - // Mark last as NULL. |
| - threads_[last] = NULL; |
| - // Pop. |
| - threads_size_--; |
| - return state; |
| -} |
| - |
| - |
| -void ThreadInterruptNoOp(const InterruptedThreadState& state, void* data) { |
| - // NoOp. |
| -} |
| +}; |
| void ThreadInterrupter::ThreadMain(uword parameters) { |
| @@ -367,11 +240,11 @@ void ThreadInterrupter::ThreadMain(uword parameters) { |
| startup_ml.Notify(); |
| } |
| { |
| - MonitorLocker ml(monitor_); |
| + MonitorLocker wait_ml(monitor_); |
| + ThreadInterrupterVisitIsolates visitor; |
| while (!shutdown_) { |
| - int64_t current_time = OS::GetCurrentTimeMicros(); |
| - InterruptThreads(current_time); |
| - ml.WaitMicros(interrupt_period_); |
| + Isolate::VisitIsolates(&visitor); |
| + wait_ml.WaitMicros(interrupt_period_); |
| } |
| } |
| if (FLAG_trace_thread_interrupter) { |