Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/lib/atomic64_test.c
26135 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Testsuite for atomic64_t functions
4
*
5
* Copyright © 2010 Luca Barbieri
6
*/
7
8
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9
10
#include <linux/init.h>
11
#include <linux/bug.h>
12
#include <linux/kernel.h>
13
#include <linux/atomic.h>
14
#include <linux/module.h>
15
16
#ifdef CONFIG_X86
17
#include <asm/cpufeature.h> /* for boot_cpu_has below */
18
#endif
19
20
#define TEST(bit, op, c_op, val) \
21
do { \
22
atomic##bit##_set(&v, v0); \
23
r = v0; \
24
atomic##bit##_##op(val, &v); \
25
r c_op val; \
26
WARN(atomic##bit##_read(&v) != r, "%Lx != %Lx\n", \
27
(unsigned long long)atomic##bit##_read(&v), \
28
(unsigned long long)r); \
29
} while (0)
30
31
/*
32
* Test for a atomic operation family,
33
* @test should be a macro accepting parameters (bit, op, ...)
34
*/
35
36
#define FAMILY_TEST(test, bit, op, args...) \
37
do { \
38
test(bit, op, ##args); \
39
test(bit, op##_acquire, ##args); \
40
test(bit, op##_release, ##args); \
41
test(bit, op##_relaxed, ##args); \
42
} while (0)
43
44
#define TEST_RETURN(bit, op, c_op, val) \
45
do { \
46
atomic##bit##_set(&v, v0); \
47
r = v0; \
48
r c_op val; \
49
BUG_ON(atomic##bit##_##op(val, &v) != r); \
50
BUG_ON(atomic##bit##_read(&v) != r); \
51
} while (0)
52
53
#define TEST_FETCH(bit, op, c_op, val) \
54
do { \
55
atomic##bit##_set(&v, v0); \
56
r = v0; \
57
r c_op val; \
58
BUG_ON(atomic##bit##_##op(val, &v) != v0); \
59
BUG_ON(atomic##bit##_read(&v) != r); \
60
} while (0)
61
62
#define RETURN_FAMILY_TEST(bit, op, c_op, val) \
63
do { \
64
FAMILY_TEST(TEST_RETURN, bit, op, c_op, val); \
65
} while (0)
66
67
#define FETCH_FAMILY_TEST(bit, op, c_op, val) \
68
do { \
69
FAMILY_TEST(TEST_FETCH, bit, op, c_op, val); \
70
} while (0)
71
72
#define TEST_ARGS(bit, op, init, ret, expect, args...) \
73
do { \
74
atomic##bit##_set(&v, init); \
75
BUG_ON(atomic##bit##_##op(&v, ##args) != ret); \
76
BUG_ON(atomic##bit##_read(&v) != expect); \
77
} while (0)
78
79
#define XCHG_FAMILY_TEST(bit, init, new) \
80
do { \
81
FAMILY_TEST(TEST_ARGS, bit, xchg, init, init, new, new); \
82
} while (0)
83
84
#define CMPXCHG_FAMILY_TEST(bit, init, new, wrong) \
85
do { \
86
FAMILY_TEST(TEST_ARGS, bit, cmpxchg, \
87
init, init, new, init, new); \
88
FAMILY_TEST(TEST_ARGS, bit, cmpxchg, \
89
init, init, init, wrong, new); \
90
} while (0)
91
92
#define INC_RETURN_FAMILY_TEST(bit, i) \
93
do { \
94
FAMILY_TEST(TEST_ARGS, bit, inc_return, \
95
i, (i) + one, (i) + one); \
96
} while (0)
97
98
#define DEC_RETURN_FAMILY_TEST(bit, i) \
99
do { \
100
FAMILY_TEST(TEST_ARGS, bit, dec_return, \
101
i, (i) - one, (i) - one); \
102
} while (0)
103
104
static __init void test_atomic(void)
105
{
106
int v0 = 0xaaa31337;
107
int v1 = 0xdeadbeef;
108
int onestwos = 0x11112222;
109
int one = 1;
110
111
atomic_t v;
112
int r;
113
114
TEST(, add, +=, onestwos);
115
TEST(, add, +=, -one);
116
TEST(, sub, -=, onestwos);
117
TEST(, sub, -=, -one);
118
TEST(, or, |=, v1);
119
TEST(, and, &=, v1);
120
TEST(, xor, ^=, v1);
121
TEST(, andnot, &= ~, v1);
122
123
RETURN_FAMILY_TEST(, add_return, +=, onestwos);
124
RETURN_FAMILY_TEST(, add_return, +=, -one);
125
RETURN_FAMILY_TEST(, sub_return, -=, onestwos);
126
RETURN_FAMILY_TEST(, sub_return, -=, -one);
127
128
FETCH_FAMILY_TEST(, fetch_add, +=, onestwos);
129
FETCH_FAMILY_TEST(, fetch_add, +=, -one);
130
FETCH_FAMILY_TEST(, fetch_sub, -=, onestwos);
131
FETCH_FAMILY_TEST(, fetch_sub, -=, -one);
132
133
FETCH_FAMILY_TEST(, fetch_or, |=, v1);
134
FETCH_FAMILY_TEST(, fetch_and, &=, v1);
135
FETCH_FAMILY_TEST(, fetch_andnot, &= ~, v1);
136
FETCH_FAMILY_TEST(, fetch_xor, ^=, v1);
137
138
INC_RETURN_FAMILY_TEST(, v0);
139
DEC_RETURN_FAMILY_TEST(, v0);
140
141
XCHG_FAMILY_TEST(, v0, v1);
142
CMPXCHG_FAMILY_TEST(, v0, v1, onestwos);
143
144
}
145
146
#define INIT(c) do { atomic64_set(&v, c); r = c; } while (0)
147
static __init void test_atomic64(void)
148
{
149
long long v0 = 0xaaa31337c001d00dLL;
150
long long v1 = 0xdeadbeefdeafcafeLL;
151
long long v2 = 0xfaceabadf00df001LL;
152
long long v3 = 0x8000000000000000LL;
153
long long onestwos = 0x1111111122222222LL;
154
long long one = 1LL;
155
int r_int;
156
157
atomic64_t v = ATOMIC64_INIT(v0);
158
long long r = v0;
159
BUG_ON(v.counter != r);
160
161
atomic64_set(&v, v1);
162
r = v1;
163
BUG_ON(v.counter != r);
164
BUG_ON(atomic64_read(&v) != r);
165
166
TEST(64, add, +=, onestwos);
167
TEST(64, add, +=, -one);
168
TEST(64, sub, -=, onestwos);
169
TEST(64, sub, -=, -one);
170
TEST(64, or, |=, v1);
171
TEST(64, and, &=, v1);
172
TEST(64, xor, ^=, v1);
173
TEST(64, andnot, &= ~, v1);
174
175
RETURN_FAMILY_TEST(64, add_return, +=, onestwos);
176
RETURN_FAMILY_TEST(64, add_return, +=, -one);
177
RETURN_FAMILY_TEST(64, sub_return, -=, onestwos);
178
RETURN_FAMILY_TEST(64, sub_return, -=, -one);
179
180
FETCH_FAMILY_TEST(64, fetch_add, +=, onestwos);
181
FETCH_FAMILY_TEST(64, fetch_add, +=, -one);
182
FETCH_FAMILY_TEST(64, fetch_sub, -=, onestwos);
183
FETCH_FAMILY_TEST(64, fetch_sub, -=, -one);
184
185
FETCH_FAMILY_TEST(64, fetch_or, |=, v1);
186
FETCH_FAMILY_TEST(64, fetch_and, &=, v1);
187
FETCH_FAMILY_TEST(64, fetch_andnot, &= ~, v1);
188
FETCH_FAMILY_TEST(64, fetch_xor, ^=, v1);
189
190
INIT(v0);
191
atomic64_inc(&v);
192
r += one;
193
BUG_ON(v.counter != r);
194
195
INIT(v0);
196
atomic64_dec(&v);
197
r -= one;
198
BUG_ON(v.counter != r);
199
200
INC_RETURN_FAMILY_TEST(64, v0);
201
DEC_RETURN_FAMILY_TEST(64, v0);
202
203
XCHG_FAMILY_TEST(64, v0, v1);
204
CMPXCHG_FAMILY_TEST(64, v0, v1, v2);
205
206
INIT(v0);
207
BUG_ON(atomic64_add_unless(&v, one, v0));
208
BUG_ON(v.counter != r);
209
210
INIT(v0);
211
BUG_ON(!atomic64_add_unless(&v, one, v1));
212
r += one;
213
BUG_ON(v.counter != r);
214
215
INIT(onestwos);
216
BUG_ON(atomic64_dec_if_positive(&v) != (onestwos - 1));
217
r -= one;
218
BUG_ON(v.counter != r);
219
220
INIT(0);
221
BUG_ON(atomic64_dec_if_positive(&v) != -one);
222
BUG_ON(v.counter != r);
223
224
INIT(-one);
225
BUG_ON(atomic64_dec_if_positive(&v) != (-one - one));
226
BUG_ON(v.counter != r);
227
228
INIT(onestwos);
229
BUG_ON(!atomic64_inc_not_zero(&v));
230
r += one;
231
BUG_ON(v.counter != r);
232
233
INIT(0);
234
BUG_ON(atomic64_inc_not_zero(&v));
235
BUG_ON(v.counter != r);
236
237
INIT(-one);
238
BUG_ON(!atomic64_inc_not_zero(&v));
239
r += one;
240
BUG_ON(v.counter != r);
241
242
/* Confirm the return value fits in an int, even if the value doesn't */
243
INIT(v3);
244
r_int = atomic64_inc_not_zero(&v);
245
BUG_ON(!r_int);
246
}
247
248
static __init int test_atomics_init(void)
249
{
250
test_atomic();
251
test_atomic64();
252
253
#ifdef CONFIG_X86
254
pr_info("passed for %s platform %s CX8 and %s SSE\n",
255
#ifdef CONFIG_X86_64
256
"x86-64",
257
#elif defined(CONFIG_X86_CX8)
258
"i586+",
259
#else
260
"i386+",
261
#endif
262
boot_cpu_has(X86_FEATURE_CX8) ? "with" : "without",
263
boot_cpu_has(X86_FEATURE_XMM) ? "with" : "without");
264
#else
265
pr_info("passed\n");
266
#endif
267
268
return 0;
269
}
270
271
static __exit void test_atomics_exit(void) {}
272
273
module_init(test_atomics_init);
274
module_exit(test_atomics_exit);
275
276
MODULE_DESCRIPTION("Testsuite for atomic64_t functions");
277
MODULE_LICENSE("GPL");
278
279