Lock thread list, show join target
There were some paths to "thread list lock must be held" functions that
weren't locking the thread list. We now do trylock/unlock in dumpFrames
to ensure that doesn't happen.
Also, append "tid=N" to the "waiting on" line in stack trace output
when we're waiting on a VMThread object (i.e. we're in Thread.join()).
Bug 2827015 (for the thread list lock).
Change-Id: I05aa27dd440c671b22ef7cfe47e31dfe54b0ed2d
diff --git a/vm/Thread.c b/vm/Thread.c
index a932889..a98dbd0 100644
--- a/vm/Thread.c
+++ b/vm/Thread.c
@@ -504,6 +504,17 @@
}
/*
+ * Try to lock the thread list.
+ *
+ * Returns "true" if we locked it. This is a "fast" mutex, so if the
+ * current thread holds the lock this will fail.
+ */
+bool dvmTryLockThreadList(void)
+{
+ return (dvmTryLockMutex(&gDvm.threadListLock) == 0);
+}
+
+/*
* Release the thread list global lock.
*/
void dvmUnlockThreadList(void)
diff --git a/vm/Thread.h b/vm/Thread.h
index e336dda..5afeefe 100644
--- a/vm/Thread.h
+++ b/vm/Thread.h
@@ -273,6 +273,8 @@
/* grab the thread list global lock */
void dvmLockThreadList(Thread* self);
+/* try to grab the thread list global lock */
+bool dvmTryLockThreadList(void);
/* release the thread list global lock */
void dvmUnlockThreadList(void);
diff --git a/vm/interp/Stack.c b/vm/interp/Stack.c
index 695aa44..74e6275 100644
--- a/vm/interp/Stack.c
+++ b/vm/interp/Stack.c
@@ -1097,7 +1097,7 @@
*
* The other thread might be alive, so this has to work carefully.
*
- * We assume the thread list lock is currently held.
+ * The thread list lock must be held.
*
* Returns "true" if we successfully recover the object. "*pOwner" will
* be NULL if we can't determine the owner for some reason (e.g. race
@@ -1192,6 +1192,13 @@
bool first = true;
/*
+ * We call functions that require us to be holding the thread list lock.
+ * It's probable that the caller has already done so, but it's not
+ * guaranteed. If it's not locked, lock it now.
+ */
+ bool needThreadUnlock = dvmTryLockThreadList();
+
+ /*
* The "currentPc" is updated whenever we execute an instruction that
* might throw an exception. Show it here.
*/
@@ -1242,9 +1249,19 @@
Monitor* mon = thread->waitMonitor;
Object* obj = dvmGetMonitorObject(mon);
if (obj != NULL) {
+ Thread* joinThread = NULL;
className = dvmDescriptorToDot(obj->clazz->descriptor);
- dvmPrintDebugMessage(target,
- " - waiting on <%p> (a %s)\n", obj, className);
+ if (strcmp(className, "java.lang.VMThread") == 0) {
+ joinThread = dvmGetThreadFromThreadObject(obj);
+ }
+ if (joinThread == NULL) {
+ dvmPrintDebugMessage(target,
+ " - waiting on <%p> (a %s)\n", obj, className);
+ } else {
+ dvmPrintDebugMessage(target,
+ " - waiting on <%p> (a %s) tid=%d\n",
+ obj, className, joinThread->threadId);
+ }
free(className);
}
} else if (thread->status == THREAD_MONITOR) {
@@ -1295,6 +1312,10 @@
}
}
dvmPrintDebugMessage(target, "\n");
+
+ if (needThreadUnlock) {
+ dvmUnlockThreadList();
+ }
}