Blame view

lib/atomic64_test.c 6.32 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>
86a893807   Luca Barbieri   lib: Add self-tes...
17

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

978e5a369   Boqun Feng   atomics: Add test...
164
165
166
167
  	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...
168

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

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