Generalizing TryLock pattern to ThreadListLocker
Change-Id: Icfe05fac35f72e59bc8d6ec5805020fff3c082d2
diff --git a/src/thread_list.cc b/src/thread_list.cc
index 29a0195..8969868 100644
--- a/src/thread_list.cc
+++ b/src/thread_list.cc
@@ -20,6 +20,29 @@
namespace art {
+// TODO: merge with ThreadListLock?
+class ThreadListLocker {
+ public:
+
+ explicit ThreadListLocker(const ThreadList* thread_list) : thread_list_(thread_list) {
+ // Avoid deadlock between two threads trying to SuspendAll
+ // simultaneously by going to kVmWait if the lock cannot be
+ // immediately acquired.
+ if (!thread_list_->thread_list_lock_.TryLock()) {
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kVmWait);
+ thread_list_->thread_list_lock_.Lock();
+ }
+ }
+
+ ~ThreadListLocker() {
+ thread_list_->thread_list_lock_.Unlock();
+ }
+
+ private:
+ const ThreadList* thread_list_;
+ DISALLOW_COPY_AND_ASSIGN(ThreadListLocker);
+};
+
ThreadList::ThreadList(bool verbose)
: verbose_(verbose),
thread_list_lock_("thread list lock"),
@@ -48,7 +71,7 @@
}
void ThreadList::Dump(std::ostream& os) {
- MutexLock mu(thread_list_lock_);
+ ThreadListLocker locker(this);
os << "DALVIK THREADS (" << list_.size() << "):\n";
for (It it = list_.begin(), end = list_.end(); it != end; ++it) {
(*it)->Dump(os);
@@ -94,13 +117,7 @@
LOG(INFO) << *self << " SuspendAll starting...";
}
- // Avoid deadlock between two threads trying to SuspendAll
- // simultaneously by going to kVmWait if the lock cannot be
- // immediately acquired.
- if (!thread_list_lock_.TryLock()) {
- ScopedThreadStateChange tsc(Thread::Current(), Thread::kVmWait);
- thread_list_lock_.Lock();
- }
+ ThreadListLocker locker(this);
{
// Increment everybody's suspend count (except our own).
@@ -140,8 +157,6 @@
}
}
- thread_list_lock_.Unlock();
-
if (verbose_) {
LOG(INFO) << *self << " SuspendAll complete";
}
@@ -156,7 +171,7 @@
LOG(INFO) << "Suspend(" << *thread << ") starting...";
}
- MutexLock mu(thread_list_lock_);
+ ThreadListLocker locker(this);
if (!Contains(thread)) {
return;
}
@@ -185,8 +200,8 @@
// writes, since nobody should be moving until we decrement the count.
// We do need to hold the thread list because of JNI attaches.
{
- MutexLock mu1(thread_list_lock_);
- MutexLock mu2(thread_suspend_count_lock_);
+ ThreadListLocker locker(this);
+ MutexLock mu(thread_suspend_count_lock_);
for (It it = list_.begin(), end = list_.end(); it != end; ++it) {
Thread* thread = *it;
if (thread != self) {
@@ -222,8 +237,8 @@
}
{
- MutexLock mu1(thread_list_lock_);
- MutexLock mu2(thread_suspend_count_lock_);
+ ThreadListLocker locker(this);
+ MutexLock mu(thread_suspend_count_lock_);
if (!Contains(thread)) {
return;
}
@@ -267,7 +282,7 @@
self->Dump(std::cerr);
}
- MutexLock mu(thread_list_lock_);
+ ThreadListLocker locker(this);
CHECK(!Contains(self));
list_.push_back(self);
}
@@ -283,7 +298,7 @@
// down the Thread* and removing it from the thread list (or start taking any locks).
self->HandleUncaughtExceptions();
- MutexLock mu(thread_list_lock_);
+ ThreadListLocker locker(this);
// Remove this thread from the list.
CHECK(Contains(self));
@@ -303,7 +318,7 @@
}
void ThreadList::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
- MutexLock mu(thread_list_lock_);
+ ThreadListLocker locker(this);
for (It it = list_.begin(), end = list_.end(); it != end; ++it) {
(*it)->VisitRoots(visitor, arg);
}
@@ -325,7 +340,7 @@
CHECK(child != self);
{
- MutexLock mu(thread_list_lock_);
+ ThreadListLocker locker(this);
// We wait for the child to tell us that it's in the thread list.
while (child->GetState() != Thread::kStarting) {
@@ -347,7 +362,7 @@
DCHECK(Contains(self));
{
- MutexLock mu(thread_list_lock_);
+ ThreadListLocker locker(this);
// Tell our parent that we're in the thread list.
self->SetState(Thread::kStarting);
@@ -376,14 +391,14 @@
}
void ThreadList::WaitForNonDaemonThreadsToExit() {
- MutexLock mu(thread_list_lock_);
+ ThreadListLocker locker(this);
while (!AllThreadsAreDaemons()) {
thread_exit_cond_.Wait(thread_list_lock_);
}
}
void ThreadList::SuspendAllDaemonThreads() {
- MutexLock mu(thread_list_lock_);
+ ThreadListLocker locker(this);
// Tell all the daemons it's time to suspend. (At this point, we know
// all threads are daemons.)
@@ -417,7 +432,7 @@
}
uint32_t ThreadList::AllocThreadId() {
- MutexLock mu(thread_list_lock_);
+ ThreadListLocker locker(this);
for (size_t i = 0; i < allocated_ids_.size(); ++i) {
if (!allocated_ids_[i]) {
allocated_ids_.set(i);