Pass self to lock methods.
This avoids frequent recomputation of
Thread::Current/pthread_getspecific.
Also add a futex based reader/writer mutex that is disabled.
Change-Id: I118fdb99ef1d1c4bfda6446ba3a0d8b6ab31eaee
diff --git a/src/thread_list.cc b/src/thread_list.cc
index 550d5c7..082d7af 100644
--- a/src/thread_list.cc
+++ b/src/thread_list.cc
@@ -128,18 +128,18 @@
#if HAVE_TIMED_RWLOCK
// Attempt to rectify locks so that we dump thread list with required locks before exiting.
-static void UnsafeLogFatalForThreadSuspendAllTimeout() NO_THREAD_SAFETY_ANALYSIS {
+static void UnsafeLogFatalForThreadSuspendAllTimeout(Thread* self) NO_THREAD_SAFETY_ANALYSIS {
Runtime* runtime = Runtime::Current();
std::ostringstream ss;
ss << "Thread suspend timeout\n";
runtime->DumpLockHolders(ss);
ss << "\n";
- Locks::mutator_lock_->SharedTryLock();
- if (!Locks::mutator_lock_->IsSharedHeld()) {
+ Locks::mutator_lock_->SharedTryLock(self);
+ if (!Locks::mutator_lock_->IsSharedHeld(self)) {
LOG(WARNING) << "Dumping thread list without holding mutator_lock_";
}
- Locks::thread_list_lock_->TryLock();
- if (!Locks::thread_list_lock_->IsExclusiveHeld()) {
+ Locks::thread_list_lock_->TryLock(self);
+ if (!Locks::thread_list_lock_->IsExclusiveHeld(self)) {
LOG(WARNING) << "Dumping thread list without holding thread_list_lock_";
}
runtime->GetThreadList()->DumpLocked(ss);
@@ -153,16 +153,15 @@
VLOG(threads) << *self << " SuspendAll starting...";
if (kIsDebugBuild) {
- Locks::mutator_lock_->AssertNotHeld();
- Locks::thread_list_lock_->AssertNotHeld();
- Locks::thread_suspend_count_lock_->AssertNotHeld();
- MutexLock mu(*Locks::thread_suspend_count_lock_);
+ Locks::mutator_lock_->AssertNotHeld(self);
+ Locks::thread_list_lock_->AssertNotHeld(self);
+ Locks::thread_suspend_count_lock_->AssertNotHeld(self);
CHECK_NE(self->GetState(), kRunnable);
}
{
- MutexLock mu(*Locks::thread_list_lock_);
+ MutexLock mu(self, *Locks::thread_list_lock_);
{
- MutexLock mu2(*Locks::thread_suspend_count_lock_);
+ MutexLock mu2(self, *Locks::thread_suspend_count_lock_);
// Update global suspend all state for attaching threads.
++suspend_all_count_;
// Increment everybody's suspend count (except our own).
@@ -183,11 +182,11 @@
timespec timeout;
clock_gettime(CLOCK_REALTIME, &timeout);
timeout.tv_sec += 30;
- if (UNLIKELY(!Locks::mutator_lock_->ExclusiveLockWithTimeout(timeout))) {
- UnsafeLogFatalForThreadSuspendAllTimeout();
+ if (UNLIKELY(!Locks::mutator_lock_->ExclusiveLockWithTimeout(self, timeout))) {
+ UnsafeLogFatalForThreadSuspendAllTimeout(self);
}
#else
- Locks::mutator_lock_->ExclusiveLock();
+ Locks::mutator_lock_->ExclusiveLock(self);
#endif
// Debug check that all threads are suspended.
@@ -200,9 +199,10 @@
Thread* self = Thread::Current();
VLOG(threads) << *self << " ResumeAll starting";
+ Locks::mutator_lock_->ExclusiveUnlock(self);
{
- MutexLock mu(*Locks::thread_list_lock_);
- MutexLock mu2(*Locks::thread_suspend_count_lock_);
+ MutexLock mu(self, *Locks::thread_list_lock_);
+ MutexLock mu2(self, *Locks::thread_suspend_count_lock_);
// Update global suspend all state for attaching threads.
--suspend_all_count_;
// Decrement the suspend counts for all threads.
@@ -219,20 +219,20 @@
VLOG(threads) << *self << " ResumeAll waking others";
Thread::resume_cond_->Broadcast();
}
- Locks::mutator_lock_->ExclusiveUnlock();
VLOG(threads) << *self << " ResumeAll complete";
}
void ThreadList::Resume(Thread* thread, bool for_debugger) {
- DCHECK(thread != Thread::Current());
+ Thread* self = Thread::Current();
+ DCHECK_NE(thread, self);
VLOG(threads) << "Resume(" << *thread << ") starting..." << (for_debugger ? " (debugger)" : "");
{
// To check Contains.
- MutexLock mu(*Locks::thread_list_lock_);
+ MutexLock mu(self, *Locks::thread_list_lock_);
// To check IsSuspended.
- MutexLock mu2(*Locks::thread_suspend_count_lock_);
- CHECK(thread->IsSuspended());
+ MutexLock mu2(self, *Locks::thread_suspend_count_lock_);
+ DCHECK(thread->IsSuspended());
if (!Contains(thread)) {
return;
}
@@ -241,7 +241,7 @@
{
VLOG(threads) << "Resume(" << *thread << ") waking others";
- MutexLock mu(*Locks::thread_suspend_count_lock_);
+ MutexLock mu(self, *Locks::thread_suspend_count_lock_);
Thread::resume_cond_->Broadcast();
}
@@ -255,9 +255,9 @@
VLOG(threads) << *self << " SuspendAllForDebugger starting...";
{
- MutexLock mu(*Locks::thread_list_lock_);
+ MutexLock mu(self, *Locks::thread_list_lock_);
{
- MutexLock mu(*Locks::thread_suspend_count_lock_);
+ MutexLock mu(self, *Locks::thread_suspend_count_lock_);
// Update global suspend all state for attaching threads.
++suspend_all_count_;
++debug_suspend_all_count_;
@@ -280,14 +280,14 @@
timespec timeout;
clock_gettime(CLOCK_REALTIME, &timeout);
timeout.tv_sec += 30;
- if (!Locks::mutator_lock_->ExclusiveLockWithTimeout(timeout)) {
- UnsafeLogFatalForThreadSuspendAllTimeout();
+ if (!Locks::mutator_lock_->ExclusiveLockWithTimeout(self, timeout)) {
+ UnsafeLogFatalForThreadSuspendAllTimeout(self);
} else {
- Locks::mutator_lock_->ExclusiveUnlock();
+ Locks::mutator_lock_->ExclusiveUnlock(self);
}
#else
- Locks::mutator_lock_->ExclusiveLock();
- Locks::mutator_lock_->ExclusiveUnlock();
+ Locks::mutator_lock_->ExclusiveLock(self);
+ Locks::mutator_lock_->ExclusiveUnlock(self);
#endif
AssertThreadsAreSuspended();
@@ -305,7 +305,7 @@
// Collisions with other suspends aren't really interesting. We want
// to ensure that we're the only one fiddling with the suspend count
// though.
- MutexLock mu(*Locks::thread_suspend_count_lock_);
+ MutexLock mu(self, *Locks::thread_suspend_count_lock_);
self->ModifySuspendCount(+1, true);
// Suspend ourselves.
@@ -319,7 +319,7 @@
Dbg::ClearWaitForEventThread();
while (self->suspend_count_ != 0) {
- Thread::resume_cond_->Wait(*Locks::thread_suspend_count_lock_);
+ Thread::resume_cond_->Wait(self, *Locks::thread_suspend_count_lock_);
if (self->suspend_count_ != 0) {
// The condition was signaled but we're still suspended. This
// can happen if the debugger lets go while a SIGQUIT thread
@@ -340,8 +340,8 @@
VLOG(threads) << *self << " UndoDebuggerSuspensions starting";
{
- MutexLock mu(*Locks::thread_list_lock_);
- MutexLock mu2(*Locks::thread_suspend_count_lock_);
+ MutexLock mu(self, *Locks::thread_list_lock_);
+ MutexLock mu2(self, *Locks::thread_suspend_count_lock_);
// Update global suspend all state for attaching threads.
suspend_all_count_ -= debug_suspend_all_count_;
debug_suspend_all_count_ = 0;
@@ -356,7 +356,7 @@
}
{
- MutexLock mu(*Locks::thread_suspend_count_lock_);
+ MutexLock mu(self, *Locks::thread_suspend_count_lock_);
Thread::resume_cond_->Broadcast();
}
@@ -364,8 +364,9 @@
}
void ThreadList::WaitForOtherNonDaemonThreadsToExit() {
- Locks::mutator_lock_->AssertNotHeld();
- MutexLock mu(*Locks::thread_list_lock_);
+ Thread* self = Thread::Current();
+ Locks::mutator_lock_->AssertNotHeld(self);
+ MutexLock mu(self, *Locks::thread_list_lock_);
bool all_threads_are_daemons;
do {
all_threads_are_daemons = true;
@@ -373,28 +374,29 @@
// TODO: there's a race here with thread exit that's being worked around by checking if the
// thread has a peer.
Thread* thread = *it;
- if (thread != Thread::Current() && thread->HasPeer() && !thread->IsDaemon()) {
+ if (thread != self && thread->HasPeer() && !thread->IsDaemon()) {
all_threads_are_daemons = false;
break;
}
}
if (!all_threads_are_daemons) {
// Wait for another thread to exit before re-checking.
- thread_exit_cond_.Wait(*Locks::thread_list_lock_);
+ thread_exit_cond_.Wait(self, *Locks::thread_list_lock_);
}
} while(!all_threads_are_daemons);
}
void ThreadList::SuspendAllDaemonThreads() {
- MutexLock mu(*Locks::thread_list_lock_);
+ Thread* self = Thread::Current();
+ MutexLock mu(self, *Locks::thread_list_lock_);
{ // Tell all the daemons it's time to suspend.
- MutexLock mu2(*Locks::thread_suspend_count_lock_);
+ MutexLock mu2(self, *Locks::thread_suspend_count_lock_);
for (It it = list_.begin(), end = list_.end(); it != end; ++it) {
Thread* thread = *it;
// This is only run after all non-daemon threads have exited, so the remainder should all be
// daemons.
CHECK(thread->IsDaemon());
- if (thread != Thread::Current()) {
+ if (thread != self) {
thread->ModifySuspendCount(+1, false);
}
}
@@ -406,8 +408,8 @@
bool all_suspended = true;
for (It it = list_.begin(), end = list_.end(); it != end; ++it) {
Thread* thread = *it;
- MutexLock mu2(*Locks::thread_suspend_count_lock_);
- if (thread != Thread::Current() && thread->GetState() == kRunnable) {
+ MutexLock mu2(self, *Locks::thread_suspend_count_lock_);
+ if (thread != self && thread->GetState() == kRunnable) {
if (!have_complained) {
LOG(WARNING) << "daemon thread not yet suspended: " << *thread;
have_complained = true;
@@ -432,8 +434,8 @@
// Atomically add self to the thread list and make its thread_suspend_count_ reflect ongoing
// SuspendAll requests.
- MutexLock mu(*Locks::thread_list_lock_);
- MutexLock mu2(*Locks::thread_suspend_count_lock_);
+ MutexLock mu(self, *Locks::thread_list_lock_);
+ MutexLock mu2(self, *Locks::thread_suspend_count_lock_);
self->suspend_count_ = suspend_all_count_;
self->debug_suspend_count_ = debug_suspend_all_count_;
CHECK(!Contains(self));
@@ -451,7 +453,7 @@
{
// Remove this thread from the list.
- MutexLock mu(*Locks::thread_list_lock_);
+ MutexLock mu(self, *Locks::thread_list_lock_);
CHECK(Contains(self));
list_.remove(self);
}
@@ -466,7 +468,7 @@
CHECK_PTHREAD_CALL(pthread_setspecific, (Thread::pthread_key_self_, NULL), "detach self");
// Signal that a thread just detached.
- MutexLock mu(*Locks::thread_list_lock_);
+ MutexLock mu(NULL, *Locks::thread_list_lock_);
thread_exit_cond_.Signal();
}
@@ -477,14 +479,14 @@
}
void ThreadList::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
- MutexLock mu(*Locks::thread_list_lock_);
+ MutexLock mu(Thread::Current(), *Locks::thread_list_lock_);
for (It it = list_.begin(), end = list_.end(); it != end; ++it) {
(*it)->VisitRoots(visitor, arg);
}
}
uint32_t ThreadList::AllocThreadId() {
- MutexLock mu(allocated_ids_lock_);
+ MutexLock mu(Thread::Current(), allocated_ids_lock_);
for (size_t i = 0; i < allocated_ids_.size(); ++i) {
if (!allocated_ids_[i]) {
allocated_ids_.set(i);
@@ -496,7 +498,7 @@
}
void ThreadList::ReleaseThreadId(uint32_t id) {
- MutexLock mu(allocated_ids_lock_);
+ MutexLock mu(Thread::Current(), allocated_ids_lock_);
--id; // Zero is reserved to mean "invalid".
DCHECK(allocated_ids_[id]) << id;
allocated_ids_.reset(id);