Merge "Restore "CFG rework for explicit exception edges"" into dalvik-dev
diff --git a/src/mutex.cc b/src/mutex.cc
index 182f6f0..18c94535 100644
--- a/src/mutex.cc
+++ b/src/mutex.cc
@@ -267,7 +267,7 @@
 #elif defined(__GLIBC__)
   return reinterpret_cast<const glibc_pthread_mutex_t*>(&mutex_)->owner;
 #elif defined(__APPLE__)
-  return reinterpret_cast<darwin_pthread_mutex_t*>(&mutex_)->owner_tid;
+  return reinterpret_cast<const darwin_pthread_mutex_t*>(&mutex_)->owner_tid;
 #else
 #error unsupported C library
 #endif
@@ -302,6 +302,7 @@
   CHECK_MUTEX_CALL(pthread_rwlock_unlock, (&rwlock_));
 }
 
+#if HAVE_TIMED_RWLOCK
 bool ReaderWriterMutex::ExclusiveLockWithTimeout(const timespec& abs_timeout) {
   int result = pthread_rwlock_timedwrlock(&rwlock_, &abs_timeout);
   if (result == ETIMEDOUT) {
@@ -309,12 +310,13 @@
   }
   if (result != 0) {
     errno = result;
-    PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
+    PLOG(FATAL) << "pthread_rwlock_timedwrlock failed for " << name_;
   }
   RegisterAsLockedWithCurrentThread();
   AssertSharedHeld();
   return true;
 }
+#endif
 
 void ReaderWriterMutex::SharedLock() {
   CHECK_MUTEX_CALL(pthread_rwlock_rdlock, (&rwlock_));
diff --git a/src/mutex.h b/src/mutex.h
index 4899382..edd458d 100644
--- a/src/mutex.h
+++ b/src/mutex.h
@@ -28,6 +28,13 @@
 #include "logging.h"
 #include "macros.h"
 
+// Currently Darwin doesn't support locks with timeouts.
+#if !defined(__APPLE__)
+#define HAVE_TIMED_RWLOCK 1
+#else
+#define HAVE_TIMED_RWLOCK 0
+#endif
+
 namespace art {
 
 class LOCKABLE Mutex;
@@ -271,7 +278,9 @@
 
   // Block until ReaderWriterMutex is free and acquire exclusive access. Returns true on success
   // or false if timeout is reached.
+#if HAVE_TIMED_RWLOCK
   bool ExclusiveLockWithTimeout(const timespec& abs_timeout) EXCLUSIVE_TRYLOCK_FUNCTION(true);
+#endif
 
   // Block until ReaderWriterMutex is shared or free then acquire a share on the access.
   void SharedLock() SHARED_LOCK_FUNCTION();
diff --git a/src/thread_list.cc b/src/thread_list.cc
index 0bd587c..6008e16 100644
--- a/src/thread_list.cc
+++ b/src/thread_list.cc
@@ -21,6 +21,7 @@
 #include <unistd.h>
 
 #include "debugger.h"
+#include "mutex.h"
 #include "timing_logger.h"
 #include "utils.h"
 
@@ -125,6 +126,7 @@
   }
 }
 
+#if HAVE_TIMED_RWLOCK
 // Attempt to rectify locks so that we dump thread list with required locks before exiting.
 static void UnsafeLogFatalForThreadSuspendAllTimeout() NO_THREAD_SAFETY_ANALYSIS {
   Runtime* runtime = Runtime::Current();
@@ -143,6 +145,7 @@
   runtime->GetThreadList()->DumpLocked(ss);
   LOG(FATAL) << ss.str();
 }
+#endif
 
 void ThreadList::SuspendAll() {
   Thread* self = Thread::Current();
@@ -174,14 +177,18 @@
     }
   }
 
-  // Block on the mutator lock until all Runnable threads release their share of access. Timeout
-  // if we wait more than 30 seconds.
+  // Block on the mutator lock until all Runnable threads release their share of access.
+#if HAVE_TIMED_RWLOCK
+  // Timeout if we wait more than 30 seconds.
   timespec timeout;
   clock_gettime(CLOCK_REALTIME, &timeout);
   timeout.tv_sec += 30;
   if (UNLIKELY(!GlobalSynchronization::mutator_lock_->ExclusiveLockWithTimeout(timeout))) {
     UnsafeLogFatalForThreadSuspendAllTimeout();
   }
+#else
+  GlobalSynchronization::mutator_lock_->ExclusiveLock();
+#endif
 
   // Debug check that all threads are suspended.
   AssertThreadsAreSuspended();
@@ -266,18 +273,22 @@
     }
   }
 
-  // Block on the mutator lock until all Runnable threads release their share of access. Timeout
-  // if we wait more than 30 seconds.
+  // Block on the mutator lock until all Runnable threads release their share of access then
+  // immediately unlock again.
+#if HAVE_TIMED_RWLOCK
+  // Timeout if we wait more than 30 seconds.
   timespec timeout;
   clock_gettime(CLOCK_REALTIME, &timeout);
   timeout.tv_sec += 30;
   if (!GlobalSynchronization::mutator_lock_->ExclusiveLockWithTimeout(timeout)) {
     UnsafeLogFatalForThreadSuspendAllTimeout();
   } else {
-    // Debugger suspends all threads but doesn't hold onto the mutator_lock_.
     GlobalSynchronization::mutator_lock_->ExclusiveUnlock();
   }
-
+#else
+  GlobalSynchronization::mutator_lock_->ExclusiveLock();
+  GlobalSynchronization::mutator_lock_->ExclusiveUnlock();
+#endif
   AssertThreadsAreSuspended();
 
   VLOG(threads) << *self << " SuspendAll complete";