Blame view

lib/atomic64_test.c 6.43 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
86a893807   Luca Barbieri   lib: Add self-tes...
2
3
4
5
  /*
   * Testsuite for atomic64_t functions
   *
   * Copyright © 2010  Luca Barbieri
86a893807   Luca Barbieri   lib: Add self-tes...
6
   */
b3b16d284   Fabian Frederick   lib/atomic64_test...
7
8
  
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
86a893807   Luca Barbieri   lib: Add self-tes...
9
  #include <linux/init.h>
50af5ead3   Paul Gortmaker   bug.h: add includ...
10
  #include <linux/bug.h>
0dbdd1bfe   Peter Huewe   lib/atomic64_test...
11
  #include <linux/kernel.h>
60063497a   Arun Sharma   atomic: use <linu...
12
  #include <linux/atomic.h>
55ded9551   Geert Uytterhoeven   lib: add module s...
13
  #include <linux/module.h>
86a893807   Luca Barbieri   lib: Add self-tes...
14

153a4334c   Andi Kleen   x86/headers: Don'...
15
  #ifdef CONFIG_X86
cd4d09ec6   Borislav Petkov   x86/cpufeature: C...
16
  #include <asm/cpufeature.h>	/* for boot_cpu_has below */
153a4334c   Andi Kleen   x86/headers: Don'...
17
  #endif
