t___sync_compare_and_swap.c revision 1.1.14.1 1 /* $NetBSD: t___sync_compare_and_swap.c,v 1.1.14.1 2025/08/02 05:58:03 perseant Exp $ */
2
3 /*
4 * Copyright (C) 2019 Tetsuya Isaki. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
22 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 __RCSID("$NetBSD: t___sync_compare_and_swap.c,v 1.1.14.1 2025/08/02 05:58:03 perseant Exp $");
30
31 #include <atf-c.h>
32 #include <inttypes.h>
33 #include <machine/types.h> // for __HAVE_ATOMIC64_OPS
34
35 #if defined __arm__ && __ARM_ARCH <= 5
36 #define pr56839_xfail \
37 atf_tc_expect_fail("PR port-arm/56839:" \
38 "GCC emits wrong codes for compare_and_swap_1 bultins" \
39 " on armv5 (el & eb)")
40 #else
41 #define pr56839_xfail __nothing
42 #endif
43
44 /*
45 * These tests don't examine the atomicity.
46 */
47
48 /* XXX
49 * Depending on a combination of arch and compiler, __sync_* is
50 * implemented as compiler's builtin function. In that case, even
51 * if libc exports the function symbol, it is not used. As a result
52 * this tests will examine compiler's builtin functions.
53 * It's better to run only when target is actually in libc.
54 */
55
56 #define OLDVAL (0x1122334455667788UL)
57 #define NEWVAL (0x8090a0b0c0d0e0f0UL)
58
59 #define atf_sync_bool(NAME, TYPE, FMT, XFAIL) \
60 ATF_TC(NAME); \
61 ATF_TC_HEAD(NAME, tc) \
62 { \
63 atf_tc_set_md_var(tc, "descr", #NAME); \
64 } \
65 ATF_TC_BODY(NAME, tc) \
66 { \
67 volatile TYPE val; \
68 TYPE oldval; \
69 TYPE newval; \
70 TYPE expval; \
71 bool expres; \
72 bool res; \
73 XFAIL; \
74 /* If successful */ \
75 val = (TYPE)OLDVAL; \
76 oldval = (TYPE)OLDVAL; \
77 newval = (TYPE)NEWVAL; \
78 expval = (TYPE)NEWVAL; \
79 expres = true; \
80 res = NAME(&val, oldval, newval); \
81 ATF_REQUIRE_MSG(val == expval, \
82 "successful case: val expects 0x%" FMT " but 0x%" FMT, expval, val); \
83 ATF_REQUIRE_MSG(res == expres, \
84 "successful case: res expects %d but %d", expres, res); \
85 /* If failure */ \
86 val = (TYPE)OLDVAL; \
87 oldval = (TYPE)(OLDVAL + 1); \
88 newval = (TYPE)NEWVAL; \
89 expval = (TYPE)OLDVAL; \
90 expres = false; \
91 res = NAME(&val, oldval, newval); \
92 ATF_REQUIRE_MSG(val == expval, \
93 "failure case: val expects 0x%" FMT " but 0x%" FMT, expval, val); \
94 ATF_REQUIRE_MSG(res == expres, \
95 "failure case: res expects %d but %d", expres, res); \
96 }
97
98 atf_sync_bool(__sync_bool_compare_and_swap_1, uint8_t, PRIx8, pr56839_xfail);
99 atf_sync_bool(__sync_bool_compare_and_swap_2, uint16_t, PRIx16, __nothing);
100 atf_sync_bool(__sync_bool_compare_and_swap_4, uint32_t, PRIx32, __nothing);
101 #ifdef __HAVE_ATOMIC64_OPS
102 atf_sync_bool(__sync_bool_compare_and_swap_8, uint64_t, PRIx64, __nothing);
103 #endif
104
105 #if _BYTE_ORDER == _LITTLE_ENDIAN
106 # define LSB 0
107 # define MSB 1
108 #elif _BYTE_ORDER == _BIG_ENDIAN
109 # define LSB 1
110 # define MSB 0
111 #else
112 # error Unknown byte order!
113 #endif
114
115 #define atf_sync_bool_subword(NAME, SUBWIDTH, SUBTYPE, TYPE, SUBFMT, FMT, XFAIL) \
116 ATF_TC(NAME##_subword); \
117 ATF_TC_HEAD(NAME##_subword, tc) \
118 { \
119 atf_tc_set_md_var(tc, "descr", "subword " #NAME); \
120 } \
121 ATF_TC_BODY(NAME##_subword, tc) \
122 { \
123 volatile union { \
124 TYPE word; \
125 SUBTYPE subword[2]; \
126 } val; \
127 XFAIL; \
128 /* If successful */ \
129 val.subword[LSB] = -1; \
130 val.subword[MSB] = 123; \
131 ATF_CHECK(NAME(&val.subword[LSB], /*old*/-1, /*new*/-2)); \
132 ATF_CHECK_EQ_MSG(val.subword[LSB], (SUBTYPE)-2, \
133 "val.subword[LSB] = 0x%" SUBFMT, val.subword[LSB]); \
134 ATF_CHECK_EQ_MSG(val.subword[MSB], 123, \
135 "val.subword[MSB] = 0x%" SUBFMT, val.subword[MSB]); \
136 ATF_CHECK_EQ_MSG(val.word, \
137 ((TYPE)123 << (SUBWIDTH)) | (TYPE)(SUBTYPE)-2, \
138 "val.word = 0x%" FMT, val.word); \
139 /* If failed */ \
140 val.subword[LSB] = -3; \
141 val.subword[MSB] = 45; \
142 ATF_CHECK(!NAME(&val.subword[LSB], /*old*/-1, /*new*/-2)); \
143 ATF_CHECK_EQ_MSG(val.subword[LSB], (SUBTYPE)-3, \
144 "val.subword[LSB] = 0x%" SUBFMT, val.subword[LSB]); \
145 ATF_CHECK_EQ_MSG(val.subword[MSB], 45, \
146 "val.subword[MSB] = 0x%" SUBFMT, val.subword[MSB]); \
147 ATF_CHECK_EQ_MSG(val.word, \
148 ((TYPE)45 << (SUBWIDTH)) | (TYPE)(SUBTYPE)-3, \
149 "val.word = 0x%" FMT, val.word); \
150 }
151
152 atf_sync_bool_subword(__sync_bool_compare_and_swap_1, 8, uint8_t, uint16_t,
153 PRIx8, PRIx16, pr56839_xfail);
154 atf_sync_bool_subword(__sync_bool_compare_and_swap_2, 16, uint16_t, uint32_t,
155 PRIx16, PRIx32, pr56839_xfail);
156 atf_sync_bool_subword(__sync_bool_compare_and_swap_4, 32, uint32_t, uint64_t,
157 PRIx32, PRIx64, __nothing);
158
159 #define atf_sync_val(NAME, TYPE, FMT, XFAIL) \
160 ATF_TC(NAME); \
161 ATF_TC_HEAD(NAME, tc) \
162 { \
163 atf_tc_set_md_var(tc, "descr", #NAME); \
164 } \
165 ATF_TC_BODY(NAME, tc) \
166 { \
167 volatile TYPE val; \
168 TYPE oldval; \
169 TYPE newval; \
170 TYPE expval; \
171 TYPE expres; \
172 TYPE res; \
173 XFAIL; \
174 /* If successful */ \
175 val = (TYPE)OLDVAL; \
176 oldval = (TYPE)OLDVAL; \
177 newval = (TYPE)NEWVAL; \
178 expval = (TYPE)NEWVAL; \
179 expres = (TYPE)OLDVAL; \
180 res = NAME(&val, oldval, newval); \
181 ATF_REQUIRE_MSG(val == expval, \
182 "successful case: val expects 0x%" FMT " but 0x%" FMT, expval, val); \
183 ATF_REQUIRE_MSG(res == expres, \
184 "successful case: res expects 0x%" FMT " but 0x%" FMT, expres, res); \
185 /* If failure */ \
186 val = (TYPE)OLDVAL; \
187 oldval = (TYPE)(OLDVAL + 1); \
188 newval = (TYPE)NEWVAL; \
189 expval = (TYPE)OLDVAL; \
190 expres = (TYPE)OLDVAL; \
191 res = NAME(&val, oldval, newval); \
192 ATF_REQUIRE_MSG(val == expval, \
193 "failure case: val expects 0x%" FMT " but 0x%" FMT, expval, val); \
194 ATF_REQUIRE_MSG(res == expres, \
195 "failure case: res expects 0x%" FMT " but 0x%" FMT, expres, res); \
196 }
197
198 atf_sync_val(__sync_val_compare_and_swap_1, uint8_t, PRIx8, pr56839_xfail);
199 atf_sync_val(__sync_val_compare_and_swap_2, uint16_t, PRIx16, __nothing);
200 atf_sync_val(__sync_val_compare_and_swap_4, uint32_t, PRIx32, __nothing);
201 #ifdef __HAVE_ATOMIC64_OPS
202 atf_sync_val(__sync_val_compare_and_swap_8, uint64_t, PRIx64, __nothing);
203 #endif
204
205 #define atf_sync_val_subword(NAME, SUBWIDTH, SUBTYPE, TYPE, SUBFMT, FMT, XFAIL) \
206 ATF_TC(NAME##_subword); \
207 ATF_TC_HEAD(NAME##_subword, tc) \
208 { \
209 atf_tc_set_md_var(tc, "descr", "subword " #NAME); \
210 } \
211 ATF_TC_BODY(NAME##_subword, tc) \
212 { \
213 volatile union { \
214 TYPE word; \
215 SUBTYPE subword[2]; \
216 } val; \
217 SUBTYPE rval; \
218 XFAIL; \
219 /* If successful */ \
220 val.subword[LSB] = -1; \
221 val.subword[MSB] = 123; \
222 ATF_CHECK_EQ_MSG((rval = NAME(&val.subword[LSB], \
223 /*old*/-1, /*new*/-2)), (SUBTYPE)-1, \
224 "expected 0x%" SUBFMT ", got 0x%" SUBFMT, \
225 (SUBTYPE)-1, rval); \
226 ATF_CHECK_EQ_MSG(val.subword[LSB], (SUBTYPE)-2, \
227 "val.subword[LSB] = 0x%" SUBFMT, val.subword[LSB]); \
228 ATF_CHECK_EQ_MSG(val.subword[MSB], 123, \
229 "val.subword[MSB] = 0x%" SUBFMT, val.subword[MSB]); \
230 ATF_CHECK_EQ_MSG(val.word, \
231 ((TYPE)123 << (SUBWIDTH)) | (TYPE)(SUBTYPE)-2, \
232 "val.word = 0x%" FMT, val.word); \
233 /* If failed */ \
234 val.subword[LSB] = -3; \
235 val.subword[MSB] = 45; \
236 ATF_CHECK_EQ_MSG((rval = NAME(&val.subword[LSB], \
237 /*old*/-1, /*new*/-2)), (SUBTYPE)-3, \
238 "expected 0x%" SUBFMT ", got 0x%" SUBFMT, \
239 (SUBTYPE)-3, rval); \
240 ATF_CHECK_EQ_MSG(val.subword[LSB], (SUBTYPE)-3, \
241 "val.subword[LSB] = 0x%" SUBFMT, val.subword[LSB]); \
242 ATF_CHECK_EQ_MSG(val.subword[MSB], 45, \
243 "val.subword[MSB] = 0x%" SUBFMT, val.subword[MSB]); \
244 ATF_CHECK_EQ_MSG(val.word, \
245 ((TYPE)45 << (SUBWIDTH)) | (TYPE)(SUBTYPE)-3, \
246 "val.word = 0x%" FMT, val.word); \
247 }
248
249 atf_sync_val_subword(__sync_val_compare_and_swap_1, 8, uint8_t, uint16_t,
250 PRIx8, PRIx16, pr56839_xfail);
251 atf_sync_val_subword(__sync_val_compare_and_swap_2, 16, uint16_t, uint32_t,
252 PRIx16, PRIx32, pr56839_xfail);
253 atf_sync_val_subword(__sync_val_compare_and_swap_4, 32, uint32_t, uint64_t,
254 PRIx32, PRIx64, __nothing);
255
256 ATF_TP_ADD_TCS(tp)
257 {
258 ATF_TP_ADD_TC(tp, __sync_bool_compare_and_swap_1);
259 ATF_TP_ADD_TC(tp, __sync_bool_compare_and_swap_2);
260 ATF_TP_ADD_TC(tp, __sync_bool_compare_and_swap_4);
261 #ifdef __HAVE_ATOMIC64_OPS
262 ATF_TP_ADD_TC(tp, __sync_bool_compare_and_swap_8);
263 #endif
264
265 ATF_TP_ADD_TC(tp, __sync_bool_compare_and_swap_1_subword);
266 ATF_TP_ADD_TC(tp, __sync_bool_compare_and_swap_2_subword);
267 ATF_TP_ADD_TC(tp, __sync_bool_compare_and_swap_4_subword);
268
269 ATF_TP_ADD_TC(tp, __sync_val_compare_and_swap_1);
270 ATF_TP_ADD_TC(tp, __sync_val_compare_and_swap_2);
271 ATF_TP_ADD_TC(tp, __sync_val_compare_and_swap_4);
272 #ifdef __HAVE_ATOMIC64_OPS
273 ATF_TP_ADD_TC(tp, __sync_val_compare_and_swap_8);
274 #endif
275
276 ATF_TP_ADD_TC(tp, __sync_val_compare_and_swap_1_subword);
277 ATF_TP_ADD_TC(tp, __sync_val_compare_and_swap_2_subword);
278 ATF_TP_ADD_TC(tp, __sync_val_compare_and_swap_4_subword);
279
280 return atf_no_error();
281 }
282