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.h b/runtime/thread.h
index db2f7b4..44b2186 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -147,7 +147,8 @@
}
bool IsSuspended() const {
- union StateAndFlags state_and_flags = state_and_flags_;
+ union StateAndFlags state_and_flags;
+ state_and_flags.as_int = state_and_flags_.as_int;
return state_and_flags.as_struct.state != kRunnable &&
(state_and_flags.as_struct.flags & kSuspendRequest) != 0;
}
@@ -638,7 +639,8 @@
// 32 bits of atomically changed state and flags. Keeping as 32 bits allows and atomic CAS to
// change from being Suspended to Runnable without a suspend request occurring.
- union StateAndFlags {
+ union PACKED(4) StateAndFlags {
+ StateAndFlags() {}
struct PACKED(4) {
// Bitfield of flag values. Must be changed atomically so that flag values aren't lost. See
// ThreadFlags for bit field meanings.
@@ -650,6 +652,11 @@
volatile uint16_t state;
} as_struct;
volatile int32_t as_int;
+
+ private:
+ // gcc does not handle struct with volatile member assignments correctly.
+ // See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47409
+ DISALLOW_COPY_AND_ASSIGN(StateAndFlags);
};
union StateAndFlags state_and_flags_;
COMPILE_ASSERT(sizeof(union StateAndFlags) == sizeof(int32_t),