1/* { dg-do link } */
2/* { dg-require-effective-target sync_char_short } */
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 2 byte values.  */
10
11unsigned short zero = 0;
12unsigned short max = ~0;
13
14unsigned short changing_value = 0;
15unsigned short value = 0;
16unsigned short 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  ret = __atomic_exchange_n (&value, max, __ATOMIC_SEQ_CST);
64  if (ret != zero || value != max)
65    test_abort();
66
67  __atomic_store_n (&value, zero, __ATOMIC_SEQ_CST);
68  if (value != zero)
69    test_abort();
70
71  ret = __atomic_fetch_add (&value, max, __ATOMIC_SEQ_CST);
72  if (value != max || ret != zero)
73    test_abort ();
74
75  ret = __atomic_fetch_sub (&value, max, __ATOMIC_SEQ_CST);
76  if (value != zero || ret != max)
77    test_abort ();
78
79  ret = __atomic_fetch_or (&value, max, __ATOMIC_SEQ_CST);
80  if (value != max || ret != zero)
81    test_abort ();
82
83  ret = __atomic_fetch_and (&value, max, __ATOMIC_SEQ_CST);
84  if (value != max || ret != max)
85    test_abort ();
86
87  ret = __atomic_fetch_xor (&value, max, __ATOMIC_SEQ_CST);
88  if (value != zero || ret != max)
89    test_abort ();
90
91  ret = __atomic_add_fetch (&value, max, __ATOMIC_SEQ_CST);
92  if (value != max || ret != max)
93    test_abort ();
94
95  ret = __atomic_sub_fetch (&value, max, __ATOMIC_SEQ_CST);
96  if (value != zero || ret != zero)
97    test_abort ();
98
99  ret = __atomic_or_fetch (&value, max, __ATOMIC_SEQ_CST);
100  if (value != max || ret != max)
101    test_abort ();
102
103  ret = __atomic_and_fetch (&value, max, __ATOMIC_SEQ_CST);
104  if (value != max || ret != max)
105    test_abort ();
106
107  ret = __atomic_xor_fetch (&value, max, __ATOMIC_SEQ_CST);
108  if (value != zero || ret != zero)
109    test_abort ();
110}
111
112int main ()
113{
114  simulate_thread_main ();
115  simulate_thread_done ();
116  return 0;
117}
118