libcorkscrew native stacks, mutex ranking, and better ScopedThreadListLock.

This change uses libcorkscrew to show native stacks for threads in kNative or,
unlike dalvikvm, kVmWait --- working on the runtime directly I've found it
somewhat useful to be able to see _which_ internal resource we're waiting on.
We can always take that back out (or make it oatexecd-only) if it turns out to
be too noisy/confusing for app developers.

This change also lets us rank mutexes and enforce -- in oatexecd -- that you
take locks in a specific order.

Both of these helped me test the third novelty: removing the heap locking from
ScopedThreadListLock. I've manually inspected all the callers and added a
ScopedHeapLock where I think one is necessary. In manual testing, this makes
jdb a lot less prone to locking us up. There still seems to be a problem with
the JDWP VirtualMachine.Resume command, but I'll look at that separately. This
is a big enough and potentially disruptive enough change already.

Change-Id: Iad974358919d0e00674662dc8a69cc65878cfb5c
diff --git a/src/mutex.cc b/src/mutex.cc
index 5d207f6..963ac99 100644
--- a/src/mutex.cc
+++ b/src/mutex.cc
@@ -18,16 +18,28 @@
 
 #include <errno.h>
 
-#include "heap.h" // for VERIFY_OBJECT_ENABLED
 #include "logging.h"
-#include "utils.h"
 #include "runtime.h"
+#include "thread.h"
+#include "utils.h"
 
 #define CHECK_MUTEX_CALL(call, args) CHECK_PTHREAD_CALL(call, args, name_)
 
 namespace art {
 
-Mutex::Mutex(const char* name) : name_(name) {
+static inline void CheckRank(MutexRank rank, bool is_locking) {
+#ifndef NDEBUG
+  if (rank == -1) {
+    return;
+  }
+  Thread* self = Thread::Current();
+  if (self != NULL) {
+    self->CheckRank(rank, is_locking);
+  }
+#endif
+}
+
+Mutex::Mutex(const char* name, MutexRank rank) : name_(name), rank_(rank) {
   // Like Java, we use recursive mutexes.
   pthread_mutexattr_t attributes;
   CHECK_MUTEX_CALL(pthread_mutexattr_init, (&attributes));
@@ -47,6 +59,7 @@
 
 void Mutex::Lock() {
   CHECK_MUTEX_CALL(pthread_mutex_lock, (&mutex_));
+  CheckRank(rank_, true);
   AssertHeld();
 }
 
@@ -59,6 +72,7 @@
     errno = result;
     PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
   }
+  CheckRank(rank_, true);
   AssertHeld();
   return true;
 }
@@ -66,6 +80,7 @@
 void Mutex::Unlock() {
   AssertHeld();
   CHECK_MUTEX_CALL(pthread_mutex_unlock, (&mutex_));
+  CheckRank(rank_, false);
 }
 
 pid_t Mutex::GetOwner() {
@@ -152,4 +167,14 @@
   }
 }
 
+std::ostream& operator<<(std::ostream& os, const MutexRank& rhs) {
+  switch (rhs) {
+    case kHeapLock: os << "HeapLock"; break;
+    case kThreadListLock: os << "ThreadListLock"; break;
+    case kThreadSuspendCountLock: os << "ThreadSuspendCountLock"; break;
+    default: os << "MutexRank[" << static_cast<int>(rhs) << "]"; break;
+  }
+  return os;
+}
+
 }  // namespace