1/* { dg-do link } */
2/* { dg-require-effective-target sync_long_long_runtime } */
3/* { dg-options "" } */
4/* { dg-options "-march=pentium" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
5/* { dg-final { simulate-thread } } */
6
7
8#include <stdio.h>
9#include "simulate-thread.h"
10
11/* Test all the __sync routines for proper atomicity on 8 byte values.  */
12
13unsigned long long zero = 0;
14unsigned long long max = ~0;
15
16unsigned long long changing_value = 0;
17unsigned long long value = 0;
18unsigned long long ret;
19
20void test_abort()
21{
22  static int reported = 0;
23  if (!reported)
24    {
25      printf ("FAIL: improper execution of __sync builtin.\n");
26      reported = 1;
27    }
28}
29
30void simulate_thread_other_threads ()
31{
32}
33
34int simulate_thread_step_verify ()
35{
36  if (value != zero && value != max)
37    {
38      printf ("FAIL: invalid intermediate result for value.\n");
39      return 1;
40    }
41  return 0;
42}
43
44int simulate_thread_final_verify ()
45{
46  if (value != 0)
47    {
48      printf ("FAIL: invalid final result for value.\n");
49      return 1;
50    }
51  return 0;
52}
53
54/* All values written to 'value' alternate between 'zero' and 'max'. Any other
55   value detected by simulate_thread_step_verify() between instructions would indicate
56   that the value was only partially written, and would thus fail this
57   atomicity test.
58
59   This function tests each different __atomic routine once, with the
60   exception of the load instruction which requires special testing.  */
61__attribute__((noinline))
62void simulate_thread_main()
63{
64  ret = __atomic_exchange_n (&value, max, __ATOMIC_SEQ_CST);
65  if (ret != zero || value != max)
66    test_abort();
67
68  __atomic_store_n (&value, zero, __ATOMIC_SEQ_CST);
69  if (value != zero)
70    test_abort();
71
72  ret = __atomic_fetch_add (&value, max, __ATOMIC_SEQ_CST);
73  if (value != max || ret != zero)
74    test_abort ();
75
76  ret = __atomic_fetch_sub (&value, max, __ATOMIC_SEQ_CST);
77  if (value != zero || ret != max)
78    test_abort ();
79
80  ret = __atomic_fetch_or (&value, max, __ATOMIC_SEQ_CST);
81  if (value != max || ret != zero)
82    test_abort ();
83
84  ret = __atomic_fetch_and (&value, max, __ATOMIC_SEQ_CST);
85  if (value != max || ret != max)
86    test_abort ();
87
88  ret = __atomic_fetch_xor (&value, max, __ATOMIC_SEQ_CST);
89  if (value != zero || ret != max)
90    test_abort ();
91
92  ret = __atomic_add_fetch (&value, max, __ATOMIC_SEQ_CST);
93  if (value != max || ret != max)
94    test_abort ();
95
96  ret = __atomic_sub_fetch (&value, max, __ATOMIC_SEQ_CST);
97  if (value != zero || ret != zero)
98    test_abort ();
99
100  ret = __atomic_or_fetch (&value, max, __ATOMIC_SEQ_CST);
101  if (value != max || ret != max)
102    test_abort ();
103
104  ret = __atomic_and_fetch (&value, max, __ATOMIC_SEQ_CST);
105  if (value != max || ret != max)
106    test_abort ();
107
108  ret = __atomic_xor_fetch (&value, max, __ATOMIC_SEQ_CST);
109  if (value != zero || ret != zero)
110    test_abort ();
111}
112
113int main ()
114{
115  simulate_thread_main ();
116  simulate_thread_done ();
117  return 0;
118}
119