Chromium Code Reviews| Index: runtime/vm/thread_interrupter.cc |
| diff --git a/runtime/vm/thread_interrupter.cc b/runtime/vm/thread_interrupter.cc |
| index 58c94bec797cc04dadc697d31c33db8dd7d31f8e..e078324c4cda823656ea5b46386f296c063eaacd 100644 |
| --- a/runtime/vm/thread_interrupter.cc |
| +++ b/runtime/vm/thread_interrupter.cc |
| @@ -51,6 +51,7 @@ DEFINE_FLAG(bool, trace_thread_interrupter, false, |
| 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_ = NULL; |
| @@ -124,9 +125,14 @@ void ThreadInterrupter::SetInterruptPeriod(intptr_t period) { |
| void ThreadInterrupter::WakeUp() { |
| + if (!initialized_) { |
| + // Early call. |
| + return; |
| + } |
| ASSERT(initialized_); |
| { |
| MonitorLocker ml(monitor_); |
| + woken_up_ = true; |
| if (!InDeepSleep()) { |
| // No need to notify, regularly waking up. |
| return; |
| @@ -137,35 +143,6 @@ void ThreadInterrupter::WakeUp() { |
| } |
| -void ThreadInterruptNoOp(const InterruptedThreadState& state, void* data) { |
| - // NoOp. |
| -} |
| - |
| - |
| -class ThreadInterrupterVisitIsolates : public IsolateVisitor { |
| - public: |
| - ThreadInterrupterVisitIsolates() { |
| - profiled_thread_count_ = 0; |
| - } |
| - |
| - void VisitIsolate(Isolate* isolate) { |
| - ASSERT(isolate != NULL); |
| - profiled_thread_count_ += isolate->ProfileInterrupt(); |
| - } |
| - |
| - intptr_t profiled_thread_count() const { |
| - return profiled_thread_count_; |
| - } |
| - |
| - void set_profiled_thread_count(intptr_t profiled_thread_count) { |
| - profiled_thread_count_ = profiled_thread_count; |
| - } |
| - |
| - private: |
| - intptr_t profiled_thread_count_; |
| -}; |
| - |
| - |
| void ThreadInterrupter::ThreadMain(uword parameters) { |
| ASSERT(initialized_); |
| InstallSignalHandler(); |
| @@ -180,31 +157,53 @@ void ThreadInterrupter::ThreadMain(uword parameters) { |
| startup_ml.Notify(); |
| } |
| { |
| - ThreadInterrupterVisitIsolates visitor; |
| + intptr_t interrupted_thread_count = 0; |
| current_wait_time_ = interrupt_period_; |
| MonitorLocker wait_ml(monitor_); |
| while (!shutdown_) { |
| intptr_t r = wait_ml.WaitMicros(current_wait_time_); |
| - if ((r == Monitor::kNotified) && shutdown_) { |
| + if (shutdown_) { |
| break; |
| } |
| if ((r == Monitor::kNotified) && InDeepSleep()) { |
| // Woken up from deep sleep. |
| - ASSERT(visitor.profiled_thread_count() == 0); |
| + ASSERT(interrupted_thread_count == 0); |
| // Return to regular interrupts. |
| current_wait_time_ = interrupt_period_; |
| } |
| - // Reset count before visiting isolates. |
| - visitor.set_profiled_thread_count(0); |
| - Isolate::VisitIsolates(&visitor); |
| + // Reset count before interrupting any threads. |
| + interrupted_thread_count = 0; |
| + |
| + // Temporarily drop the monitor while we interrupt threads. |
| + monitor_->Exit(); |
| + |
| + { |
| + ThreadIterator it; |
| + while (it.HasNext()) { |
| + Thread* thread = it.Next(); |
| + if (thread->ThreadInterruptsEnabled()) { |
| + interrupted_thread_count++; |
| + InterruptThread(thread); |
| + } |
| + } |
| + } |
| + |
| + // Take the monitor lock again. |
| + monitor_->Enter(); |
| + |
| + // Now that we have the lock, check if we were signal to wake up while |
|
siva
2015/10/29 21:47:41
we were signalled
Cutch
2015/11/02 20:47:12
Done.
|
| + // interrupting threads. |
| + const bool woken_up = woken_up_; |
| + // Clear the state. |
| + woken_up_ = false; |
| - if (visitor.profiled_thread_count() == 0) { |
| - // No isolates were profiled. In order to reduce unnecessary CPU |
| - // load, we will wait until we are notified before attempting to |
| - // interrupt again. |
| + 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; |
| } |