Workaround for gcc volatile struct member bug
gcc does not handle struct with volatile member assignments correctly.
See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47409
Using structure assignments for the StateAndFlag union can cause gcc
to optimise the code incorrectly. Doing the assignment using the
as_int member forces the correct behaviour.
Change-Id: I6379d36add16c321b2e4d1dcd6fd8c959f3f92d6
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 297fa45..fa49faa 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -579,7 +579,8 @@
}
bool Thread::RequestCheckpoint(Closure* function) {
- union StateAndFlags old_state_and_flags = state_and_flags_;
+ union StateAndFlags old_state_and_flags;
+ old_state_and_flags.as_int = state_and_flags_.as_int;
if (old_state_and_flags.as_struct.state != kRunnable) {
return false; // Fail, thread is suspended and so can't run a checkpoint.
}
@@ -591,7 +592,8 @@
// Checkpoint function installed now install flag bit.
// We must be runnable to request a checkpoint.
DCHECK_EQ(old_state_and_flags.as_struct.state, kRunnable);
- union StateAndFlags new_state_and_flags = old_state_and_flags;
+ union StateAndFlags new_state_and_flags;
+ new_state_and_flags.as_int = old_state_and_flags.as_int;
new_state_and_flags.as_struct.flags |= kCheckpointRequest;
int succeeded = android_atomic_cmpxchg(old_state_and_flags.as_int, new_state_and_flags.as_int,
&state_and_flags_.as_int);