1 /* Test for _Atomic in C11.  Test that compare-and-exchange is
2    operating properly when operations on the same variable are carried
3    out in two threads.  */
4 /* { dg-do run } */
5 /* { dg-options "-std=c11 -pedantic-errors -pthread -U_POSIX_C_SOURCE -D_POSIX_C_SOURCE=200809L" } */
6 /* { dg-additional-options "-D_XOPEN_SOURCE=600" { target *-*-solaris2.1[0-9]* } } */
7 /* { dg-require-effective-target pthread } */
8 
9 #include <stdint.h>
10 #include <pthread.h>
11 #include <stdbool.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 
15 #define ITER_COUNT 10000
16 
17 static volatile _Atomic bool thread_ready;
18 
19 /* Generate test code (with NAME used to name functions and variables)
20    for atomic compound assignments to a variable of type LHSTYPE.  The
21    variable is initialized to INIT, then PRE var POST is executed
22    ITER_COUNT times in each of two threads, and the final result
23    should be FINAL.  A function test_main_##NAME is generated that
24    returns nonzero on failure, zero on success.  */
25 
26 #define TEST_FUNCS(NAME, LHSTYPE, PRE, POST, INIT, FINAL)		\
27 									\
28 static volatile _Atomic LHSTYPE var_##NAME = (INIT);			\
29 									\
30 static void *								\
31 test_thread_##NAME (void *arg)						\
32 {									\
33   thread_ready = true;							\
34   for (int i = 0; i < ITER_COUNT; i++)					\
35     PRE var_##NAME POST;						\
36   return NULL;								\
37 }									\
38 									\
39 static int								\
40 test_main_##NAME (void)							\
41 {									\
42   thread_ready = false;							\
43   pthread_t thread_id;							\
44   int pret = pthread_create (&thread_id, NULL, test_thread_##NAME,	\
45 			     NULL);					\
46   if (pret != 0)							\
47     {									\
48       printf ("pthread_create failed: %d\n", pret);			\
49       return 1;								\
50     }									\
51   while (!thread_ready)							\
52     ;									\
53   for (int i = 0; i < ITER_COUNT; i++)					\
54     PRE var_##NAME POST;						\
55   pthread_join (thread_id, NULL);					\
56   if (var_##NAME != (FINAL))						\
57     {									\
58       printf (#NAME " failed\n");					\
59       return 1;								\
60     }									\
61   else									\
62     {									\
63       printf (#NAME " passed\n");					\
64       return 0;								\
65     }									\
66 }
67 
68 TEST_FUNCS (uint8_add, uint8_t, , += 1, 0, (uint8_t) 20000)
69 TEST_FUNCS (uint8_add_3, uint8_t, , += 3, 0, (uint8_t) 60000)
70 TEST_FUNCS (uint16_add, uint16_t, , += 1, 0, (uint16_t) 20000)
71 TEST_FUNCS (uint16_add_3, uint16_t, , += 3, 0, (uint16_t) 60000)
72 TEST_FUNCS (uint32_add, uint32_t, , += 1, 0, (uint32_t) 20000)
73 TEST_FUNCS (uint32_add_3, uint32_t, , += 3, 0, (uint32_t) 60000)
74 TEST_FUNCS (uint64_add, uint64_t, , += 1, 0, (uint64_t) 20000)
75 TEST_FUNCS (uint64_add_3, uint64_t, , += 3, 0, (uint64_t) 60000)
76 TEST_FUNCS (uint64_add_neg, uint64_t, , += 1, -10000, (uint64_t) 10000)
77 TEST_FUNCS (float_add, float, , += 1, 0, 20000)
78 TEST_FUNCS (double_add, double, , += 1, 0, 20000)
79 TEST_FUNCS (long_double_add, long double, , += 1, 0, 20000)
80 TEST_FUNCS (complex_float_add, _Complex float, , += 1, 0, 20000)
81 TEST_FUNCS (complex_double_add, _Complex double, , += 1, 0, 20000)
82 TEST_FUNCS (complex_long_double_add, _Complex long double, , += 1, 0, 20000)
83 TEST_FUNCS (uint8_postinc, uint8_t, , ++, 0, (uint8_t) 20000)
84 TEST_FUNCS (uint16_postinc, uint16_t, , ++, 0, (uint16_t) 20000)
85 TEST_FUNCS (uint32_postinc, uint32_t, , ++, 0, (uint32_t) 20000)
86 TEST_FUNCS (uint64_postinc, uint64_t, , ++, 0, (uint64_t) 20000)
87 TEST_FUNCS (uint64_postinc_neg, uint64_t, , ++, -10000, (uint64_t) 10000)
88 TEST_FUNCS (float_postinc, float, , ++, 0, 20000)
89 TEST_FUNCS (double_postinc, double, , ++, 0, 20000)
90 TEST_FUNCS (long_double_postinc, long double, , ++, 0, 20000)
91 TEST_FUNCS (uint8_preinc, uint8_t, ++, , 0, (uint8_t) 20000)
92 TEST_FUNCS (uint16_preinc, uint16_t, ++, , 0, (uint16_t) 20000)
93 TEST_FUNCS (uint32_preinc, uint32_t, ++, , 0, (uint32_t) 20000)
94 TEST_FUNCS (uint64_preinc, uint64_t, ++, , 0, (uint64_t) 20000)
95 TEST_FUNCS (uint64_preinc_neg, uint64_t, ++, , -10000, (uint64_t) 10000)
96 TEST_FUNCS (float_preinc, float, ++, , 0, 20000)
97 TEST_FUNCS (double_preinc, double, ++, , 0, 20000)
98 TEST_FUNCS (long_double_preinc, long double, ++, , 0, 20000)
99 TEST_FUNCS (uint8_sub, uint8_t, , -= 1, 0, (uint8_t) -20000)
100 TEST_FUNCS (uint8_sub_3, uint8_t, , -= 3, 0, (uint8_t) -60000)
101 TEST_FUNCS (uint16_sub, uint16_t, , -= 1, 0, (uint16_t) -20000)
102 TEST_FUNCS (uint16_sub_3, uint16_t, , -= 3, 0, (uint16_t) -60000)
103 TEST_FUNCS (uint32_sub, uint32_t, , -= 1, 0, (uint32_t) -20000)
104 TEST_FUNCS (uint32_sub_3, uint32_t, , -= 3, 0, (uint32_t) -60000)
105 TEST_FUNCS (uint64_sub, uint64_t, , -= 1, 0, (uint64_t) -20000)
106 TEST_FUNCS (uint64_sub_3, uint64_t, , -= 3, 0, (uint64_t) -60000)
107 TEST_FUNCS (uint64_sub_neg, uint64_t, , -= 1, 10000, (uint64_t) -10000)
108 TEST_FUNCS (float_sub, float, , -= 1, 0, -20000)
109 TEST_FUNCS (double_sub, double, , -= 1, 0, -20000)
110 TEST_FUNCS (long_double_sub, long double, , -= 1, 0, -20000)
111 TEST_FUNCS (complex_float_sub, _Complex float, , -= 1, 0, -20000)
112 TEST_FUNCS (complex_double_sub, _Complex double, , -= 1, 0, -20000)
113 TEST_FUNCS (complex_long_double_sub, _Complex long double, , -= 1, 0, -20000)
114 TEST_FUNCS (uint8_postdec, uint8_t, , --, 0, (uint8_t) -20000)
115 TEST_FUNCS (uint16_postdec, uint16_t, , --, 0, (uint16_t) -20000)
116 TEST_FUNCS (uint32_postdec, uint32_t, , --, 0, (uint32_t) -20000)
117 TEST_FUNCS (uint64_postdec, uint64_t, , --, 0, (uint64_t) -20000)
118 TEST_FUNCS (uint64_postdec_neg, uint64_t, , --, 10000, (uint64_t) -10000)
119 TEST_FUNCS (float_postdec, float, , --, 0, -20000)
120 TEST_FUNCS (double_postdec, double, , --, 0, -20000)
121 TEST_FUNCS (long_double_postdec, long double, , --, 0, -20000)
122 TEST_FUNCS (uint8_predec, uint8_t, --, , 0, (uint8_t) -20000)
123 TEST_FUNCS (uint16_predec, uint16_t, --, , 0, (uint16_t) -20000)
124 TEST_FUNCS (uint32_predec, uint32_t, --, , 0, (uint32_t) -20000)
125 TEST_FUNCS (uint64_predec, uint64_t, --, , 0, (uint64_t) -20000)
126 TEST_FUNCS (uint64_predec_neg, uint64_t, --, , 10000, (uint64_t) -10000)
127 TEST_FUNCS (float_predec, float, --, , 0, -20000)
128 TEST_FUNCS (double_predec, double, --, , 0, -20000)
129 TEST_FUNCS (long_double_predec, long double, --, , 0, -20000)
130 TEST_FUNCS (uint8_mul, uint8_t, , *= 3, 1, (uint8_t) 0x81)
131 TEST_FUNCS (uint16_mul, uint16_t, , *= 3, 1, (uint16_t) 0x9681)
132 TEST_FUNCS (uint32_mul, uint32_t, , *= 3, 1, (uint32_t) 0x62b49681U)
133 TEST_FUNCS (uint64_mul, uint64_t, , *= 3, 1, (uint64_t) 0xcd926beb62b49681ULL)
134 
135 int
main(void)136 main (void)
137 {
138   int ret = 0;
139   ret |= test_main_uint8_add ();
140   ret |= test_main_uint8_add_3 ();
141   ret |= test_main_uint16_add ();
142   ret |= test_main_uint16_add_3 ();
143   ret |= test_main_uint32_add ();
144   ret |= test_main_uint32_add_3 ();
145   ret |= test_main_uint64_add ();
146   ret |= test_main_uint64_add_3 ();
147   ret |= test_main_uint64_add_neg ();
148   ret |= test_main_float_add ();
149   ret |= test_main_double_add ();
150   ret |= test_main_long_double_add ();
151   ret |= test_main_complex_float_add ();
152   ret |= test_main_complex_double_add ();
153   ret |= test_main_complex_long_double_add ();
154   ret |= test_main_uint8_postinc ();
155   ret |= test_main_uint16_postinc ();
156   ret |= test_main_uint32_postinc ();
157   ret |= test_main_uint64_postinc ();
158   ret |= test_main_uint64_postinc_neg ();
159   ret |= test_main_float_postinc ();
160   ret |= test_main_double_postinc ();
161   ret |= test_main_long_double_postinc ();
162   ret |= test_main_uint8_preinc ();
163   ret |= test_main_uint16_preinc ();
164   ret |= test_main_uint32_preinc ();
165   ret |= test_main_uint64_preinc ();
166   ret |= test_main_uint64_preinc_neg ();
167   ret |= test_main_float_preinc ();
168   ret |= test_main_double_preinc ();
169   ret |= test_main_long_double_preinc ();
170   ret |= test_main_uint8_sub ();
171   ret |= test_main_uint8_sub_3 ();
172   ret |= test_main_uint16_sub ();
173   ret |= test_main_uint16_sub_3 ();
174   ret |= test_main_uint32_sub ();
175   ret |= test_main_uint32_sub_3 ();
176   ret |= test_main_uint64_sub ();
177   ret |= test_main_uint64_sub_3 ();
178   ret |= test_main_uint64_sub_neg ();
179   ret |= test_main_float_sub ();
180   ret |= test_main_double_sub ();
181   ret |= test_main_long_double_sub ();
182   ret |= test_main_complex_float_sub ();
183   ret |= test_main_complex_double_sub ();
184   ret |= test_main_complex_long_double_sub ();
185   ret |= test_main_uint8_postdec ();
186   ret |= test_main_uint16_postdec ();
187   ret |= test_main_uint32_postdec ();
188   ret |= test_main_uint64_postdec ();
189   ret |= test_main_uint64_postdec_neg ();
190   ret |= test_main_float_postdec ();
191   ret |= test_main_double_postdec ();
192   ret |= test_main_long_double_postdec ();
193   ret |= test_main_uint8_predec ();
194   ret |= test_main_uint16_predec ();
195   ret |= test_main_uint32_predec ();
196   ret |= test_main_uint64_predec ();
197   ret |= test_main_uint64_predec_neg ();
198   ret |= test_main_float_predec ();
199   ret |= test_main_double_predec ();
200   ret |= test_main_long_double_predec ();
201   ret |= test_main_uint8_mul ();
202   ret |= test_main_uint16_mul ();
203   ret |= test_main_uint32_mul ();
204   ret |= test_main_uint64_mul ();
205   if (ret)
206     abort ();
207   else
208     exit (0);
209 }
210