Blame view

lib/atomic64_test.c 5.44 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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
  /*
   * 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)
  
  #define RETURN_FAMILY_TEST(bit, op, c_op, val)			\
  do {								\
  	FAMILY_TEST(TEST_RETURN, bit, op, c_op, val);		\
  } while (0)
  
  #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...
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
  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...
108
109
110
111
112
113
114
115
116
117
118
  
  	RETURN_FAMILY_TEST(, add_return, +=, onestwos);
  	RETURN_FAMILY_TEST(, add_return, +=, -one);
  	RETURN_FAMILY_TEST(, sub_return, -=, onestwos);
  	RETURN_FAMILY_TEST(, sub_return, -=, -one);
  
  	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...
119
  }
86a893807   Luca Barbieri   lib: Add self-tes...
120
  #define INIT(c) do { atomic64_set(&v, c); r = c; } while (0)
41b9e9fcc   Peter Zijlstra   atomic: Add simpl...
121
  static __init void test_atomic64(void)
86a893807   Luca Barbieri   lib: Add self-tes...
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
  {
  	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...
137
138
139
140
141
142
143
144
  	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...
145

978e5a369   Boqun Feng   atomics: Add test...
146
147
148
149
  	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...
150
151
152
153
154
155
156
  
  	INIT(v0);
  	atomic64_inc(&v);
  	r += one;
  	BUG_ON(v.counter != r);
  
  	INIT(v0);
86a893807   Luca Barbieri   lib: Add self-tes...
157
158
159
  	atomic64_dec(&v);
  	r -= one;
  	BUG_ON(v.counter != r);
978e5a369   Boqun Feng   atomics: Add test...
160
161
  	INC_RETURN_FAMILY_TEST(64, v0);
  	DEC_RETURN_FAMILY_TEST(64, v0);
86a893807   Luca Barbieri   lib: Add self-tes...
162

978e5a369   Boqun Feng   atomics: Add test...
163
164
  	XCHG_FAMILY_TEST(64, v0, v1);
  	CMPXCHG_FAMILY_TEST(64, v0, v1, v2);
86a893807   Luca Barbieri   lib: Add self-tes...
165
166
  
  	INIT(v0);
9efbcd590   Luca Barbieri   lib: Fix atomic64...
167
  	BUG_ON(atomic64_add_unless(&v, one, v0));
86a893807   Luca Barbieri   lib: Add self-tes...
168
169
170
  	BUG_ON(v.counter != r);
  
  	INIT(v0);
9efbcd590   Luca Barbieri   lib: Fix atomic64...
171
  	BUG_ON(!atomic64_add_unless(&v, one, v1));
86a893807   Luca Barbieri   lib: Add self-tes...
172
173
  	r += one;
  	BUG_ON(v.counter != r);
7463449b8   Catalin Marinas   atomic64_test: si...
174
  #ifdef CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
86a893807   Luca Barbieri   lib: Add self-tes...
175
176
177
178
179
180
181
182
183
184
185
186
  	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);
8f4f202b3   Luca Barbieri   lib: Only test at...
187
  #else
7463449b8   Catalin Marinas   atomic64_test: si...
188
  #warning Please implement atomic64_dec_if_positive for your architecture and select the above Kconfig symbol
8f4f202b3   Luca Barbieri   lib: Only test at...
189
  #endif
86a893807   Luca Barbieri   lib: Add self-tes...
190
191
  
  	INIT(onestwos);
25a304f27   Luca Barbieri   lib: Fix atomic64...
192
  	BUG_ON(!atomic64_inc_not_zero(&v));
86a893807   Luca Barbieri   lib: Add self-tes...
193
194
195
196
  	r += one;
  	BUG_ON(v.counter != r);
  
  	INIT(0);
25a304f27   Luca Barbieri   lib: Fix atomic64...
197
  	BUG_ON(atomic64_inc_not_zero(&v));
86a893807   Luca Barbieri   lib: Add self-tes...
198
199
200
  	BUG_ON(v.counter != r);
  
  	INIT(-one);
25a304f27   Luca Barbieri   lib: Fix atomic64...
201
  	BUG_ON(!atomic64_inc_not_zero(&v));
86a893807   Luca Barbieri   lib: Add self-tes...
202
203
  	r += one;
  	BUG_ON(v.counter != r);
41b9e9fcc   Peter Zijlstra   atomic: Add simpl...
204
205
206
207
208
209
  }
  
  static __init int test_atomics(void)
  {
  	test_atomic();
  	test_atomic64();
86a893807   Luca Barbieri   lib: Add self-tes...
210
211
  
  #ifdef CONFIG_X86
b3b16d284   Fabian Frederick   lib/atomic64_test...
212
213
  	pr_info("passed for %s platform %s CX8 and %s SSE
  ",
a5c9161f2   H. Peter Anvin   x86, atomic64: In...
214
  #ifdef CONFIG_X86_64
b3b16d284   Fabian Frederick   lib/atomic64_test...
215
  		"x86-64",
a5c9161f2   H. Peter Anvin   x86, atomic64: In...
216
  #elif defined(CONFIG_X86_CMPXCHG64)
b3b16d284   Fabian Frederick   lib/atomic64_test...
217
  		"i586+",
86a893807   Luca Barbieri   lib: Add self-tes...
218
  #else
b3b16d284   Fabian Frederick   lib/atomic64_test...
219
  		"i386+",
86a893807   Luca Barbieri   lib: Add self-tes...
220
  #endif
a5c9161f2   H. Peter Anvin   x86, atomic64: In...
221
222
  	       boot_cpu_has(X86_FEATURE_CX8) ? "with" : "without",
  	       boot_cpu_has(X86_FEATURE_XMM) ? "with" : "without");
86a893807   Luca Barbieri   lib: Add self-tes...
223
  #else
b3b16d284   Fabian Frederick   lib/atomic64_test...
224
225
  	pr_info("passed
  ");
86a893807   Luca Barbieri   lib: Add self-tes...
226
227
228
229
  #endif
  
  	return 0;
  }
41b9e9fcc   Peter Zijlstra   atomic: Add simpl...
230
  core_initcall(test_atomics);