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
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 16f5f87..6b1934c 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -1803,6 +1803,17 @@
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);
}