Index: runtime/vm/thread_interrupter.cc |
diff --git a/runtime/vm/thread_interrupter.cc b/runtime/vm/thread_interrupter.cc |
index 616d29b5e7cae897580a8ee8315ccdcc0acbec37..58c94bec797cc04dadc697d31c33db8dd7d31f8e 100644 |
--- a/runtime/vm/thread_interrupter.cc |
+++ b/runtime/vm/thread_interrupter.cc |
@@ -51,7 +51,6 @@ 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; |
@@ -125,14 +124,9 @@ 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; |
@@ -143,6 +137,35 @@ 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(); |
@@ -157,55 +180,35 @@ void ThreadInterrupter::ThreadMain(uword parameters) { |
startup_ml.Notify(); |
} |
{ |
- intptr_t interrupted_thread_count = 0; |
+ ThreadInterrupterVisitIsolates visitor; |
current_wait_time_ = interrupt_period_; |
MonitorLocker wait_ml(monitor_); |
while (!shutdown_) { |
intptr_t r = wait_ml.WaitMicros(current_wait_time_); |
- if (shutdown_) { |
+ if ((r == Monitor::kNotified) && shutdown_) { |
break; |
} |
if ((r == Monitor::kNotified) && InDeepSleep()) { |
// Woken up from deep sleep. |
- ASSERT(interrupted_thread_count == 0); |
+ ASSERT(visitor.profiled_thread_count() == 0); |
// Return to regular interrupts. |
current_wait_time_ = interrupt_period_; |
} |
- // 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(); |
+ // Reset count before visiting isolates. |
+ visitor.set_profiled_thread_count(0); |
+ Isolate::VisitIsolates(&visitor); |
- // Now that we have the lock, check if we were signaled to wake up while |
- // interrupting threads. |
- 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. |
+ 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. |
current_wait_time_ = Monitor::kNoTimeout; |
continue; |
} |
- woken_up_ = false; |
- |
ASSERT(current_wait_time_ != Monitor::kNoTimeout); |
} |
} |