Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Testsuite for atomic64_t functions
0004  *
0005  * Copyright © 2010  Luca Barbieri
0006  */
0007 
0008 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0009 
0010 #include <linux/init.h>
0011 #include <linux/bug.h>
0012 #include <linux/kernel.h>
0013 #include <linux/atomic.h>
0014 #include <linux/module.h>
0015 
0016 #ifdef CONFIG_X86
0017 #include <asm/cpufeature.h> /* for boot_cpu_has below */
0018 #endif
0019 
0020 #define TEST(bit, op, c_op, val)                \
0021 do {                                \
0022     atomic##bit##_set(&v, v0);              \
0023     r = v0;                         \
0024     atomic##bit##_##op(val, &v);                \
0025     r c_op val;                     \
0026     WARN(atomic##bit##_read(&v) != r, "%Lx != %Lx\n",   \
0027         (unsigned long long)atomic##bit##_read(&v), \
0028         (unsigned long long)r);             \
0029 } while (0)
0030 
0031 /*
0032  * Test for a atomic operation family,
0033  * @test should be a macro accepting parameters (bit, op, ...)
0034  */
0035 
0036 #define FAMILY_TEST(test, bit, op, args...) \
0037 do {                        \
0038     test(bit, op, ##args);      \
0039     test(bit, op##_acquire, ##args);    \
0040     test(bit, op##_release, ##args);    \
0041     test(bit, op##_relaxed, ##args);    \
0042 } while (0)
0043 
0044 #define TEST_RETURN(bit, op, c_op, val)             \
0045 do {                                \
0046     atomic##bit##_set(&v, v0);              \
0047     r = v0;                         \
0048     r c_op val;                     \
0049     BUG_ON(atomic##bit##_##op(val, &v) != r);       \
0050     BUG_ON(atomic##bit##_read(&v) != r);            \
0051 } while (0)
0052 
0053 #define TEST_FETCH(bit, op, c_op, val)              \
0054 do {                                \
0055     atomic##bit##_set(&v, v0);              \
0056     r = v0;                         \
0057     r c_op val;                     \
0058     BUG_ON(atomic##bit##_##op(val, &v) != v0);      \
0059     BUG_ON(atomic##bit##_read(&v) != r);            \
0060 } while (0)
0061 
0062 #define RETURN_FAMILY_TEST(bit, op, c_op, val)          \
0063 do {                                \
0064     FAMILY_TEST(TEST_RETURN, bit, op, c_op, val);       \
0065 } while (0)
0066 
0067 #define FETCH_FAMILY_TEST(bit, op, c_op, val)           \
0068 do {                                \
0069     FAMILY_TEST(TEST_FETCH, bit, op, c_op, val);        \
0070 } while (0)
0071 
0072 #define TEST_ARGS(bit, op, init, ret, expect, args...)      \
0073 do {                                \
0074     atomic##bit##_set(&v, init);                \
0075     BUG_ON(atomic##bit##_##op(&v, ##args) != ret);      \
0076     BUG_ON(atomic##bit##_read(&v) != expect);       \
0077 } while (0)
0078 
0079 #define XCHG_FAMILY_TEST(bit, init, new)                \
0080 do {                                    \
0081     FAMILY_TEST(TEST_ARGS, bit, xchg, init, init, new, new);    \
0082 } while (0)
0083 
0084 #define CMPXCHG_FAMILY_TEST(bit, init, new, wrong)          \
0085 do {                                    \
0086     FAMILY_TEST(TEST_ARGS, bit, cmpxchg,                \
0087             init, init, new, init, new);            \
0088     FAMILY_TEST(TEST_ARGS, bit, cmpxchg,                \
0089             init, init, init, wrong, new);          \
0090 } while (0)
0091 
0092 #define INC_RETURN_FAMILY_TEST(bit, i)          \
0093 do {                            \
0094     FAMILY_TEST(TEST_ARGS, bit, inc_return,     \
0095             i, (i) + one, (i) + one);   \
0096 } while (0)
0097 
0098 #define DEC_RETURN_FAMILY_TEST(bit, i)          \
0099 do {                            \
0100     FAMILY_TEST(TEST_ARGS, bit, dec_return,     \
0101             i, (i) - one, (i) - one);   \
0102 } while (0)
0103 
0104 static __init void test_atomic(void)
0105 {
0106     int v0 = 0xaaa31337;
0107     int v1 = 0xdeadbeef;
0108     int onestwos = 0x11112222;
0109     int one = 1;
0110 
0111     atomic_t v;
0112     int r;
0113 
0114     TEST(, add, +=, onestwos);
0115     TEST(, add, +=, -one);
0116     TEST(, sub, -=, onestwos);
0117     TEST(, sub, -=, -one);
0118     TEST(, or, |=, v1);
0119     TEST(, and, &=, v1);
0120     TEST(, xor, ^=, v1);
0121     TEST(, andnot, &= ~, v1);
0122 
0123     RETURN_FAMILY_TEST(, add_return, +=, onestwos);
0124     RETURN_FAMILY_TEST(, add_return, +=, -one);
0125     RETURN_FAMILY_TEST(, sub_return, -=, onestwos);
0126     RETURN_FAMILY_TEST(, sub_return, -=, -one);
0127 
0128     FETCH_FAMILY_TEST(, fetch_add, +=, onestwos);
0129     FETCH_FAMILY_TEST(, fetch_add, +=, -one);
0130     FETCH_FAMILY_TEST(, fetch_sub, -=, onestwos);
0131     FETCH_FAMILY_TEST(, fetch_sub, -=, -one);
0132 
0133     FETCH_FAMILY_TEST(, fetch_or,  |=, v1);
0134     FETCH_FAMILY_TEST(, fetch_and, &=, v1);
0135     FETCH_FAMILY_TEST(, fetch_andnot, &= ~, v1);
0136     FETCH_FAMILY_TEST(, fetch_xor, ^=, v1);
0137 
0138     INC_RETURN_FAMILY_TEST(, v0);
0139     DEC_RETURN_FAMILY_TEST(, v0);
0140 
0141     XCHG_FAMILY_TEST(, v0, v1);
0142     CMPXCHG_FAMILY_TEST(, v0, v1, onestwos);
0143 
0144 }
0145 
0146 #define INIT(c) do { atomic64_set(&v, c); r = c; } while (0)
0147 static __init void test_atomic64(void)
0148 {
0149     long long v0 = 0xaaa31337c001d00dLL;
0150     long long v1 = 0xdeadbeefdeafcafeLL;
0151     long long v2 = 0xfaceabadf00df001LL;
0152     long long v3 = 0x8000000000000000LL;
0153     long long onestwos = 0x1111111122222222LL;
0154     long long one = 1LL;
0155     int r_int;
0156 
0157     atomic64_t v = ATOMIC64_INIT(v0);
0158     long long r = v0;
0159     BUG_ON(v.counter != r);
0160 
0161     atomic64_set(&v, v1);
0162     r = v1;
0163     BUG_ON(v.counter != r);
0164     BUG_ON(atomic64_read(&v) != r);
0165 
0166     TEST(64, add, +=, onestwos);
0167     TEST(64, add, +=, -one);
0168     TEST(64, sub, -=, onestwos);
0169     TEST(64, sub, -=, -one);
0170     TEST(64, or, |=, v1);
0171     TEST(64, and, &=, v1);
0172     TEST(64, xor, ^=, v1);
0173     TEST(64, andnot, &= ~, v1);
0174 
0175     RETURN_FAMILY_TEST(64, add_return, +=, onestwos);
0176     RETURN_FAMILY_TEST(64, add_return, +=, -one);
0177     RETURN_FAMILY_TEST(64, sub_return, -=, onestwos);
0178     RETURN_FAMILY_TEST(64, sub_return, -=, -one);
0179 
0180     FETCH_FAMILY_TEST(64, fetch_add, +=, onestwos);
0181     FETCH_FAMILY_TEST(64, fetch_add, +=, -one);
0182     FETCH_FAMILY_TEST(64, fetch_sub, -=, onestwos);
0183     FETCH_FAMILY_TEST(64, fetch_sub, -=, -one);
0184 
0185     FETCH_FAMILY_TEST(64, fetch_or,  |=, v1);
0186     FETCH_FAMILY_TEST(64, fetch_and, &=, v1);
0187     FETCH_FAMILY_TEST(64, fetch_andnot, &= ~, v1);
0188     FETCH_FAMILY_TEST(64, fetch_xor, ^=, v1);
0189 
0190     INIT(v0);
0191     atomic64_inc(&v);
0192     r += one;
0193     BUG_ON(v.counter != r);
0194 
0195     INIT(v0);
0196     atomic64_dec(&v);
0197     r -= one;
0198     BUG_ON(v.counter != r);
0199 
0200     INC_RETURN_FAMILY_TEST(64, v0);
0201     DEC_RETURN_FAMILY_TEST(64, v0);
0202 
0203     XCHG_FAMILY_TEST(64, v0, v1);
0204     CMPXCHG_FAMILY_TEST(64, v0, v1, v2);
0205 
0206     INIT(v0);
0207     BUG_ON(atomic64_add_unless(&v, one, v0));
0208     BUG_ON(v.counter != r);
0209 
0210     INIT(v0);
0211     BUG_ON(!atomic64_add_unless(&v, one, v1));
0212     r += one;
0213     BUG_ON(v.counter != r);
0214 
0215     INIT(onestwos);
0216     BUG_ON(atomic64_dec_if_positive(&v) != (onestwos - 1));
0217     r -= one;
0218     BUG_ON(v.counter != r);
0219 
0220     INIT(0);
0221     BUG_ON(atomic64_dec_if_positive(&v) != -one);
0222     BUG_ON(v.counter != r);
0223 
0224     INIT(-one);
0225     BUG_ON(atomic64_dec_if_positive(&v) != (-one - one));
0226     BUG_ON(v.counter != r);
0227 
0228     INIT(onestwos);
0229     BUG_ON(!atomic64_inc_not_zero(&v));
0230     r += one;
0231     BUG_ON(v.counter != r);
0232 
0233     INIT(0);
0234     BUG_ON(atomic64_inc_not_zero(&v));
0235     BUG_ON(v.counter != r);
0236 
0237     INIT(-one);
0238     BUG_ON(!atomic64_inc_not_zero(&v));
0239     r += one;
0240     BUG_ON(v.counter != r);
0241 
0242     /* Confirm the return value fits in an int, even if the value doesn't */
0243     INIT(v3);
0244     r_int = atomic64_inc_not_zero(&v);
0245     BUG_ON(!r_int);
0246 }
0247 
0248 static __init int test_atomics_init(void)
0249 {
0250     test_atomic();
0251     test_atomic64();
0252 
0253 #ifdef CONFIG_X86
0254     pr_info("passed for %s platform %s CX8 and %s SSE\n",
0255 #ifdef CONFIG_X86_64
0256         "x86-64",
0257 #elif defined(CONFIG_X86_CMPXCHG64)
0258         "i586+",
0259 #else
0260         "i386+",
0261 #endif
0262            boot_cpu_has(X86_FEATURE_CX8) ? "with" : "without",
0263            boot_cpu_has(X86_FEATURE_XMM) ? "with" : "without");
0264 #else
0265     pr_info("passed\n");
0266 #endif
0267 
0268     return 0;
0269 }
0270 
0271 static __exit void test_atomics_exit(void) {}
0272 
0273 module_init(test_atomics_init);
0274 module_exit(test_atomics_exit);
0275 
0276 MODULE_LICENSE("GPL");