diff options
author | Lokesh Gidra <lokeshgidra@google.com> | 2023-05-12 13:52:55 -0700 |
---|---|---|
committer | Lokesh Gidra <lokeshgidra@google.com> | 2023-05-15 17:08:38 +0000 |
commit | 0fb2fde6e776101e9e103e7e0f66fd1640501029 (patch) | |
tree | 7edcc7706905b1e674e9a1df969e3b9d93abfa8d | |
parent | 2cf88e73b4ddc894959146d417b7c726e74268e8 (diff) | |
download | art-0fb2fde6e776101e9e103e7e0f66fd1640501029.tar.gz |
Ensure flip-function is completed before running synchronous checkpoint
Currently, there is a possibility that the target (for synchronous
checkpoint) thread is not flipped but the caller is. This could result
in accessing from-space objects or having a mix of 'from' and 'to' space
references on the target's stack. This is particularly an issue with
userfaultfd GC.
Bug: 279006963
Bug: 160737021
Test: art/test/testrunner/testrunner.py --target -t 1913-get-set-local-objects
Change-Id: I3df64ded15d126b84638b13fdbb80d9009423698
(cherry picked from commit 47769d3bb5b221b18ebfec7eab6111945228e2fe)
Merged-In: I3df64ded15d126b84638b13fdbb80d9009423698
-rw-r--r-- | runtime/thread.cc | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/runtime/thread.cc b/runtime/thread.cc index 16f5f876a4..6b1934c86e 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -1803,6 +1803,17 @@ bool Thread::RequestSynchronousCheckpoint(Closure* function, ThreadState suspend sched_yield(); } } + // Ensure that the flip function for this thread, if pending, is finished *before* + // the checkpoint function is run. Otherwise, we may end up with both `to' and 'from' + // space references on the stack, confusing the GC's thread-flip logic. The caller is + // runnable so can't have a pending flip function. + DCHECK_EQ(self->GetState(), ThreadState::kRunnable); + DCHECK( + !self->GetStateAndFlags(std::memory_order_relaxed).IsAnyOfFlagsSet(FlipFunctionFlags())); + EnsureFlipFunctionStarted(self); + while (GetStateAndFlags(std::memory_order_acquire).IsAnyOfFlagsSet(FlipFunctionFlags())) { + sched_yield(); + } function->Run(this); } |