On Tue, 2017-09-19 at 07:19 +0200, Florian Weimer wrote:
> On 09/18/2017 10:07 PM, Torvald Riegel wrote:
> > On Mon, 2017-09-18 at 14:19 +0200, Florian Weimer wrote:
> >> I would like to see the GCC project to document that if the address of a
> >> member is taken, this does not constitute an access to the object as a
> >> whole.
> >>
> >> That is, in the following code:
> >>
> >> #include <stdatomic.h>
> >>
> >> struct S {
> >>     _Atomic int a;
> >>     int b;
> >> };
> >>
> >> int
> >> load_a (struct S *p)
> >> {
> >>     return atomic_load_explicit (&p->a, memory_order_relaxed);
> >> }
> >>
> >> int
> >> store_b (struct S *p, int b)
> >> {
> >>     p->b = b;
> >> }
> >>
> >> If one thread calls load_a and another thread calls store_b on the same
> >> struct S *, no data race happens.
> > 
> > There is no data race in this example; a and b are separate objects as
> > far as the memory model is concerned.  That's my understanding and I
> > believe also the understanding in the C++ committee.
> 
> I'm not sure what the C++ standard says in this matter.
> 
> C++ may indeed have addressed this and related issues (e.g., that a 
> memory location which is passed by reference to a function is not 
> actually read in the caller).

The memory models of C and C++ are intended to be the same.  In the
example above, the values of p in both calls are supposed to be equal,
so accesses go to the same object of type S; as far as the memory model
is concerned, a and b are separate objects.

> >> This is an extension over the C standard because of the way “->” is
> >> defined.  C requires that E1->E2 it is evaluated as (*(E1))->E2, and *E1
> >> is defined as an access to the entire struct, so there is a data race in
> >> load_a with the assignment in store_b.
> > 
> > If ISO C really says that this is potentially a data race, then that's a
> > bug in the standard I'd say.  I see no need to have an extension for
> > this (module there potentially being a real bug in the standard).
> 
> GCC relies on the implicit access to the full struct object in this case:
> 
> struct T {
>    int a;
>    int b;
> };
> 
> int
> opt (struct T *p1, struct T *p2)
> {
>    p1->a = 1;
>    p2->b = 2;
>    return p1->a;
> }

This example isn't about data races anymore, because the program
effectively asserts that there are no concurrent accesses to p1->a or
p2->b.  Nonetheless, I see that you are wondering what forbids aliasing
of p1->a and p2->b.  I don't know enough about (the standardese around)
unions to comment on what precisely would prevent aliasing through
unions.

Reply via email to