summaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/simulate-thread/subfields.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/gcc.dg/simulate-thread/subfields.c')
-rw-r--r--gcc/testsuite/gcc.dg/simulate-thread/subfields.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.dg/simulate-thread/subfields.c b/gcc/testsuite/gcc.dg/simulate-thread/subfields.c
new file mode 100644
index 00000000000..2d931176e7d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/simulate-thread/subfields.c
@@ -0,0 +1,93 @@
+/* { dg-do link } */
+/* { dg-options "--param allow-packed-store-data-races=0" } */
+/* { dg-final { simulate-thread } } */
+
+#include <stdio.h>
+#include "simulate-thread.h"
+
+/* This test verifies that data races aren't introduced by structure subfield
+ stores. */
+
+struct test_struct {
+ char a;
+ char b;
+ char c;
+ char d;
+} var = {0,0,0,0};
+
+
+/* This routine sets field a to 'x'. If executed properly, it will
+ not affect any of the other fields in the structure. An improper
+ implementation may load an entire word, change the 8 bits for field
+ 'a' and write the entire word back out. */
+__attribute__((noinline))
+void set_a(char x)
+{
+ var.a = x;
+}
+
+static int global = 0;
+
+/* The other thread increments the value of each of the other fields
+ in the structure every cycle. If the store to the 'a' field does
+ an incorrect full or partial word load, mask and store, it will
+ write back an incorrect value to one or more of the other
+ fields. */
+void simulate_thread_other_threads()
+{
+ global++;
+ var.b = global;
+ var.c = global;
+ var.d = global;
+}
+
+
+/* Make sure that none of the other fields have been changed. */
+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;
+ }
+ if (var.d != global)
+ {
+ printf("FAIL: Unexpected value. var.d is %d, should be %d\n",
+ var.d, global);
+ ret = 1;
+ }
+ return ret;
+}
+
+/* Verify that every variable has the correct value. */
+int simulate_thread_final_verify()
+{
+ int ret = simulate_thread_step_verify();
+ if (var.a != 1)
+ {
+ printf("FAIL: Unexpected value. var.a is %d, should be %d\n", var.a, 1);
+ ret = 1;
+ }
+ return ret;
+}
+
+__attribute__((noinline))
+void simulate_thread_main()
+{
+ set_a(1);
+}
+
+int main ()
+{
+ simulate_thread_main();
+ simulate_thread_done();
+ return 0;
+}