This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GCC extension for atomic access to members


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.

This is somewhat complicated to fix, wording-wise, because for the purpose of aliasing analysis, we need the whole-struct access to *E1, otherwise there is nothing that asserts the dynamic type of this memory location. But without such an assertion, the alias analysis GCC currently performs would be wrong.

A similar extension is needed for access to embedded synchronization types (such as mutexes), but it is even harder to express properly.

Of course, there is a workaround to make this issue go away, like this:

#define member_type(type, member) __typeof__ (((type) {}).member)
#define member_address(this, member) \
  (member_type (__typeof__ (*(this)), member) *) \
  (((char *) (this) + offsetof (__typeof__ (*(this)), member)))

int
load_a_ (struct S *p)
{
return atomic_load_explicit (member_address (p, a), memory_order_relaxed);
}

int
store_b_ (struct S *p, int b)
{
  *member_address (p, b) = b;
}

But it seems to be silly to write code this way. (We actually use these macros in libio, where we have to implement C++ class inheritance in C.)

For C++, we can probably fix this in the standard in some way, so that no extension is required.

Thanks,
Florian


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]