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