ART: Add Monitor::FetchState
Add a function returning descriptive state for a monitor. The
function will return the thread state, and possible the object
the thread is blocked/waiting/sleeping on, as well as the lock
owner's tid.
Rewrite DescribeWait to use this.
In preparation for new uses.
Bug: 70538431
Test: m
Change-Id: I79d0104ad04dec633522d4127542184a0cbdf95c
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index 1252905..ba18f8d 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -1291,60 +1291,111 @@
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) {
- if (pretty_object == nullptr) {
- os << wait_message << "an unknown object";
+ if (wait_message == nullptr) {
+ return;
+ }
+
+ 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) {