I'm trying to understand memory model and reads 5.1.2.4 Multi-threaded executions and data races
and is confused by the release sequence concept defined at 5.1.2.4(p10)
as follows:
A release sequence headed by a release operation
A
on an atomic objectM
is a maximal contiguous sub-sequence of side effects in the modification order ofM
, where the first operation isA
and every subsequent operation either is performed by the same thread that performed the release or is an atomic read-modify-write operation.
which is subsequently used to define synchronize with at 5.1.2.4(p11)
as follows:
Certain library calls synchronize with other library calls performed by another thread. In particular, an atomic operation
A
that performs a release operation on an objectM
synchronizes with an atomic operationB
that performs an acquire operation onM
and reads a value written by any side effect in the release sequence headed byA
.
I can imagine the following example:
#include <stdatomic.h>
Atomic_ int a; // <<--- M
int main(void){
atomic_store_explicit(&a, 42, memory_order_release); // <<--- A
atomic_store_explicit(&a, 442, memory_order_release);
atomic_store_explicit(&a, 242, memory_order_release);
int a_value = atomic_load_explicit(&a, memory_order_acquire);
atomic_store_explicit(&a, 242, memory_order_release);
}
I currently understands it as A
being atomic_store_explicit(&a, 42, memory_order_release);
and its release sequence is
atomic_store_explicit(&a, 442, memory_order_release);
atomic_store_explicit(&a, 242, memory_order_release);
But atomic_store_explicit(&a, 242, memory_order_release);
is not included since it is followed by int a_value = atomic_load_explicit(&a, memory_order_acquire);
which is an acquire operation.
Now coming to the synchronize with
an atomic operation A that performs a release operation on an object M synchronizes with an atomic operation B that performs an acquire operation on M and reads a value written by any side effect in the release sequence headed by A. means that the all release opearations in the release sequence of A are visible by an acquire operation which is atomic_load_explicit(&a, memory_order_acquire);
Is it correct or I missed something?
No, the sequence includes all four store operations, because the intermediate load operation is done by the same thread. Basically for your example you don't have to refer to synchronization. Since there is only one thread in the game, "sequenced before" already give you all the information that you want. An optimizer could even ommit all stores but the last one in your simplified example, even for atomic operations. (Well there is the volatile
in the specification of atomic_store
, but let's forget about this for the moment.)
I think, the idea of the concept of a release sequence is to identify the points at which reads of different threads may intercept stored values, and which make the read dependeny-ordered after the first store operation in the sequence. For that, the fact that the thread reads the value it has written can be ignored.