Implement C11 _Atomic
diff mbox

Message ID alpine.BSF.2.02.1311211758050.26167@arjuna.pair.com
State New
Headers show

Commit Message

Hans-Peter Nilsson Nov. 21, 2013, 11:23 p.m. UTC
On Thu, 21 Nov 2013, Andrew MacLeod wrote:
> I can bootstrap and check this on x86 to make sure it doesnt affect anything,
> and you can fool with it and see if you can get your desired results with your
> port.

Success!

For the record, tested together with the attached patch for the
CRIS ports, both regularly (not finished, but done with the C
testsuite part and no regressions there), as well as manually
for the attached test-programs, compiling and inspecting output
for different sub-targets and checking that data layout,
alignment and size is as intended.

Too bad about the libstdc++ atomics, but with this/these patches
at least I'll be able to tell people that _Atomic for C11 works.

Thanks to the both of you!

brgds, H-P

struct r0 {
  char a;
  int b;
};

struct l0 {
  char a;
  int b __attribute__((__aligned__(4)));
};

struct a0 {
  char a;
  _Atomic int b;
};

#define test(name, cond) typedef int test_ ## name [-!(cond)]

struct a0 ag;
struct l0 lg;
struct r0 rg;

struct a0 ai = {0, 1};
struct l0 li = {1, 2};
struct r0 ri = {2, 3};

extern struct a0 ae;
extern struct l0 le;
extern struct r0 re;

void foo(void)
{
  struct a0 al;
  struct l0 ll;
  struct r0 rl;
  test(a_al_ge_4, __alignof__(al) >= 4);
  test(a_al_ge_ll, __alignof__(al) >= __alignof__(ll));
  test(a_al_ge_rl, __alignof__(al) >= __alignof__(rl));
  test(a_ag_ge_4, __alignof__(ag) >= 4);
  test(a_ag_ge_lg, __alignof__(ag) >= __alignof__(lg));
  test(a_ag_ge_rg, __alignof__(ag) >= __alignof__(rg));
  test(a_ai_ge_4, __alignof__(ai) >= 4);
  test(a_ai_ge_li, __alignof__(ai) >= __alignof__(li));
  test(a_ai_ge_ri, __alignof__(ai) >= __alignof__(ri));
  test(a_ae_ge_4, __alignof__(ae) >= 4);
  test(a_ae_ge_le, __alignof__(ae) >= __alignof__(le));
  test(a_ae_ge_re, __alignof__(ae) >= __alignof__(re));

  test(s_al_ge_4, sizeof(al) >= 8);
  test(s_al_ge_ll, sizeof(al) >= sizeof(ll));
  test(s_al_ge_rl, sizeof(al) >= sizeof(rl));
  test(s_ag_ge_4, sizeof(ag) >= 8);
  test(s_ag_ge_lg, sizeof(ag) >= sizeof(lg));
  test(s_ag_ge_rg, sizeof(ag) >= sizeof(rg));
  test(s_ai_ge_4, sizeof(ai) >= 8);
  test(s_ai_ge_lg, sizeof(ai) >= sizeof(li));
  test(s_ai_ge_rg, sizeof(ai) >= sizeof(ri));
  test(s_ae_ge_4, sizeof(ae) >= 8);
  test(s_ae_ge_le, sizeof(ae) >= sizeof(le));
  test(s_ae_ge_re, sizeof(ae) >= sizeof(re));

  test(ab_eq_4, __builtin_offsetof(struct a0, b) == 4);
  al = ai;
  al.b++;
  ae = al;
}
_Atomic int foo;
int bar;
void baz(void)
{
  foo++;
}
void foobar(void)
{
  bar++;
}

void xyzzy(int *x)
{
  (*x)++;
}

void plugh(_Atomic int *x)
{
  (*x)++;
}

void xyzzy1(int *x)
{
  int y = *x;
  *x = y+1;
}

void plugh2(_Atomic int *x)
{
  _Atomic int y = *x;
  *x = y+1;
}

Comments

Andrew MacLeod Nov. 21, 2013, 11:31 p.m. UTC | #1
On 11/21/2013 06:23 PM, Hans-Peter Nilsson wrote:
> On Thu, 21 Nov 2013, Andrew MacLeod wrote:
>> I can bootstrap and check this on x86 to make sure it doesnt affect anything,
>> and you can fool with it and see if you can get your desired results with your
>> port.
> Success!
>
> For the record, tested together with the attached patch for the
> CRIS ports, both regularly (not finished, but done with the C
> testsuite part and no regressions there), as well as manually
> for the attached test-programs, compiling and inspecting output
> for different sub-targets and checking that data layout,
> alignment and size is as intended.
>
> Too bad about the libstdc++ atomics, but with this/these patches
> at least I'll be able to tell people that _Atomic for C11 works.
>
> Thanks to the both of you!
>
>
All we need is a way to communicate the atomic property to the type 
within the libstdc++ template...  We cant use _Atomic there :-P

  I originally had created an __attribute__ ((atomic)) whch you could 
