diff options
-rw-r--r-- | runtime/monitor.cc | 143 | ||||
-rw-r--r-- | runtime/monitor.h | 5 |
2 files changed, 102 insertions, 46 deletions
diff --git a/runtime/monitor.cc b/runtime/monitor.cc index 12529058e2..ba18f8ddd4 100644 --- a/runtime/monitor.cc +++ b/runtime/monitor.cc @@ -1291,60 +1291,111 @@ uint32_t Monitor::GetLockOwnerThreadId(mirror::Object* obj) { void Monitor::DescribeWait(std::ostream& os, const Thread* thread) { // Determine the wait message and object we're waiting or blocked upon. - mirror::Object* pretty_object = nullptr; + mirror::Object* pretty_object; + uint32_t lock_owner; + ThreadState state = FetchState(thread, &pretty_object, &lock_owner); + const char* wait_message = nullptr; - uint32_t lock_owner = ThreadList::kInvalidThreadId; - ThreadState state = thread->GetState(); - if (state == kWaiting || state == kTimedWaiting || state == kSleeping) { - wait_message = (state == kSleeping) ? " - sleeping on " : " - waiting on "; - Thread* self = Thread::Current(); - MutexLock mu(self, *thread->GetWaitMutex()); - Monitor* monitor = thread->GetWaitMonitor(); - if (monitor != nullptr) { - pretty_object = monitor->GetObject(); - } - } else if (state == kBlocked || state == kWaitingForLockInflation) { - wait_message = (state == kBlocked) ? " - waiting to lock " - : " - waiting for lock inflation of "; - pretty_object = thread->GetMonitorEnterObject(); - if (pretty_object != nullptr) { - if (kUseReadBarrier && Thread::Current()->GetIsGcMarking()) { - // We may call Thread::Dump() in the middle of the CC thread flip and this thread's stack - // may have not been flipped yet and "pretty_object" may be a from-space (stale) ref, in - // which case the GetLockOwnerThreadId() call below will crash. So explicitly mark/forward - // it here. - pretty_object = ReadBarrier::Mark(pretty_object); - } - lock_owner = pretty_object->GetLockOwnerThreadId(); - } + switch (state) { + case kWaiting: + case kTimedWaiting: + wait_message = " - waiting on "; + break; + + case kSleeping: + wait_message = " - sleeping on "; + break; + + case kBlocked: + wait_message = " - waiting to lock "; + break; + + case kWaitingForLockInflation: + wait_message = " - waiting for lock inflation of "; + break; + + default: + break; + } + + if (wait_message == nullptr) { + return; } - if (wait_message != nullptr) { - if (pretty_object == nullptr) { - os << wait_message << "an unknown object"; + if (pretty_object == nullptr) { + os << wait_message << "an unknown object"; + } else { + if ((pretty_object->GetLockWord(true).GetState() == LockWord::kThinLocked) && + Locks::mutator_lock_->IsExclusiveHeld(Thread::Current())) { + // Getting the identity hashcode here would result in lock inflation and suspension of the + // current thread, which isn't safe if this is the only runnable thread. + os << wait_message << StringPrintf("<@addr=0x%" PRIxPTR "> (a %s)", + reinterpret_cast<intptr_t>(pretty_object), + pretty_object->PrettyTypeOf().c_str()); } else { - if ((pretty_object->GetLockWord(true).GetState() == LockWord::kThinLocked) && - Locks::mutator_lock_->IsExclusiveHeld(Thread::Current())) { - // Getting the identity hashcode here would result in lock inflation and suspension of the - // current thread, which isn't safe if this is the only runnable thread. - os << wait_message << StringPrintf("<@addr=0x%" PRIxPTR "> (a %s)", - reinterpret_cast<intptr_t>(pretty_object), - pretty_object->PrettyTypeOf().c_str()); - } else { - // - waiting on <0x6008c468> (a java.lang.Class<java.lang.ref.ReferenceQueue>) - // Call PrettyTypeOf before IdentityHashCode since IdentityHashCode can cause thread - // suspension and move pretty_object. - const std::string pretty_type(pretty_object->PrettyTypeOf()); - os << wait_message << StringPrintf("<0x%08x> (a %s)", pretty_object->IdentityHashCode(), - pretty_type.c_str()); + // - waiting on <0x6008c468> (a java.lang.Class<java.lang.ref.ReferenceQueue>) + // Call PrettyTypeOf before IdentityHashCode since IdentityHashCode can cause thread + // suspension and move pretty_object. + const std::string pretty_type(pretty_object->PrettyTypeOf()); + os << wait_message << StringPrintf("<0x%08x> (a %s)", pretty_object->IdentityHashCode(), + pretty_type.c_str()); + } + } + // - waiting to lock <0x613f83d8> (a java.lang.Object) held by thread 5 + if (lock_owner != ThreadList::kInvalidThreadId) { + os << " held by thread " << lock_owner; + } + os << "\n"; +} + +ThreadState Monitor::FetchState(const Thread* thread, + /* out */ mirror::Object** monitor_object, + /* out */ uint32_t* lock_owner_tid) { + DCHECK(monitor_object != nullptr); + DCHECK(lock_owner_tid != nullptr); + + *monitor_object = nullptr; + *lock_owner_tid = ThreadList::kInvalidThreadId; + + ThreadState state = thread->GetState(); + + switch (state) { + case kWaiting: + case kTimedWaiting: + case kSleeping: + { + Thread* self = Thread::Current(); + MutexLock mu(self, *thread->GetWaitMutex()); + Monitor* monitor = thread->GetWaitMonitor(); + if (monitor != nullptr) { + *monitor_object = monitor->GetObject(); } } - // - waiting to lock <0x613f83d8> (a java.lang.Object) held by thread 5 - if (lock_owner != ThreadList::kInvalidThreadId) { - os << " held by thread " << lock_owner; + break; + + case kBlocked: + case kWaitingForLockInflation: + { + mirror::Object* lock_object = thread->GetMonitorEnterObject(); + if (lock_object != nullptr) { + if (kUseReadBarrier && Thread::Current()->GetIsGcMarking()) { + // We may call Thread::Dump() in the middle of the CC thread flip and this thread's stack + // may have not been flipped yet and "pretty_object" may be a from-space (stale) ref, in + // which case the GetLockOwnerThreadId() call below will crash. So explicitly mark/forward + // it here. + lock_object = ReadBarrier::Mark(lock_object); + } + *monitor_object = lock_object; + *lock_owner_tid = lock_object->GetLockOwnerThreadId(); + } } - os << "\n"; + break; + + default: + break; } + + return state; } mirror::Object* Monitor::GetContendedMonitor(Thread* thread) { diff --git a/runtime/monitor.h b/runtime/monitor.h index b4c0e6f471..30f47d849f 100644 --- a/runtime/monitor.h +++ b/runtime/monitor.h @@ -97,6 +97,11 @@ class Monitor { static void DescribeWait(std::ostream& os, const Thread* thread) REQUIRES(!Locks::thread_suspend_count_lock_) REQUIRES_SHARED(Locks::mutator_lock_); + static ThreadState FetchState(const Thread* thread, + /* out */ mirror::Object** monitor_object, + /* out */ uint32_t* lock_owner_tid) + REQUIRES(!Locks::thread_suspend_count_lock_) + REQUIRES_SHARED(Locks::mutator_lock_); // Used to implement JDWP's ThreadReference.CurrentContendedMonitor. static mirror::Object* GetContendedMonitor(Thread* thread) |