Add two locks to expected_mutexes_on_weak_ref_access_.

The ObjectRegistry lock and the jdwp event list lock to avoid DCHECK
failures.

Some cleanup.

Bug: 35360959
Bug: 35745310
Test: test-art-host
Test: jdwp test.
Test: angler boot.
Change-Id: I16000c0c7624b1271d40c4c1a01a4e249271b67e
diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h
index 9b6938f..83fe696 100644
--- a/runtime/base/mutex.h
+++ b/runtime/base/mutex.h
@@ -583,6 +583,12 @@
   // Checks for whether it is safe to call Abort() without using locks.
   static bool IsSafeToCallAbortRacy() NO_THREAD_SAFETY_ANALYSIS;
 
+  // Add a mutex to expected_mutexes_on_weak_ref_access_.
+  static void AddToExpectedMutexesOnWeakRefAccess(BaseMutex* mutex, bool need_lock = true);
+  // Remove a mutex from expected_mutexes_on_weak_ref_access_.
+  static void RemoveFromExpectedMutexesOnWeakRefAccess(BaseMutex* mutex, bool need_lock = true);
+  // Check if the given mutex is in expected_mutexes_on_weak_ref_access_.
+  static bool IsExpectedOnWeakRefAccess(BaseMutex* mutex);
 
   // Guards allocation entrypoint instrumenting.
   static Mutex* instrument_entrypoints_lock_;
@@ -734,6 +740,8 @@
   // encounter an unexpected mutex on accessing weak refs,
   // Thread::CheckEmptyCheckpointFromWeakRefAccess will detect it.
   static std::vector<BaseMutex*> expected_mutexes_on_weak_ref_access_;
+  static Atomic<const BaseMutex*> expected_mutexes_on_weak_ref_access_guard_;
+  class ScopedExpectedMutexesOnWeakRefAccessLock;
 };
 
 class Roles {