apply to the atomic template type and get the same behaviour  as 
_Atomic, Im not sure if there is another way or not.  The atomic 
template is generic, so I couldn't think of any special macro wizardry 
we could define...

Andrew
Hans-Peter Nilsson Nov. 21, 2013, 11:40 p.m. UTC | #2
On Thu, 21 Nov 2013, Hans-Peter Nilsson wrote:
> with this/these patches
> at least I'll be able to tell people that _Atomic for C11 works.

Oh right, gcc still doesn't remove target-introduced "manual"
alignment checks (when expanding atomic intrinsics), but at
least gcc makes sure it's aligned on stack, when options doesn't
say it's aligned.  And a.c:plugh2 doesn't seem to perform an
atomic assignment, but just assignment through an
_Atomic-aligned stack temporary.  Might be my C11-ignorance
showing.

(Without the patches layout and alignment is all broken.)

brgds, H-P
Joseph Myers Nov. 22, 2013, 12:20 a.m. UTC | #3
On Thu, 21 Nov 2013, Hans-Peter Nilsson wrote:

> Oh right, gcc still doesn't remove target-introduced "manual"
> alignment checks (when expanding atomic intrinsics), but at
> least gcc makes sure it's aligned on stack, when options doesn't
> say it's aligned.  And a.c:plugh2 doesn't seem to perform an
> atomic assignment, but just assignment through an
> _Atomic-aligned stack temporary.  Might be my C11-ignorance
> showing.

It appears to me on x86_64 to produce an __atomic_store_4 to *x (in the 
GIMPLE dumps, what happens after that is a matter for the back end).

Note that atomic variable initialization is *not* atomic (see 7.17.2.1 - 
in general ATOMIC_VAR_INIT needs using with the initializer, or the 
initialization needs to be carried out with atomic_init, though GCC 
doesn't require that).  (In C11, the effect of a plain initialization 
without ATOMIC_VAR_INIT is I think that the initializer is evaluated for 
its side effects, but if the variable gets used as either rvalue or lvalue 
without one of the special forms of initialization being used first then 
the behavior is undefined.  The idea is to support implementations with 
extra bits in atomic objects used for locking purposes.)  So no atomic 
store to y is expected - although there are atomic loads from y.
Andrew MacLeod Nov. 22, 2013, 4:21 p.m. UTC | #4
On 11/21/2013 06:40 PM, Hans-Peter Nilsson wrote:
> On Thu, 21 Nov 2013, Hans-Peter Nilsson wrote:
>> with this/these patches
>> at least I'll be able to tell people that _Atomic for C11 works.
> Oh right, gcc still doesn't remove target-introduced "manual"
> alignment checks (when expanding atomic intrinsics), but at
> least gcc makes sure it's aligned on stack, when options doesn't
> say it's aligned.  And a.c:plugh2 doesn't seem to perform an
> atomic assignment, but just assignment through an
> _Atomic-aligned stack temporary.  Might be my C11-ignorance
> showing.
>
> (Without the patches layout and alignment is all broken.)
>
> brgds, H-P
The target hook patch is checked into mainline, revision 205273.

Andrew

Patch
diff mbox

Index: config/cris/cris.c
===================================================================
--- config/cris/cris.c	(revision 205225)
+++ config/cris/cris.c	(working copy)
@@ -93,6 +93,8 @@  static int cris_reg_overlap_mentioned_p 
 static enum machine_mode cris_promote_function_mode (const_tree, enum machine_mode,
 						     int *, const_tree, int);
 
+static unsigned int cris_atomic_align_for_mode (enum machine_mode);
+
 static void cris_print_base (rtx, FILE *);
 
 static void cris_print_index (rtx, FILE *);
@@ -227,6 +229,9 @@  int cris_cpu_version = CRIS_DEFAULT_CPU_
 #undef TARGET_PROMOTE_FUNCTION_MODE
 #define TARGET_PROMOTE_FUNCTION_MODE cris_promote_function_mode
 
+#undef TARGET_ATOMIC_ALIGN_FOR_MODE
+#define TARGET_ATOMIC_ALIGN_FOR_MODE cris_atomic_align_for_mode
+
 #undef TARGET_STRUCT_VALUE_RTX
 #define TARGET_STRUCT_VALUE_RTX cris_struct_value_rtx
 #undef TARGET_SETUP_INCOMING_VARARGS
@@ -4018,6 +4023,14 @@  cris_promote_function_mode (const_tree t
     return mode;
   return CRIS_PROMOTED_MODE (mode, *punsignedp, type);
 } 
+
+/* Atomic types require alignment to be at least the "natural" size. */
+
+static unsigned int
+cris_atomic_align_for_mode (enum machine_mode mode)
+{
+  return GET_MODE_BITSIZE (mode);
+}
 
 /* Let's assume all functions return in r[CRIS_FIRST_ARG_REG] for the
    time being.  */