| 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);
|
| }
|
| }
|
|
|