[Jason, Benjamin: It'd be nice to get input from y'all, since you are more intimately involved with the standard. I want to make sure I'm not misunderstanding things.]

Hopefully a non-controversial feature, but given my luck, I doubt it :).

Here are two additional tests to verify our atomic compliance.

1. Synchronized atomic load/stores:

        atomic_int atomi;
        long double j;

        Thread 1:
                j = 13.0;
                atomi.store(1);

        Thread 2:
                atomi.load();

   As I understand it, the load/stores have acquire/release semantics,
   so the store to <j> must happen before the store to <atomi>.

   Currently, this is not the case on x86-64, because GCC reorders the
   stores and the attached atomics-2.C test fails.  We emit the
   following for thread 1:

        flds    .LC0(%rip)
        movl    $1, atomi(%rip)
        xorl    %eax, %eax
        fstpt   j(%rip)
        mfence

   Notice the store of <j> *after* the store to <atomi>.  I consider
   this a bug and have put this on my laundry list.

2. Unsynchronized atomic load/stores.

   For the "memory_order_relaxed" directive, load/stores are not
   synchronized as the previous example, but stores to identical memory
   locations must be performed in modification order.

   For the following loop, I assume and test that the stores to x[] do
   not happen out of order:

        for (int i=0; i < SIZE; ++i)
                x[i].store(666, memory_order_relaxed);

   This is the test in the attached atomics-3.C.

The test atomics-2.C fails on x86-64, but atomics-3.C passes.

I would like input on my interpretation of the proposed memory model standard, and the sanity of my tests.

I will be committing the attached tests if there are no issues today (with the tests, not the sanity of the model :)).

Aldy
Index: g++.dg/memmodel/atomics-2.C
===================================================================
--- g++.dg/memmodel/atomics-2.C (revision 0)
+++ g++.dg/memmodel/atomics-2.C (revision 0)
@@ -0,0 +1,51 @@
+/* { dg-do link } */
+/* { dg-options "-std=c++0x -O2" } */
+/* { dg-final { memmodel-gdb-test } } */
+
+using namespace std;
+
+#include <atomic>
+#include <limits.h>
+#include <stdio.h>
+#include "memmodel.h"
+
+atomic_int atomi;
+
+/* Non-atomic.  Use a type wide enough to possibly coerce GCC into
+   moving things around.  */
+long double j;
+
+
+/* Test that an atomic store synchronizes with an atomic load.
+
+   In this case, test that the store to <j> happens-before the atomic
+   store to <atomi>.  Make sure the compiler does not reorder the
+   stores.  */
+main()
+{
+  j = 13.0;
+  atomi.store(1);
+  memmodel_done();
+}
+
+void memmodel_other_threads()
+{
+}
+
+/* Verify that side-effects before an atomic store are correctly
+   synchronized with the an atomic load to the same location.  */
+int memmodel_step_verify()
+{
+  if (atomi.load() == 1 && j != 13.0)
+    {
+      printf ("FAIL: invalid synchronization for atomic load/store.\n");
+      return 1;
+    }
+  return 0;
+}
+
+
+int memmodel_final_verify()
+{
+  return memmodel_step_verify();
+}
Index: g++.dg/memmodel/atomics-3.C
===================================================================
--- g++.dg/memmodel/atomics-3.C (revision 0)
+++ g++.dg/memmodel/atomics-3.C (revision 0)
@@ -0,0 +1,55 @@
+/* { dg-do link } */
+/* { dg-options "-std=c++0x -O2" } */
+/* { dg-final { memmodel-gdb-test } } */
+
+using namespace std;
+
+#include <atomic>
+#include <limits.h>
+#include <stdio.h>
+#include "memmodel.h"
+
+#define SIZE 64
+
+atomic_int x[SIZE];            // initially all 0's.
+int i;
+
+
+/* Test that atomic stores to the same location are performed in
+   modification order, despite the use of "memory_order_relaxed".  */
+main()
+{
+  /* These stores must be done consecutively.  */
+  for (int i=0; i < SIZE; ++i)
+    x[i].store(666, memory_order_relaxed);
+  memmodel_done();
+}
+
+void memmodel_other_threads()
+{
+}
+
+/* Verify that the stores were done in order, that is-- once you get
+   to an uninitialized value, every subsequent slot is empty as
+   well.  */
+int memmodel_step_verify()
+{
+  bool seen0 = false;
+  for (i = 0; i < SIZE; ++i)
+    {
+      if (x[i].load() == 0)
+       seen0 = true;
+      else if (seen0)
+       {
+         printf ("FAIL: out-of-order modification\n");
+         return 1;
+       }
+    }
+  return 0;
+}
+
+
+int memmodel_final_verify()
+{
+  return memmodel_step_verify();
+}

Reply via email to