41b9e9fcc   Peter Zijlstra   atomic: Add simpl...
18
19
20
21
22
23
24
25
26
27
28
  #define TEST(bit, op, c_op, val)				\
  do {								\
  	atomic##bit##_set(&v, v0);				\
  	r = v0;							\
  	atomic##bit##_##op(val, &v);				\
  	r c_op val;						\
  	WARN(atomic##bit##_read(&v) != r, "%Lx != %Lx
  ",	\
  		(unsigned long long)atomic##bit##_read(&v),	\
  		(unsigned long long)r);				\
  } while (0)
978e5a369   Boqun Feng   atomics: Add test...
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
  /*
   * Test for a atomic operation family,
   * @test should be a macro accepting parameters (bit, op, ...)
   */
  
  #define FAMILY_TEST(test, bit, op, args...)	\
  do {						\
  	test(bit, op, ##args);		\
  	test(bit, op##_acquire, ##args);	\
  	test(bit, op##_release, ##args);	\
  	test(bit, op##_relaxed, ##args);	\
  } while (0)
  
  #define TEST_RETURN(bit, op, c_op, val)				\
  do {								\
  	atomic##bit##_set(&v, v0);				\
  	r = v0;							\
  	r c_op val;						\
  	BUG_ON(atomic##bit##_##op(val, &v) != r);		\
  	BUG_ON(atomic##bit##_read(&v) != r);			\
  } while (0)
28aa2bda2   Peter Zijlstra   locking/atomic: I...
50
51
52
53
54
55
56
57
  #define TEST_FETCH(bit, op, c_op, val)				\
  do {								\
  	atomic##bit##_set(&v, v0);				\
  	r = v0;							\
  	r c_op val;						\
  	BUG_ON(atomic##bit##_##op(val, &v) != v0);		\
  	BUG_ON(atomic##bit##_read(&v) != r);			\
  } while (0)
978e5a369   Boqun Feng   atomics: Add test...
58
59
60
61
  #define RETURN_FAMILY_TEST(bit, op, c_op, val)			\
  do {								\
  	FAMILY_TEST(TEST_RETURN, bit, op, c_op, val);		\
  } while (0)
28aa2bda2   Peter Zijlstra   locking/atomic: I...
62
63
64
65
  #define FETCH_FAMILY_TEST(bit, op, c_op, val)			\
  do {								\
  	FAMILY_TEST(TEST_FETCH, bit, op, c_op, val);		\
  } while (0)
978e5a369   Boqun Feng   atomics: Add test...
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
  #define TEST_ARGS(bit, op, init, ret, expect, args...)		\
  do {								\
  	atomic##bit##_set(&v, init);				\
  	BUG_ON(atomic##bit##_##op(&v, ##args) != ret);		\
  	BUG_ON(atomic##bit##_read(&v) != expect);		\
  } while (0)
  
  #define XCHG_FAMILY_TEST(bit, init, new)				\
  do {									\
  	FAMILY_TEST(TEST_ARGS, bit, xchg, init, init, new, new);	\
  } while (0)
  
  #define CMPXCHG_FAMILY_TEST(bit, init, new, wrong)			\
  do {									\
  	FAMILY_TEST(TEST_ARGS, bit, cmpxchg, 				\
  			init, init, new, init, new);			\
  	FAMILY_TEST(TEST_ARGS, bit, cmpxchg,				\
  			init, init, init, wrong, new);			\
  } while (0)
  
  #define INC_RETURN_FAMILY_TEST(bit, i)			\
  do {							\
  	FAMILY_TEST(TEST_ARGS, bit, inc_return,		\
  			i, (i) + one, (i) + one);	\
  } while (0)
  
  #define DEC_RETURN_FAMILY_TEST(bit, i)			\
  do {							\
  	FAMILY_TEST(TEST_ARGS, bit, dec_return,		\
  			i, (i) - one, (i) - one);	\
  } while (0)
41b9e9fcc   Peter Zijlstra   atomic: Add simpl...
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
  static __init void test_atomic(void)
  {
  	int v0 = 0xaaa31337;
  	int v1 = 0xdeadbeef;
  	int onestwos = 0x11112222;
  	int one = 1;
  
  	atomic_t v;
  	int r;
  
  	TEST(, add, +=, onestwos);
  	TEST(, add, +=, -one);
  	TEST(, sub, -=, onestwos);
  	TEST(, sub, -=, -one);
  	TEST(, or, |=, v1);
  	TEST(, and, &=, v1);
  	TEST(, xor, ^=, v1);
  	TEST(, andnot, &= ~, v1);
978e5a369   Boqun Feng   atomics: Add test...
115
116
117
118
119
  
  	RETURN_FAMILY_TEST(, add_return, +=, onestwos);
  	RETURN_FAMILY_TEST(, add_return, +=, -one);
  	RETURN_FAMILY_TEST(, sub_return, -=, onestwos);
  	RETURN_FAMILY_TEST(, sub_return, -=, -one);
28aa2bda2   Peter Zijlstra   locking/atomic: I...
120
121
122
123
124
125
126
127
128
  	FETCH_FAMILY_TEST(, fetch_add, +=, onestwos);
  	FETCH_FAMILY_TEST(, fetch_add, +=, -one);
  	FETCH_FAMILY_TEST(, fetch_sub, -=, onestwos);
  	FETCH_FAMILY_TEST(, fetch_sub, -=, -one);
  
  	FETCH_FAMILY_TEST(, fetch_or,  |=, v1);
  	FETCH_FAMILY_TEST(, fetch_and, &=, v1);
  	FETCH_FAMILY_TEST(, fetch_andnot, &= ~, v1);
  	FETCH_FAMILY_TEST(, fetch_xor, ^=, v1);
978e5a369   Boqun Feng   atomics: Add test...
129
130
131
132
133
  	INC_RETURN_FAMILY_TEST(, v0);
  	DEC_RETURN_FAMILY_TEST(, v0);
  
  	XCHG_FAMILY_TEST(, v0, v1);
  	CMPXCHG_FAMILY_TEST(, v0, v1, onestwos);
41b9e9fcc   Peter Zijlstra   atomic: Add simpl...
134
  }
86a893807   Luca Barbieri   lib: Add self-tes...
135
  #define INIT(c) do { atomic64_set(&v, c); r = c; } while (0)
41b9e9fcc   Peter Zijlstra   atomic: Add simpl...
136
  static __init void test_atomic64(void)
86a893807   Luca Barbieri   lib: Add self-tes...
137
138
139
140
  {
  	long long v0 = 0xaaa31337c001d00dLL;
  	long long v1 = 0xdeadbeefdeafcafeLL;
  	long long v2 = 0xfaceabadf00df001LL;
ffba19cca   Michael Ellerman   lib/atomic64_test...
141
  	long long v3 = 0x8000000000000000LL;
86a893807   Luca Barbieri   lib: Add self-tes...
142
143
  	long long onestwos = 0x1111111122222222LL;
  	long long one = 1LL;
ffba19cca   Michael Ellerman   lib/atomic64_test...
144
  	int r_int;
86a893807   Luca Barbieri   lib: Add self-tes...
145
146
147
148
149
150
151
152
153
  
  	atomic64_t v = ATOMIC64_INIT(v0);
  	long long r = v0;
  	BUG_ON(v.counter != r);
  
  	atomic64_set(&v, v1);
  	r = v1;
  	BUG_ON(v.counter != r);
  	BUG_ON(atomic64_read(&v) != r);
41b9e9fcc   Peter Zijlstra   atomic: Add simpl...
154
155
156
157
158
159
160
161
  	TEST(64, add, +=, onestwos);
  	TEST(64, add, +=, -one);
  	TEST(64, sub, -=, onestwos);
  	TEST(64, sub, -=, -one);
  	TEST(64, or, |=, v1);
  	TEST(64, and, &=, v1);
  	TEST(64, xor, ^=, v1);
  	TEST(64, andnot, &= ~, v1);
86a893807   Luca Barbieri   lib: Add self-tes...
162

978e5a369   Boqun Feng   atomics: Add test...
163
164
165
166
  	RETURN_FAMILY_TEST(64, add_return, +=, onestwos);
  	RETURN_FAMILY_TEST(64, add_return, +=, -one);
  	RETURN_FAMILY_TEST(64, sub_return, -=, onestwos);
  	RETURN_FAMILY_TEST(64, sub_return, -=, -one);
86a893807   Luca Barbieri   lib: Add self-tes...
167

28aa2bda2   Peter Zijlstra   locking/atomic: I...
168
169
170
171
172
173
174
175
176
  	FETCH_FAMILY_TEST(64, fetch_add, +=, onestwos);
  	FETCH_FAMILY_TEST(64, fetch_add, +=, -one);
  	FETCH_FAMILY_TEST(64, fetch_sub, -=, onestwos);
  	FETCH_FAMILY_TEST(64, fetch_sub, -=, -one);
  
  	FETCH_FAMILY_TEST(64, fetch_or,  |=, v1);
  	FETCH_FAMILY_TEST(64, fetch_and, &=, v1);
  	FETCH_FAMILY_TEST(64, fetch_andnot, &= ~, v1);
  	FETCH_FAMILY_TEST(64, fetch_xor, ^=, v1);
86a893807   Luca Barbieri   lib: Add self-tes...
177
178
179
180
181
182
  	INIT(v0);
  	atomic64_inc(&v);
  	r += one;
  	BUG_ON(v.counter != r);
  
  	INIT(v0);
86a893807   Luca Barbieri   lib: Add self-tes...
183
184
185
  	atomic64_dec(&v);
  	r -= one;
  	BUG_ON(v.counter != r);
978e5a369   Boqun Feng   atomics: Add test...
186
187
  	INC_RETURN_FAMILY_TEST(64, v0);
  	DEC_RETURN_FAMILY_TEST(64, v0);
86a893807   Luca Barbieri   lib: Add self-tes...
188

978e5a369   Boqun Feng   atomics: Add test...
189
190
  	XCHG_FAMILY_TEST(64, v0, v1);
  	CMPXCHG_FAMILY_TEST(64, v0, v1, v2);
86a893807   Luca Barbieri   lib: Add self-tes...
191
192
  
  	INIT(v0);
9efbcd590   Luca Barbieri   lib: Fix atomic64...
193
  	BUG_ON(atomic64_add_unless(&v, one, v0));
86a893807   Luca Barbieri   lib: Add self-tes...
194
195
196
  	BUG_ON(v.counter != r);
  
  	INIT(v0);
9efbcd590   Luca Barbieri   lib: Fix atomic64...
197
  	BUG_ON(!atomic64_add_unless(&v, one, v1));
86a893807   Luca Barbieri   lib: Add self-tes...
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
  	r += one;
  	BUG_ON(v.counter != r);
  
  	INIT(onestwos);
  	BUG_ON(atomic64_dec_if_positive(&v) != (onestwos - 1));
  	r -= one;
  	BUG_ON(v.counter != r);
  
  	INIT(0);
  	BUG_ON(atomic64_dec_if_positive(&v) != -one);
  	BUG_ON(v.counter != r);
  
  	INIT(-one);
  	BUG_ON(atomic64_dec_if_positive(&v) != (-one - one));
  	BUG_ON(v.counter != r);
  
  	INIT(onestwos);
25a304f27   Luca Barbieri   lib: Fix atomic64...
215
  	BUG_ON(!atomic64_inc_not_zero(&v));
86a893807   Luca Barbieri   lib: Add self-tes...
216
217
218
219
  	r += one;
  	BUG_ON(v.counter != r);
  
  	INIT(0);
25a304f27   Luca Barbieri   lib: Fix atomic64...
220
  	BUG_ON(atomic64_inc_not_zero(&v));
86a893807   Luca Barbieri   lib: Add self-tes...
221
222
223
  	BUG_ON(v.counter != r);
  
  	INIT(-one);
25a304f27   Luca Barbieri   lib: Fix atomic64...
224
  	BUG_ON(!atomic64_inc_not_zero(&v));
86a893807   Luca Barbieri   lib: Add self-tes...
225
226
  	r += one;
  	BUG_ON(v.counter != r);
ffba19cca   Michael Ellerman   lib/atomic64_test...
227
228
229
230
231
  
  	/* Confirm the return value fits in an int, even if the value doesn't */
  	INIT(v3);
  	r_int = atomic64_inc_not_zero(&v);
  	BUG_ON(!r_int);
41b9e9fcc   Peter Zijlstra   atomic: Add simpl...
232
  }
55ded9551   Geert Uytterhoeven   lib: add module s...
233
  static __init int test_atomics_init(void)
41b9e9fcc   Peter Zijlstra   atomic: Add simpl...
234
235
236
  {
  	test_atomic();
  	test_atomic64();
86a893807   Luca Barbieri   lib: Add self-tes...
237
238
  
  #ifdef CONFIG_X86
b3b16d284   Fabian Frederick   lib/atomic64_test...
239
240
  	pr_info("passed for %s platform %s CX8 and %s SSE
  ",
a5c9161f2   H. Peter Anvin   x86, atomic64: In...
241
  #ifdef CONFIG_X86_64
b3b16d284   Fabian Frederick   lib/atomic64_test...
242
  		"x86-64",
a5c9161f2   H. Peter Anvin   x86, atomic64: In...
243
  #elif defined(CONFIG_X86_CMPXCHG64)
b3b16d284   Fabian Frederick   lib/atomic64_test...
244
  		"i586+",
86a893807   Luca Barbieri   lib: Add self-tes...
245
  #else
b3b16d284   Fabian Frederick   lib/atomic64_test...
246
  		"i386+",
86a893807   Luca Barbieri   lib: Add self-tes...
247
  #endif
a5c9161f2   H. Peter Anvin   x86, atomic64: In...
248
249
  	       boot_cpu_has(X86_FEATURE_CX8) ? "with" : "without",
  	       boot_cpu_has(X86_FEATURE_XMM) ? "with" : "without");
86a893807   Luca Barbieri   lib: Add self-tes...
250
  #else
b3b16d284   Fabian Frederick   lib/atomic64_test...
251
252
  	pr_info("passed
  ");
86a893807   Luca Barbieri   lib: Add self-tes...
253
254
255
256
  #endif
  
  	return 0;
  }
55ded9551   Geert Uytterhoeven   lib: add module s...
257
258
259
260
261
262
  static __exit void test_atomics_exit(void) {}
  
  module_init(test_atomics_init);
  module_exit(test_atomics_exit);
  
  MODULE_LICENSE("GPL");