Change RequestSynchronousCheckpoint to release thread_list_lock_

The RequestSynchronousCheckpoint function in some cases needs to
release the thread_list_lock_ as it waits for a checkpoint to be
executed. This means that the thread being checkpointed might be
deleted. Previously it was not obvious this was the case since the
thread_list_lock_ seemed to be held throughout the execution of the
method.

In order to prevent bugs we make RequestSynchronousCheckpoint
explicitly release the thread_list_lock_ when executed, meaning code
will be aware that threads might die during its execution.

Bug: 67362832
Test: ./test.py --host -j50
Change-Id: I1cbdf7660096dc1908b0eeabc1062447307bc888
diff --git a/runtime/thread.h b/runtime/thread.h
index ab89778..42b38da 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -265,9 +265,13 @@
 
   bool RequestCheckpoint(Closure* function)
       REQUIRES(Locks::thread_suspend_count_lock_);
+
+  // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution. This is
+  // due to the fact that Thread::Current() needs to go to sleep to allow the targeted thread to
+  // execute the checkpoint for us if it is Runnable.
   bool RequestSynchronousCheckpoint(Closure* function)
       REQUIRES_SHARED(Locks::mutator_lock_)
-      REQUIRES(Locks::thread_list_lock_)
+      RELEASE(Locks::thread_list_lock_)
       REQUIRES(!Locks::thread_suspend_count_lock_);
   bool RequestEmptyCheckpoint()
       REQUIRES(Locks::thread_suspend_count_lock_);