diff options
author | 2014-10-24 07:49:38 +0000 | |
---|---|---|
committer | 2014-10-24 07:49:38 +0000 | |
commit | 02567379e7099682345fd59d45a23e17711c9ddd (patch) | |
tree | afab6024db00d1efb6236fadef9886aefe470973 | |
parent | a1e50cab308af9f9a94e8bd370111eeff5634914 (diff) | |
parent | 253fa555d9424a56c52879449eabe73d5c96cf61 (diff) |
Merge "Fix JDWP Virtualmachine.Resume command"
-rw-r--r-- | runtime/debugger.cc | 2 | ||||
-rw-r--r-- | runtime/debugger.h | 8 | ||||
-rw-r--r-- | runtime/thread_list.cc | 50 | ||||
-rw-r--r-- | runtime/thread_list.h | 5 |
4 files changed, 62 insertions, 3 deletions
diff --git a/runtime/debugger.cc b/runtime/debugger.cc index c56c0e94a6..d9061c8e68 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -2391,7 +2391,7 @@ void Dbg::SuspendVM() { } void Dbg::ResumeVM() { - Runtime::Current()->GetThreadList()->UndoDebuggerSuspensions(); + Runtime::Current()->GetThreadList()->ResumeAllForDebugger(); } JDWP::JdwpError Dbg::SuspendThread(JDWP::ObjectId thread_id, bool request_suspension) { diff --git a/runtime/debugger.h b/runtime/debugger.h index cb7adae47a..48e457fc6f 100644 --- a/runtime/debugger.h +++ b/runtime/debugger.h @@ -246,7 +246,9 @@ class Dbg { */ static int64_t LastDebuggerActivity(); - static void UndoDebuggerSuspensions(); + static void UndoDebuggerSuspensions() + LOCKS_EXCLUDED(Locks::thread_list_lock_, + Locks::thread_suspend_count_lock_); /* * Class, Object, Array @@ -459,7 +461,9 @@ class Dbg { static void SuspendVM() LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::thread_suspend_count_lock_); - static void ResumeVM(); + static void ResumeVM() + LOCKS_EXCLUDED(Locks::thread_list_lock_, + Locks::thread_suspend_count_lock_); static JDWP::JdwpError SuspendThread(JDWP::ObjectId thread_id, bool request_suspension = true) LOCKS_EXCLUDED(Locks::mutator_lock_, Locks::thread_list_lock_, diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc index 6e189047fe..f8c8fdbfee 100644 --- a/runtime/thread_list.cc +++ b/runtime/thread_list.cc @@ -666,6 +666,7 @@ void ThreadList::SuspendAllForDebugger() { { MutexLock mu(self, *Locks::thread_suspend_count_lock_); // Update global suspend all state for attaching threads. + DCHECK_GE(suspend_all_count_, debug_suspend_all_count_); ++suspend_all_count_; ++debug_suspend_all_count_; // Increment everybody's suspend count (except our own). @@ -757,6 +758,55 @@ void ThreadList::SuspendSelfForDebugger() { VLOG(threads) << *self << " self-reviving (debugger)"; } +void ThreadList::ResumeAllForDebugger() { + Thread* self = Thread::Current(); + Thread* debug_thread = Dbg::GetDebugThread(); + bool needs_resume = false; + + VLOG(threads) << *self << " ResumeAllForDebugger starting..."; + + // Threads can't resume if we exclusively hold the mutator lock. + Locks::mutator_lock_->AssertNotExclusiveHeld(self); + + { + MutexLock mu(self, *Locks::thread_list_lock_); + { + MutexLock 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) { + --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. + LOG(WARNING) << "Debugger attempted to resume all threads without " + << "having suspended them all before."; + } + } + } + + if (needs_resume) { + MutexLock mu(self, *Locks::thread_suspend_count_lock_); + Thread::resume_cond_->Broadcast(self); + } + + VLOG(threads) << *self << " ResumeAllForDebugger complete"; +} + void ThreadList::UndoDebuggerSuspensions() { Thread* self = Thread::Current(); diff --git a/runtime/thread_list.h b/runtime/thread_list.h index 9f47f9f9ef..a7f2c539af 100644 --- a/runtime/thread_list.h +++ b/runtime/thread_list.h @@ -105,6 +105,11 @@ class ThreadList { void SuspendSelfForDebugger() LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_); + // Resume all threads + void ResumeAllForDebugger() + LOCKS_EXCLUDED(Locks::thread_list_lock_, + Locks::thread_suspend_count_lock_); + void UndoDebuggerSuspensions() LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::thread_suspend_count_lock_); |