Blame view

lib/atomic64_test.c 6.64 KB
86a893807   Luca Barbieri   lib: Add self-tes...
1
2
3
4
5
6
7
8
9
10
  /*
   * Testsuite for atomic64_t functions
   *
   * Copyright © 2010  Luca Barbieri
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   */
b3b16d284   Fabian Frederick   lib/atomic64_test...
11
12
  
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
86a893807   Luca Barbieri   lib: Add self-tes...
13
  #include <linux/init.h>
50af5ead3   Paul Gortmaker   bug.h: add includ...
14
  #include <linux/bug.h>
0dbdd1bfe   Peter Huewe   lib/atomic64_test...
15
  #include <linux/kernel.h>
60063497a   Arun Sharma   atomic: use <linu...
16
  #include <linux/atomic.h>
55ded9551   Geert Uytterhoeven   lib: add module s...
17
  #include <linux/module.h>
86a893807   Luca Barbieri   lib: Add self-tes...
18

153a4334c   Andi Kleen   x86/headers: Don'...
19
  #ifdef CONFIG_X86
cd4d09ec6   Borislav Petkov   x86/cpufeature: C...
20
  #include <asm/cpufeature.h>	/* for boot_cpu_has below */
153a4334c   Andi Kleen   x86/headers: Don'...
21
  #endif
41b9e9fcc   Peter Zijlstra   atomic: Add simpl...
22
23
24
25
26
27
28
29
30
31
32
  #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...
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  /*
   * 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...
54
55
56
57
58
59
60
61
  #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...
62
63
64
65
  #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...
66
67
68
69
  #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...
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
97
98
99
100
  #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...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
  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...
119
120
121
122
123
  
  	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...
124
125
126
127
128
129
130
131
132
  	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...
133
134
135
136
137
  	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...
138
  }
86a893807   Luca Barbieri   lib: Add self-tes...
139
  #define INIT(c) do { atomic64_set(&v, c); r = c; } while (0)
41b9e9fcc   Peter Zijlstra   atomic: Add simpl...
140
  static __init void test_atomic64(void)
86a893807   Luca Barbieri   lib: Add self-tes...
141
142
143
144
  {
  	long long v0 = 0xaaa31337c001d00dLL;
  	long long v1 = 0xdeadbeefdeafcafeLL;
  	long long v2 = 0xfaceabadf00df001LL;
ffba19cca   Michael Ellerman   lib/atomic64_test...
145
  	long long v3 = 0x8000000000000000LL;
86a893807   Luca Barbieri   lib: Add self-tes...
146
147
  	long long onestwos = 0x1111111122222222LL;
  	long long one = 1LL;
ffba19cca   Michael Ellerman   lib/atomic64_test...
148
  	int r_int;
86a893807   Luca Barbieri   lib: Add self-tes...
149
150
151
152
153
154
155
156
157
  
  	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...
158
159
160
161
162
163
164
165
  	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...
166

978e5a369   Boqun Feng   atomics: Add test...
167
168
169
170
  	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...
171

28aa2bda2   Peter Zijlstra   locking/atomic: I...
172
173
174
175
176
177
178
179
180
  	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...
181
182
183
184
185
186
  	INIT(v0);
  	atomic64_inc(&v);
  	r += one;
  	BUG_ON(v.counter != r);
  
  	INIT(v0);
86a893807   Luca Barbieri   lib: Add self-tes...
187
188
189
  	atomic64_dec(&v);
  	r -= one;
  	BUG_ON(v.counter != r);
978e5a369   Boqun Feng   atomics: Add test...
190
191
  	INC_RETURN_FAMILY_TEST(64, v0);
  	DEC_RETURN_FAMILY_TEST(64, v0);
86a893807   Luca Barbieri   lib: Add self-tes...
192

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