Merge remote-tracking branch 'asoc/fix/dapm' into asoc-linus
[platform/kernel/linux-rpi.git] / lib / atomic64_test.c
1 /*
2  * Testsuite for atomic64_t functions
3  *
4  * Copyright © 2010  Luca Barbieri
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  */
11
12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
14 #include <linux/init.h>
15 #include <linux/bug.h>
16 #include <linux/kernel.h>
17 #include <linux/atomic.h>
18
19 #ifdef CONFIG_X86
20 #include <asm/cpufeature.h>     /* for boot_cpu_has below */
21 #endif
22
23 #define TEST(bit, op, c_op, val)                                \
24 do {                                                            \
25         atomic##bit##_set(&v, v0);                              \
26         r = v0;                                                 \
27         atomic##bit##_##op(val, &v);                            \
28         r c_op val;                                             \
29         WARN(atomic##bit##_read(&v) != r, "%Lx != %Lx\n",       \
30                 (unsigned long long)atomic##bit##_read(&v),     \
31                 (unsigned long long)r);                         \
32 } while (0)
33
34 /*
35  * Test for a atomic operation family,
36  * @test should be a macro accepting parameters (bit, op, ...)
37  */
38
39 #define FAMILY_TEST(test, bit, op, args...)     \
40 do {                                            \
41         test(bit, op, ##args);          \
42         test(bit, op##_acquire, ##args);        \
43         test(bit, op##_release, ##args);        \
44         test(bit, op##_relaxed, ##args);        \
45 } while (0)
46
47 #define TEST_RETURN(bit, op, c_op, val)                         \
48 do {                                                            \
49         atomic##bit##_set(&v, v0);                              \
50         r = v0;                                                 \
51         r c_op val;                                             \
52         BUG_ON(atomic##bit##_##op(val, &v) != r);               \
53         BUG_ON(atomic##bit##_read(&v) != r);                    \
54 } while (0)
55
56 #define TEST_FETCH(bit, op, c_op, val)                          \
57 do {                                                            \
58         atomic##bit##_set(&v, v0);                              \
59         r = v0;                                                 \
60         r c_op val;                                             \
61         BUG_ON(atomic##bit##_##op(val, &v) != v0);              \
62         BUG_ON(atomic##bit##_read(&v) != r);                    \
63 } while (0)
64
65 #define RETURN_FAMILY_TEST(bit, op, c_op, val)                  \
66 do {                                                            \
67         FAMILY_TEST(TEST_RETURN, bit, op, c_op, val);           \
68 } while (0)
69
70 #define FETCH_FAMILY_TEST(bit, op, c_op, val)                   \
71 do {                                                            \
72         FAMILY_TEST(TEST_FETCH, bit, op, c_op, val);            \
73 } while (0)
74
75 #define TEST_ARGS(bit, op, init, ret, expect, args...)          \
76 do {                                                            \
77         atomic##bit##_set(&v, init);                            \
78         BUG_ON(atomic##bit##_##op(&v, ##args) != ret);          \
79         BUG_ON(atomic##bit##_read(&v) != expect);               \
80 } while (0)
81
82 #define XCHG_FAMILY_TEST(bit, init, new)                                \
83 do {                                                                    \
84         FAMILY_TEST(TEST_ARGS, bit, xchg, init, init, new, new);        \
85 } while (0)
86
87 #define CMPXCHG_FAMILY_TEST(bit, init, new, wrong)                      \
88 do {                                                                    \
89         FAMILY_TEST(TEST_ARGS, bit, cmpxchg,                            \
90                         init, init, new, init, new);                    \
91         FAMILY_TEST(TEST_ARGS, bit, cmpxchg,                            \
92                         init, init, init, wrong, new);                  \
93 } while (0)
94
95 #define INC_RETURN_FAMILY_TEST(bit, i)                  \
96 do {                                                    \
97         FAMILY_TEST(TEST_ARGS, bit, inc_return,         \
98                         i, (i) + one, (i) + one);       \
99 } while (0)
100
101 #define DEC_RETURN_FAMILY_TEST(bit, i)                  \
102 do {                                                    \
103         FAMILY_TEST(TEST_ARGS, bit, dec_return,         \
104                         i, (i) - one, (i) - one);       \
105 } while (0)
106
107 static __init void test_atomic(void)
108 {
109         int v0 = 0xaaa31337;
110         int v1 = 0xdeadbeef;
111         int onestwos = 0x11112222;
112         int one = 1;
113
114         atomic_t v;
115         int r;
116
117         TEST(, add, +=, onestwos);
118         TEST(, add, +=, -one);
119         TEST(, sub, -=, onestwos);
120         TEST(, sub, -=, -one);
121         TEST(, or, |=, v1);
122         TEST(, and, &=, v1);
123         TEST(, xor, ^=, v1);
124         TEST(, andnot, &= ~, v1);
125
126         RETURN_FAMILY_TEST(, add_return, +=, onestwos);
127         RETURN_FAMILY_TEST(, add_return, +=, -one);
128         RETURN_FAMILY_TEST(, sub_return, -=, onestwos);
129         RETURN_FAMILY_TEST(, sub_return, -=, -one);
130
131         FETCH_FAMILY_TEST(, fetch_add, +=, onestwos);
132         FETCH_FAMILY_TEST(, fetch_add, +=, -one);
133         FETCH_FAMILY_TEST(, fetch_sub, -=, onestwos);
134         FETCH_FAMILY_TEST(, fetch_sub, -=, -one);
135
136         FETCH_FAMILY_TEST(, fetch_or,  |=, v1);
137         FETCH_FAMILY_TEST(, fetch_and, &=, v1);
138         FETCH_FAMILY_TEST(, fetch_andnot, &= ~, v1);
139         FETCH_FAMILY_TEST(, fetch_xor, ^=, v1);
140
141         INC_RETURN_FAMILY_TEST(, v0);
142         DEC_RETURN_FAMILY_TEST(, v0);
143
144         XCHG_FAMILY_TEST(, v0, v1);
145         CMPXCHG_FAMILY_TEST(, v0, v1, onestwos);
146
147 }
148
149 #define INIT(c) do { atomic64_set(&v, c); r = c; } while (0)
150 static __init void test_atomic64(void)
151 {
152         long long v0 = 0xaaa31337c001d00dLL;
153         long long v1 = 0xdeadbeefdeafcafeLL;
154         long long v2 = 0xfaceabadf00df001LL;
155         long long onestwos = 0x1111111122222222LL;
156         long long one = 1LL;
157
158         atomic64_t v = ATOMIC64_INIT(v0);
159         long long r = v0;
160         BUG_ON(v.counter != r);
161
162         atomic64_set(&v, v1);
163         r = v1;
164         BUG_ON(v.counter != r);
165         BUG_ON(atomic64_read(&v) != r);
166
167         TEST(64, add, +=, onestwos);
168         TEST(64, add, +=, -one);
169         TEST(64, sub, -=, onestwos);
170         TEST(64, sub, -=, -one);
171         TEST(64, or, |=, v1);
172         TEST(64, and, &=, v1);
173         TEST(64, xor, ^=, v1);
174         TEST(64, andnot, &= ~, v1);
175
176         RETURN_FAMILY_TEST(64, add_return, +=, onestwos);
177         RETURN_FAMILY_TEST(64, add_return, +=, -one);
178         RETURN_FAMILY_TEST(64, sub_return, -=, onestwos);
179         RETURN_FAMILY_TEST(64, sub_return, -=, -one);
180
181         FETCH_FAMILY_TEST(64, fetch_add, +=, onestwos);
182         FETCH_FAMILY_TEST(64, fetch_add, +=, -one);
183         FETCH_FAMILY_TEST(64, fetch_sub, -=, onestwos);
184         FETCH_FAMILY_TEST(64, fetch_sub, -=, -one);
185
186         FETCH_FAMILY_TEST(64, fetch_or,  |=, v1);
187         FETCH_FAMILY_TEST(64, fetch_and, &=, v1);
188         FETCH_FAMILY_TEST(64, fetch_andnot, &= ~, v1);
189         FETCH_FAMILY_TEST(64, fetch_xor, ^=, v1);
190
191         INIT(v0);
192         atomic64_inc(&v);
193         r += one;
194         BUG_ON(v.counter != r);
195
196         INIT(v0);
197         atomic64_dec(&v);
198         r -= one;
199         BUG_ON(v.counter != r);
200
201         INC_RETURN_FAMILY_TEST(64, v0);
202         DEC_RETURN_FAMILY_TEST(64, v0);
203
204         XCHG_FAMILY_TEST(64, v0, v1);
205         CMPXCHG_FAMILY_TEST(64, v0, v1, v2);
206
207         INIT(v0);
208         BUG_ON(atomic64_add_unless(&v, one, v0));
209         BUG_ON(v.counter != r);
210
211         INIT(v0);
212         BUG_ON(!atomic64_add_unless(&v, one, v1));
213         r += one;
214         BUG_ON(v.counter != r);
215
216 #ifdef CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
217         INIT(onestwos);
218         BUG_ON(atomic64_dec_if_positive(&v) != (onestwos - 1));
219         r -= one;
220         BUG_ON(v.counter != r);
221
222         INIT(0);
223         BUG_ON(atomic64_dec_if_positive(&v) != -one);
224         BUG_ON(v.counter != r);
225
226         INIT(-one);
227         BUG_ON(atomic64_dec_if_positive(&v) != (-one - one));
228         BUG_ON(v.counter != r);
229 #else
230 #warning Please implement atomic64_dec_if_positive for your architecture and select the above Kconfig symbol
231 #endif
232
233         INIT(onestwos);
234         BUG_ON(!atomic64_inc_not_zero(&v));
235         r += one;
236         BUG_ON(v.counter != r);
237
238         INIT(0);
239         BUG_ON(atomic64_inc_not_zero(&v));
240         BUG_ON(v.counter != r);
241
242         INIT(-one);
243         BUG_ON(!atomic64_inc_not_zero(&v));
244         r += one;
245         BUG_ON(v.counter != r);
246 }
247
248 static __init int test_atomics(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_CMPXCHG64)
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 core_initcall(test_atomics);