Fix a deadlock between thread flip and suspend request.
See 31683379#9 for the deadlock scenario.
Make ModifySuspendCount(+1) retry if the thread flip function is set.
Bug: 31683379
Bug: 12687968
Test: test-art, N9 libartd boot, Ritz EAAC with CC.
Test: 129-GetThreadId with gcstress and CC.
Change-Id: Id5cdfcd90a08a2ff497f9f0e2842fa4c613549bc
diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc
index 17c6c2e..21ecb15 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -584,24 +584,7 @@
continue;
}
VLOG(threads) << "requesting thread suspend: " << *thread;
- while (true) {
- if (LIKELY(thread->ModifySuspendCount(self, +1, &pending_threads, debug_suspend))) {
- break;
- } else {
- // Failure means the list of active_suspend_barriers is full, we should release the
- // thread_suspend_count_lock_ (to avoid deadlock) and wait till the target thread has
- // executed Thread::PassActiveSuspendBarriers(). Note that we could not simply wait for
- // the thread to change to a suspended state, because it might need to run checkpoint
- // function before the state change, which also needs thread_suspend_count_lock_.
-
- // This is very unlikely to happen since more than kMaxSuspendBarriers threads need to
- // execute SuspendAllInternal() simultaneously, and target thread stays in kRunnable
- // in the mean time.
- Locks::thread_suspend_count_lock_->ExclusiveUnlock(self);
- NanoSleep(100000);
- Locks::thread_suspend_count_lock_->ExclusiveLock(self);
- }
- }
+ thread->ModifySuspendCount(self, +1, &pending_threads, debug_suspend);
// Must install the pending_threads counter first, then check thread->IsSuspend() and clear
// the counter. Otherwise there's a race with Thread::TransitionFromRunnableToSuspended()