Index: runtime/vm/thread_interrupter.cc |
diff --git a/runtime/vm/thread_interrupter.cc b/runtime/vm/thread_interrupter.cc |
index 58c94bec797cc04dadc697d31c33db8dd7d31f8e..a151791963c754d932214626eca594ab47f04cc0 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() { |
Ivan Posva
2015/10/28 08:27:47
It is not clear to me from this CL when the Thread
|
+ 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,11 @@ void ThreadInterrupter::WakeUp() { |
} |
-void ThreadInterruptNoOp(const InterruptedThreadState& state, void* data) { |
+void ThreadInterruptNoOp(Thread* thread, const InterruptedThreadState& state) { |
Ivan Posva
2015/10/28 08:27:47
Where is this used?
Cutch
2015/10/28 14:39:19
Nowhere. It's gone now.
|
// 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,7 +162,7 @@ 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_) { |
@@ -192,19 +174,41 @@ void ThreadInterrupter::ThreadMain(uword parameters) { |
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 |
+ // 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; |
} |