summaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/simulate-thread
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/g++.dg/simulate-thread')
-rw-r--r--gcc/testsuite/g++.dg/simulate-thread/atomics-1.C73
-rw-r--r--gcc/testsuite/g++.dg/simulate-thread/atomics-2.C58
-rw-r--r--gcc/testsuite/g++.dg/simulate-thread/bitfields-2.C77
-rw-r--r--gcc/testsuite/g++.dg/simulate-thread/bitfields.C80
4 files changed, 288 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/simulate-thread/atomics-1.C b/gcc/testsuite/g++.dg/simulate-thread/atomics-1.C
new file mode 100644
index 00000000000..7e0041ee382
--- /dev/null
+++ b/gcc/testsuite/g++.dg/simulate-thread/atomics-1.C
@@ -0,0 +1,73 @@
+/* { dg-do link } */
+/* { dg-options "-std=c++0x" } */
+/* { dg-final { simulate-thread } } */
+
+/* Test that atomic int and atomic char work properly. */
+
+using namespace std;
+
+#include <atomic>
+#include <limits.h>
+#include <stdio.h>
+#include "simulate-thread.h"
+
+atomic<int> atomi;
+atomic<char> atomc;
+
+/* No need for parallel threads to do anything */
+void simulate_thread_other_threads()
+{
+}
+
+/* Verify after every instruction is executed, that the atmoic int and
+ char have one of the 2 legitimate values. */
+int simulate_thread_step_verify()
+{
+ if (atomi != 0 && atomi != INT_MAX)
+ {
+ printf ("FAIL: invalid intermediate result for atomi (%d).\n",
+ (int)atomi);
+ return 1;
+ }
+ if (atomc != 0 && atomc != CHAR_MAX)
+ {
+ printf ("FAIL: invalid intermediate result for atomc (%d).\n",
+ (int)atomc);
+ return 1;
+ }
+ return 0;
+}
+
+
+/* Verify that both atmoics have the corerct value. */
+int simulate_thread_final_verify()
+{
+ if (atomi != INT_MAX)
+ {
+ printf ("FAIL: invalid final result for atomi (%d).\n",
+ (int)atomi);
+ return 1;
+ }
+ if (atomc != CHAR_MAX)
+ {
+ printf ("FAIL: invalid final result for atomc (%d).\n",
+ (int)atomc);
+ return 1;
+ }
+ return 0;
+}
+
+/* Test a store to an atomic int and an atomic char. */
+__attribute__((noinline))
+void simulate_thread_main()
+{
+ atomi = INT_MAX;
+ atomc = CHAR_MAX;
+}
+
+int main ()
+{
+ simulate_thread_main();
+ simulate_thread_done();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/simulate-thread/atomics-2.C b/gcc/testsuite/g++.dg/simulate-thread/atomics-2.C
new file mode 100644
index 00000000000..be3232d7087
--- /dev/null
+++ b/gcc/testsuite/g++.dg/simulate-thread/atomics-2.C
@@ -0,0 +1,58 @@
+/* { dg-do link } */
+/* { dg-options "-std=c++0x" } */
+/* { dg-final { simulate-thread } } */
+
+using namespace std;
+
+#include <atomic>
+#include <limits.h>
+#include <stdio.h>
+#include "simulate-thread.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. */
+__attribute__((noinline))
+void simulate_thread_main()
+{
+ j = 13.0;
+ atomi.store(1);
+}
+
+int main ()
+{
+ simulate_thread_main();
+ simulate_thread_done();
+ return 0;
+}
+
+void simulate_thread_other_threads()
+{
+}
+
+/* Verify that side-effects before an atomic store are correctly
+ synchronized with the an atomic load to the same location. */
+int simulate_thread_step_verify()
+{
+ if (atomi.load() == 1 && j != 13.0)
+ {
+ printf ("FAIL: invalid synchronization for atomic load/store.\n");
+ return 1;
+ }
+ return 0;
+}
+
+
+int simulate_thread_final_verify()
+{
+ return simulate_thread_step_verify();
+}
diff --git a/gcc/testsuite/g++.dg/simulate-thread/bitfields-2.C b/gcc/testsuite/g++.dg/simulate-thread/bitfields-2.C
new file mode 100644
index 00000000000..077514a3ff5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/simulate-thread/bitfields-2.C
@@ -0,0 +1,77 @@
+/* { dg-do link } */
+/* { dg-options "--param allow-load-data-races=0 --param allow-store-data-races=0" } */
+/* { dg-final { simulate-thread } } */
+
+/* Test that setting <var.a> does not touch either <var.b> or <var.c>.
+ In the C++ memory model, non contiguous bitfields ("a" and "c"
+ here) should be considered as distinct memory locations, so we
+ can't use bit twiddling to set either one. */
+
+#include <stdio.h>
+#include "simulate-thread.h"
+
+#define CONSTA 12
+
+static int global;
+struct S
+{
+ unsigned int a : 4;
+ unsigned char b;
+ unsigned int c : 6;
+} var;
+
+__attribute__((noinline))
+void set_a()
+{
+ var.a = CONSTA;
+}
+
+void simulate_thread_other_threads()
+{
+ ++global;
+ var.b = global;
+ var.c = global;
+}
+
+int simulate_thread_step_verify()
+{
+ int ret = 0;
+ if (var.b != global)
+ {
+ printf ("FAIL: Unexpected value: var.b is %d, should be %d\n",
+ var.b, global);
+ ret = 1;
+ }
+ if (var.c != global)
+ {
+ printf ("FAIL: Unexpected value: var.c is %d, should be %d\n",
+ var.c, global);
+ ret = 1;
+ }
+ return ret;
+}
+
+int simulate_thread_final_verify()
+{
+ int ret = simulate_thread_step_verify();
+ if (var.a != CONSTA)
+ {
+ printf ("FAIL: Unexpected value: var.a is %d, should be %d\n",
+ var.a, CONSTA);
+ ret = 1;
+ }
+ return ret;
+}
+
+__attribute__((noinline))
+void simulate_thread_main()
+{
+ set_a();
+}
+
+int main()
+{
+ simulate_thread_main();
+ simulate_thread_done();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/simulate-thread/bitfields.C b/gcc/testsuite/g++.dg/simulate-thread/bitfields.C
new file mode 100644
index 00000000000..3acf21f876f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/simulate-thread/bitfields.C
@@ -0,0 +1,80 @@
+/* { dg-do link } */
+/* { dg-options "--param allow-load-data-races=0 --param allow-store-data-races=0" } */
+/* { dg-final { simulate-thread } } */
+
+/* Test that setting <var.a> does not touch either <var.b> or <var.c>.
+ In the C++ memory model, non contiguous bitfields ("a" and "c"
+ here) should be considered as distinct memory locations, so we
+ can't use bit twiddling to set either one. */
+
+#include <stdio.h>
+#include "simulate-thread.h"
+
+#define CONSTA 12
+
+static int global;
+struct S
+{
+ /* On x86-64, the volatile causes us to access <a> with a 32-bit
+ access, and thus trigger this test. */
+ volatile unsigned int a : 4;
+
+ unsigned char b;
+ unsigned int c : 6;
+} var;
+
+__attribute__((noinline))
+void set_a()
+{
+ var.a = CONSTA;
+}
+
+void simulate_thread_other_threads()
+{
+ ++global;
+ var.b = global;
+ var.c = global;
+}
+
+int simulate_thread_step_verify()
+{
+ int ret = 0;
+ if (var.b != global)
+ {
+ printf ("FAIL: Unexpected value: var.b is %d, should be %d\n",
+ var.b, global);
+ ret = 1;
+ }
+ if (var.c != global)
+ {
+ printf ("FAIL: Unexpected value: var.c is %d, should be %d\n",
+ var.c, global);
+ ret = 1;
+ }
+ return ret;
+}
+
+int simulate_thread_final_verify()
+{
+ int ret = simulate_thread_step_verify();
+ if (var.a != CONSTA)
+ {
+ printf ("FAIL: Unexpected value: var.a is %d, should be %d\n",
+ var.a, CONSTA);
+ ret = 1;
+ }
+ return ret;
+}
+
+__attribute__((noinline))
+void simulate_thread_main()
+{
+ set_a();
+}
+
+int main ()
+{
+ simulate_thread_main();
+ simulate_thread_done();
+ return 0;
+}