Change state to waiting during aborting the VM

Symptom:
Process freeze when multiple runtime error happen on runnable threads.

Root cause:
When multiple runtime error happen, only one thread locks abort_lock_
and other threads are blocked even if they are runnable state.
If an other thread tries to suspend blocked threads at the same time,
blocked threads can't be suspended until abort_lock_ is unlocked from
owner thread. But owner thread can be suspended even if it locks
abort_lock_. Thus, these threads causes dead lock.

Solution:
Change state to waiting when locking abort_lock_.

Bug: 127875380
Change-Id: I7e914924690bb30d6d0490cf5f8afdb1c3cd4e4a
diff --git a/openjdkjvmti/ti_monitor.cc b/openjdkjvmti/ti_monitor.cc
index aac7233..2ca5057 100644
--- a/openjdkjvmti/ti_monitor.cc
+++ b/openjdkjvmti/ti_monitor.cc
@@ -403,6 +403,7 @@
         case art::kWaitingForGetObjectsAllocated:
         case art::kWaitingWeakGcRootRead:
         case art::kWaitingForGcThreadFlip:
+        case art::kNativeForAbort:
         case art::kStarting:
         case art::kNative:
         case art::kSuspended: {
diff --git a/openjdkjvmti/ti_thread.cc b/openjdkjvmti/ti_thread.cc
index c6798bb..01cc8c7 100644
--- a/openjdkjvmti/ti_thread.cc
+++ b/openjdkjvmti/ti_thread.cc
@@ -453,6 +453,7 @@
     case art::ThreadState::kWaitingForVisitObjects:
     case art::ThreadState::kWaitingForGetObjectsAllocated:
     case art::ThreadState::kWaitingForGcThreadFlip:
+    case art::ThreadState::kNativeForAbort:
       // All of these are causing the thread to wait for an indeterminate amount of time but isn't
       // caused by sleep, park, or object#wait.
       jvmti_state |= (JVMTI_THREAD_STATE_WAITING |
@@ -508,6 +509,7 @@
     case art::ThreadState::kWaitingForMethodTracingStart:
     case art::ThreadState::kWaitingForVisitObjects:
     case art::ThreadState::kWaitingForGcThreadFlip:
+    case art::ThreadState::kNativeForAbort:
       return JVMTI_JAVA_LANG_THREAD_STATE_WAITING;
   }
   LOG(FATAL) << "Unreachable";
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 663af81..d3a3eea 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -2261,6 +2261,7 @@
     case kWaitingPerformingGc:
     case kWaitingWeakGcRootRead:
     case kWaitingForGcThreadFlip:
+    case kNativeForAbort:
     case kWaiting:
       return JDWP::TS_WAIT;
       // Don't add a 'default' here so the compiler can spot incompatible enum changes.
diff --git a/runtime/native/java_lang_Thread.cc b/runtime/native/java_lang_Thread.cc
index 67ad0a4..37b3fe6 100644
--- a/runtime/native/java_lang_Thread.cc
+++ b/runtime/native/java_lang_Thread.cc
@@ -104,6 +104,7 @@
     case kWaitingForVisitObjects:         return kJavaWaiting;
     case kWaitingWeakGcRootRead:          return kJavaRunnable;
     case kWaitingForGcThreadFlip:         return kJavaWaiting;
+    case kNativeForAbort:                 return kJavaWaiting;
     case kSuspended:                      return kJavaRunnable;
     // Don't add a 'default' here so the compiler can spot incompatible enum changes.
   }
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index d698d48..4565939 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -584,9 +584,12 @@
 #endif
   }
 
-  // Ensure that we don't have multiple threads trying to abort at once,
-  // which would result in significantly worse diagnostics.
-  MutexLock mu(Thread::Current(), *Locks::abort_lock_);
+  {
+    // Ensure that we don't have multiple threads trying to abort at once,
+    // which would result in significantly worse diagnostics.
+    ScopedThreadStateChange tsc(Thread::Current(), kNativeForAbort);
+    Locks::abort_lock_->ExclusiveLock(Thread::Current());
+  }
 
   // Get any pending output out of the way.
   fflush(nullptr);
diff --git a/runtime/thread_state.h b/runtime/thread_state.h
index e57a040..c8f3826 100644
--- a/runtime/thread_state.h
+++ b/runtime/thread_state.h
@@ -47,6 +47,7 @@
   kWaitingForGetObjectsAllocated,   // WAITING        TS_WAIT      waiting for getting the number of allocated objects
   kWaitingWeakGcRootRead,           // WAITING        TS_WAIT      waiting on the GC to read a weak root
   kWaitingForGcThreadFlip,          // WAITING        TS_WAIT      waiting on the GC thread flip (CC collector) to finish
+  kNativeForAbort,                  // WAITING        TS_WAIT      checking other threads are not run on abort.
   kStarting,                        // NEW            TS_WAIT      native thread started, not yet ready to run managed code
   kNative,                          // RUNNABLE       TS_RUNNING   running in a JNI native method
   kSuspended,                       // RUNNABLE       TS_RUNNING   suspended by GC or debugger