void ThreadList::ResumeAllForDebugger() {
Thread* self = Thread::Current();
Thread* debug_thread = Dbg::GetDebugThread();
- bool needs_resume = false;
VLOG(threads) << *self << " ResumeAllForDebugger starting...";
MutexLock suspend_count_mu(self, *Locks::thread_suspend_count_lock_);
// Update global suspend all state for attaching threads.
DCHECK_GE(suspend_all_count_, debug_suspend_all_count_);
- needs_resume = (debug_suspend_all_count_ > 0);
- if (needs_resume) {
+ if (debug_suspend_all_count_ > 0) {
--suspend_all_count_;
--debug_suspend_all_count_;
- // Decrement everybody's suspend count (except our own).
- for (const auto& thread : list_) {
- if (thread == self || thread == debug_thread) {
- continue;
- }
- if (thread->GetDebugSuspendCount() == 0) {
- // This thread may have been individually resumed with ThreadReference.Resume.
- continue;
- }
- VLOG(threads) << "requesting thread resume: " << *thread;
- thread->ModifySuspendCount(self, -1, true);
- }
} else {
// We've been asked to resume all threads without being asked to
- // suspend them all before. Let's print a warning.
+ // suspend them all before. That may happen if a debugger tries
+ // to resume some suspended threads (with suspend count == 1)
+ // at once with a VirtualMachine.Resume command. Let's print a
+ // warning.
LOG(WARNING) << "Debugger attempted to resume all threads without "
<< "having suspended them all before.";
}
+ // Decrement everybody's suspend count (except our own).
+ for (const auto& thread : list_) {
+ if (thread == self || thread == debug_thread) {
+ continue;
+ }
+ if (thread->GetDebugSuspendCount() == 0) {
+ // This thread may have been individually resumed with ThreadReference.Resume.
+ continue;
+ }
+ VLOG(threads) << "requesting thread resume: " << *thread;
+ thread->ModifySuspendCount(self, -1, true);
+ }
}
}
- if (needs_resume) {
+ {
MutexLock mu(self, *Locks::thread_suspend_count_lock_);
Thread::resume_cond_->Broadcast(self);
}