Created
April 12, 2020 18:46
-
-
Save dannas/2d957f1e3372cfedcbb885adb8b7149d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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