This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: GCC extension for atomic access to members
- From: Martin Sebor <msebor at gmail dot com>
- To: Florian Weimer <fweimer at redhat dot com>, GCC <gcc at gcc dot gnu dot org>
- Date: Tue, 19 Sep 2017 09:14:31 -0600
- Subject: Re: GCC extension for atomic access to members
- Authentication-results: sourceware.org; auth=none
- References: <bbe0877c-7651-a732-cfe1-6d6b326d6d7c@redhat.com>
On 09/18/2017 06:19 AM, 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.
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.
It's true that E1->E2 is equivalent to (*(E1))->E2 (this is made
clear in C11 by Footnote 96) but C doesn't use the term "access"
in the definition of the * operator. The * operator is defined
to result in an lvalue that designates an object, and operator .
to evaluate the first operand, which doesn't imply accessing it.
If E1->E2 implied accessing all members of *E1 then there would
be no way to assign an initial value to just the E2 member without
also accessing all other members of *E1, even those that haven't
yet been initialized.
Martin