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/processor.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 static __init void test_atomic(void) 35 { 36 int v0 = 0xaaa31337; 37 int v1 = 0xdeadbeef; 38 int onestwos = 0x11112222; 39 int one = 1; 40 41 atomic_t v; 42 int r; 43 44 TEST(, add, +=, onestwos); 45 TEST(, add, +=, -one); 46 TEST(, sub, -=, onestwos); 47 TEST(, sub, -=, -one); 48 TEST(, or, |=, v1); 49 TEST(, and, &=, v1); 50 TEST(, xor, ^=, v1); 51 TEST(, andnot, &= ~, v1); 52 } 53 54 #define INIT(c) do { atomic64_set(&v, c); r = c; } while (0) 55 static __init void test_atomic64(void) 56 { 57 long long v0 = 0xaaa31337c001d00dLL; 58 long long v1 = 0xdeadbeefdeafcafeLL; 59 long long v2 = 0xfaceabadf00df001LL; 60 long long onestwos = 0x1111111122222222LL; 61 long long one = 1LL; 62 63 atomic64_t v = ATOMIC64_INIT(v0); 64 long long r = v0; 65 BUG_ON(v.counter != r); 66 67 atomic64_set(&v, v1); 68 r = v1; 69 BUG_ON(v.counter != r); 70 BUG_ON(atomic64_read(&v) != r); 71 72 TEST(64, add, +=, onestwos); 73 TEST(64, add, +=, -one); 74 TEST(64, sub, -=, onestwos); 75 TEST(64, sub, -=, -one); 76 TEST(64, or, |=, v1); 77 TEST(64, and, &=, v1); 78 TEST(64, xor, ^=, v1); 79 TEST(64, andnot, &= ~, v1); 80 81 INIT(v0); 82 r += onestwos; 83 BUG_ON(atomic64_add_return(onestwos, &v) != r); 84 BUG_ON(v.counter != r); 85 86 INIT(v0); 87 r += -one; 88 BUG_ON(atomic64_add_return(-one, &v) != r); 89 BUG_ON(v.counter != r); 90 91 INIT(v0); 92 r -= onestwos; 93 BUG_ON(atomic64_sub_return(onestwos, &v) != r); 94 BUG_ON(v.counter != r); 95 96 INIT(v0); 97 r -= -one; 98 BUG_ON(atomic64_sub_return(-one, &v) != r); 99 BUG_ON(v.counter != r); 100 101 INIT(v0); 102 atomic64_inc(&v); 103 r += one; 104 BUG_ON(v.counter != r); 105 106 INIT(v0); 107 r += one; 108 BUG_ON(atomic64_inc_return(&v) != r); 109 BUG_ON(v.counter != r); 110 111 INIT(v0); 112 atomic64_dec(&v); 113 r -= one; 114 BUG_ON(v.counter != r); 115 116 INIT(v0); 117 r -= one; 118 BUG_ON(atomic64_dec_return(&v) != r); 119 BUG_ON(v.counter != r); 120 121 INIT(v0); 122 BUG_ON(atomic64_xchg(&v, v1) != v0); 123 r = v1; 124 BUG_ON(v.counter != r); 125 126 INIT(v0); 127 BUG_ON(atomic64_cmpxchg(&v, v0, v1) != v0); 128 r = v1; 129 BUG_ON(v.counter != r); 130 131 INIT(v0); 132 BUG_ON(atomic64_cmpxchg(&v, v2, v1) != v0); 133 BUG_ON(v.counter != r); 134 135 INIT(v0); 136 BUG_ON(atomic64_add_unless(&v, one, v0)); 137 BUG_ON(v.counter != r); 138 139 INIT(v0); 140 BUG_ON(!atomic64_add_unless(&v, one, v1)); 141 r += one; 142 BUG_ON(v.counter != r); 143 144 #ifdef CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE 145 INIT(onestwos); 146 BUG_ON(atomic64_dec_if_positive(&v) != (onestwos - 1)); 147 r -= one; 148 BUG_ON(v.counter != r); 149 150 INIT(0); 151 BUG_ON(atomic64_dec_if_positive(&v) != -one); 152 BUG_ON(v.counter != r); 153 154 INIT(-one); 155 BUG_ON(atomic64_dec_if_positive(&v) != (-one - one)); 156 BUG_ON(v.counter != r); 157 #else 158 #warning Please implement atomic64_dec_if_positive for your architecture and select the above Kconfig symbol 159 #endif 160 161 INIT(onestwos); 162 BUG_ON(!atomic64_inc_not_zero(&v)); 163 r += one; 164 BUG_ON(v.counter != r); 165 166 INIT(0); 167 BUG_ON(atomic64_inc_not_zero(&v)); 168 BUG_ON(v.counter != r); 169 170 INIT(-one); 171 BUG_ON(!atomic64_inc_not_zero(&v)); 172 r += one; 173 BUG_ON(v.counter != r); 174 } 175 176 static __init int test_atomics(void) 177 { 178 test_atomic(); 179 test_atomic64(); 180 181 #ifdef CONFIG_X86 182 pr_info("passed for %s platform %s CX8 and %s SSE\n", 183 #ifdef CONFIG_X86_64 184 "x86-64", 185 #elif defined(CONFIG_X86_CMPXCHG64) 186 "i586+", 187 #else 188 "i386+", 189 #endif 190 boot_cpu_has(X86_FEATURE_CX8) ? "with" : "without", 191 boot_cpu_has(X86_FEATURE_XMM) ? "with" : "without"); 192 #else 193 pr_info("passed\n"); 194 #endif 195 196 return 0; 197 } 198 199 core_initcall(test_atomics); 200