1/* { dg-do link } */
2/* { dg-require-effective-target sync_int_long } */
3/* { dg-final { simulate-thread } } */
4
5
6#include <stdio.h>
7#include "simulate-thread.h"
8
9/* Test all the __sync routines for proper atomicity on 4 byte values.  */
10
11unsigned int zero = 0;
12unsigned int max = ~0;
13
14unsigned int changing_value = 0;
15unsigned int value = 0;
16unsigned int ret;
17
18void test_abort()
19{
20  static int reported = 0;
21  if (!reported)
22    {
23      printf ("FAIL: improper execution of __sync builtin.\n");
24      reported = 1;
25    }
26}
27
28void simulate_thread_other_threads ()
29{
30}
31
32int simulate_thread_step_verify ()
33{
34  if (value != zero && value != max)
35    {
36      printf ("FAIL: invalid intermediate result for value.\n");
37      return 1;
38    }
39  return 0;
40}
41
42int simulate_thread_final_verify ()
43{
44  if (value != 0)
45    {
46      printf ("FAIL: invalid final result for value.\n");
47      return 1;
48    }
49  return 0;
50}
51
52/* All values written to 'value' alternate between 'zero' and
53   'max'. Any other value detected by simulate_thread_step_verify()
54   between instructions would indicate that the value was only
55   partially written, and would thus fail this atomicity test.
56
57   This function tests each different __atomic routine once, with
58   the exception of the load instruction which requires special
59   testing.  */
60__attribute__((noinline))
61void simulate_thread_main()
62{
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
114main ()
115{
116  simulate_thread_main ();
117  simulate_thread_done ();
118  return 0;
119}
120