Consider the following code:
#include <stdatomic.h>
#include <stdlib.h>
void write(int *j, _Atomic int *i){
*j = rand();
atomic_store_explicit(i, 1, memory_order_release);
}
void read(int *j, _Atomic int *i){
if(atomic_load_explicit(i, memory_order_acquire)){
int var = *j;
atomic_store_explicit(i, 0, memory_order_release);
}
}
Assuming that int *j and _Atomic int *i are unrelated memory locations refering to the same objects in both of the functions and 2 separate threads run each functions in an infinite loop is the following true:
If atomic_load_explicit(i, memory_order_acquire) reads a value written by atomic_store_explicit(i, 1, memory_order_release) then int var = *j; reads a value written by *j = rand(); exactly in the same iteration?
My understanding:
*j = rand();is Sequenced beforeatomic_store_explicit(i, 1, memory_order_release);since these are 2 statements in program order.If
atomic_load_explicit(i, memory_order_acquire)reads a value written byatomic_store_explicit(i, 1, memory_order_release);thenatomic_load_explicit(i, memory_order_acquire)synchronizes withatomic_store_explicit(i, 1, memory_order_release);Similarly
atomic_load_explicit(i, memory_order_acquire)is Sequenced beforeint var = *j;.Therefore
*j = rand();inter-thread happens beforeint var = *j;.
Accroding to 5.1.2.4/p20 *j = rand(); is a visible side effect with respect to int var = *j;
QUESTION: Is it really possible to provide visibility guarantees even on non-atomic object if there are acquire-release operations in between with synchronize-with relations?
The main question is if *j = rand(); might be reordered with atomic_store_explicit(i, 1, memory_order_release); or similarly atomic_load_explicit(i, memory_order_acquire might be reordered with int var = *j;
On x86 reads and writes are not reordered with like operations so assembly code compiled for x86 cannot provide a counter-example.