Merge "Use ScopedObjectAccess in ThreadList::Dump"
diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc
index da21479..80b99fc 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -234,7 +234,12 @@
     os << "DALVIK THREADS (" << list_.size() << "):\n";
   }
   DumpCheckpoint checkpoint(&os, dump_native_stack);
-  size_t threads_running_checkpoint = RunCheckpoint(&checkpoint);
+  size_t threads_running_checkpoint;
+  {
+    // Use SOA to prevent deadlocks if multiple threads are calling Dump() at the same time.
+    ScopedObjectAccess soa(Thread::Current());
+    threads_running_checkpoint = RunCheckpoint(&checkpoint);
+  }
   if (threads_running_checkpoint != 0) {
     checkpoint.WaitForThreadsToRunThroughCheckpoint(threads_running_checkpoint);
   }
diff --git a/test/149-suspend-all-stress/src/Main.java b/test/149-suspend-all-stress/src/Main.java
index 6a27c4b..aa94fc9 100644
--- a/test/149-suspend-all-stress/src/Main.java
+++ b/test/149-suspend-all-stress/src/Main.java
@@ -17,7 +17,7 @@
 import java.util.Map;
 
 public class Main implements Runnable {
-    static final int numberOfThreads = 8;
+    static final int numberOfThreads = 4;
 
     public static void main(String[] args) throws Exception {
         System.loadLibrary(args[0]);
diff --git a/test/149-suspend-all-stress/suspend_all.cc b/test/149-suspend-all-stress/suspend_all.cc
index c22ddad..de479a5 100644
--- a/test/149-suspend-all-stress/suspend_all.cc
+++ b/test/149-suspend-all-stress/suspend_all.cc
@@ -21,11 +21,37 @@
 namespace art {
 
 extern "C" JNIEXPORT void JNICALL Java_Main_suspendAndResume(JNIEnv*, jclass) {
-  usleep(100 * 1000);  // Leave some time for threads to get in here before we start suspending.
-  for (size_t i = 0; i < 500; ++i) {
-    Runtime::Current()->GetThreadList()->SuspendAll(__FUNCTION__);
-    usleep(500);
-    Runtime::Current()->GetThreadList()->ResumeAll();
+  static constexpr size_t kInitialSleepUS = 100 * 1000;  // 100ms.
+  static constexpr size_t kIterations = 500;
+  usleep(kInitialSleepUS);  // Leave some time for threads to get in here before we start suspending.
+  enum Operation {
+    kOPSuspendAll,
+    kOPDumpStack,
+    kOPSuspendAllDumpStack,
+    // Total number of operations.
+    kOPNumber,
+  };
+  for (size_t i = 0; i < kIterations; ++i) {
+    switch (static_cast<Operation>(i % kOPNumber)) {
+      case kOPSuspendAll: {
+        ScopedSuspendAll ssa(__FUNCTION__);
+        usleep(500);
+        break;
+      }
+      case kOPDumpStack: {
+        Runtime::Current()->GetThreadList()->Dump(LOG(INFO));
+        usleep(500);
+        break;
+      }
+      case kOPSuspendAllDumpStack: {
+        // Not yet supported.
+        // ScopedSuspendAll ssa(__FUNCTION__);
+        // Runtime::Current()->GetThreadList()->Dump(LOG(INFO));
+        break;
+      }
+      case kOPNumber:
+        break;
+    }
   }
 }