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();
+    }
 }