summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Sebastien Hertz <shertz@google.com> 2014-10-28 20:30:40 +0000
committer Android Git Automerger <android-git-automerger@android.com> 2014-10-28 20:30:40 +0000
commit1e3926e286b72f53afc84d2e0932ebb7b35a4038 (patch)
treee2696077ae7fff5fc288df561c06a51629ad643d
parentadcd83ffb74c6776aab826d6de76fe4aa237db08 (diff)
parenta6e599a8838b7d8098cba12301422e0fb6296753 (diff)
am a6e599a8: Merge "Fix JDWP Virtualmachine.Resume command" into lmp-mr1-dev
* commit 'a6e599a8838b7d8098cba12301422e0fb6296753': Fix JDWP Virtualmachine.Resume command
-rw-r--r--runtime/debugger.cc2
-rw-r--r--runtime/debugger.h8
-rw-r--r--runtime/thread_list.cc50
-rw-r--r--runtime/thread_list.h5
4 files changed, 62 insertions, 3 deletions
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index b676c62ee1..1dd68eff2a 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -2386,7 +2386,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 646830acc6..03afd11558 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -662,6 +662,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).
@@ -753,6 +754,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_);