Skip to content

Instantly share code, notes, and snippets.

@dannas
Created April 12, 2020 18:46
Show Gist options
  • Save dannas/2d957f1e3372cfedcbb885adb8b7149d to your computer and use it in GitHub Desktop.
Save dannas/2d957f1e3372cfedcbb885adb8b7149d to your computer and use it in GitHub Desktop.
// Example of unwanted reordering gcc 9.3
// https://godbolt.org/z/5AL_wh
//
// The flag |ready| should be set after the load to the message.
//
// If I use size_t as type for |i| then all three functions give
// the correct ordering, so the compiler needs "something to chew on",
// in this case the sign extension to a 64 bit type, for it to emit
// the stores in the wrong order.
#define READ_ONCE(x) (*(volatile typeof(x) *) &(x))
#define WRITE_ONCE(x, val) ((*(volatile typeof(x) *) &(x)) = (val))
volatile int ready;
int message[100];
// Ready is stored before message.
void faulty(int i) {
message[i] = 42;
ready = 1;
}
// The compiler barrier ensure that stores to message and ready can't be reordered.
void ordered(int i) {
message[i] = 42;
asm("" : : : "memory");
ready = 1;
}
// The volatile loads can't be reordered so message and ready are stored in the right order.
void volatile_ordered(int i) {
WRITE_ONCE(message[i], 42);
WRITE_ONCE(ready,1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment