diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/atomic64_test.c | 120 |
1 files changed, 79 insertions, 41 deletions
diff --git a/lib/atomic64_test.c b/lib/atomic64_test.c index 83c33a5bcffb..18e422b259cf 100644 --- a/lib/atomic64_test.c +++ b/lib/atomic64_test.c | |||
| @@ -27,6 +27,65 @@ do { \ | |||
| 27 | (unsigned long long)r); \ | 27 | (unsigned long long)r); \ |
| 28 | } while (0) | 28 | } while (0) |
| 29 | 29 | ||
| 30 | /* | ||
| 31 | * Test for a atomic operation family, | ||
| 32 | * @test should be a macro accepting parameters (bit, op, ...) | ||
| 33 | */ | ||
| 34 | |||
| 35 | #define FAMILY_TEST(test, bit, op, args...) \ | ||
| 36 | do { \ | ||
| 37 | test(bit, op, ##args); \ | ||
| 38 | test(bit, op##_acquire, ##args); \ | ||
| 39 | test(bit, op##_release, ##args); \ | ||
| 40 | test(bit, op##_relaxed, ##args); \ | ||
| 41 | } while (0) | ||
| 42 | |||
| 43 | #define TEST_RETURN(bit, op, c_op, val) \ | ||
| 44 | do { \ | ||
| 45 | atomic##bit##_set(&v, v0); \ | ||
| 46 | r = v0; \ | ||
| 47 | r c_op val; \ | ||
| 48 | BUG_ON(atomic##bit##_##op(val, &v) != r); \ | ||
| 49 | BUG_ON(atomic##bit##_read(&v) != r); \ | ||
| 50 | } while (0) | ||
| 51 | |||
| 52 | #define RETURN_FAMILY_TEST(bit, op, c_op, val) \ | ||
| 53 | do { \ | ||
| 54 | FAMILY_TEST(TEST_RETURN, bit, op, c_op, val); \ | ||
| 55 | } while (0) | ||
| 56 | |||
| 57 | #define TEST_ARGS(bit, op, init, ret, expect, args...) \ | ||
| 58 | do { \ | ||
| 59 | atomic##bit##_set(&v, init); \ | ||
| 60 | BUG_ON(atomic##bit##_##op(&v, ##args) != ret); \ | ||
| 61 | BUG_ON(atomic##bit##_read(&v) != expect); \ | ||
| 62 | } while (0) | ||
| 63 | |||
| 64 | #define XCHG_FAMILY_TEST(bit, init, new) \ | ||
| 65 | do { \ | ||
| 66 | FAMILY_TEST(TEST_ARGS, bit, xchg, init, init, new, new); \ | ||
| 67 | } while (0) | ||
| 68 | |||
| 69 | #define CMPXCHG_FAMILY_TEST(bit, init, new, wrong) \ | ||
| 70 | do { \ | ||
| 71 | FAMILY_TEST(TEST_ARGS, bit, cmpxchg, \ | ||
| 72 | init, init, new, init, new); \ | ||
| 73 | FAMILY_TEST(TEST_ARGS, bit, cmpxchg, \ | ||
| 74 | init, init, init, wrong, new); \ | ||
| 75 | } while (0) | ||
| 76 | |||
| 77 | #define INC_RETURN_FAMILY_TEST(bit, i) \ | ||
| 78 | do { \ | ||
| 79 | FAMILY_TEST(TEST_ARGS, bit, inc_return, \ | ||
| 80 | i, (i) + one, (i) + one); \ | ||
| 81 | } while (0) | ||
| 82 | |||
| 83 | #define DEC_RETURN_FAMILY_TEST(bit, i) \ | ||
| 84 | do { \ | ||
| 85 | FAMILY_TEST(TEST_ARGS, bit, dec_return, \ | ||
| 86 | i, (i) - one, (i) - one); \ | ||
| 87 | } while (0) | ||
| 88 | |||
| 30 | static __init void test_atomic(void) | 89 | static __init void test_atomic(void) |
| 31 | { | 90 | { |
| 32 | int v0 = 0xaaa31337; | 91 | int v0 = 0xaaa31337; |
| @@ -45,6 +104,18 @@ static __init void test_atomic(void) | |||
| 45 | TEST(, and, &=, v1); | 104 | TEST(, and, &=, v1); |
| 46 | TEST(, xor, ^=, v1); | 105 | TEST(, xor, ^=, v1); |
| 47 | TEST(, andnot, &= ~, v1); | 106 | TEST(, andnot, &= ~, v1); |
| 107 | |||
| 108 | RETURN_FAMILY_TEST(, add_return, +=, onestwos); | ||
| 109 | RETURN_FAMILY_TEST(, add_return, +=, -one); | ||
| 110 | RETURN_FAMILY_TEST(, sub_return, -=, onestwos); | ||
| 111 | RETURN_FAMILY_TEST(, sub_return, -=, -one); | ||
| 112 | |||
| 113 | INC_RETURN_FAMILY_TEST(, v0); | ||
| 114 | DEC_RETURN_FAMILY_TEST(, v0); | ||
| 115 | |||
| 116 | XCHG_FAMILY_TEST(, v0, v1); | ||
| 117 | CMPXCHG_FAMILY_TEST(, v0, v1, onestwos); | ||
| 118 | |||
| 48 | } | 119 | } |
| 49 | 120 | ||
| 50 | #define INIT(c) do { atomic64_set(&v, c); r = c; } while (0) | 121 | #define INIT(c) do { atomic64_set(&v, c); r = c; } while (0) |
| @@ -74,25 +145,10 @@ static __init void test_atomic64(void) | |||
| 74 | TEST(64, xor, ^=, v1); | 145 | TEST(64, xor, ^=, v1); |
| 75 | TEST(64, andnot, &= ~, v1); | 146 | TEST(64, andnot, &= ~, v1); |
| 76 | 147 | ||
| 77 | INIT(v0); | 148 | RETURN_FAMILY_TEST(64, add_return, +=, onestwos); |
| 78 | r += onestwos; | 149 | RETURN_FAMILY_TEST(64, add_return, +=, -one); |
| 79 | BUG_ON(atomic64_add_return(onestwos, &v) != r); | 150 | RETURN_FAMILY_TEST(64, sub_return, -=, onestwos); |
| 80 | BUG_ON(v.counter != r); | 151 | RETURN_FAMILY_TEST(64, sub_return, -=, -one); |
| 81 | |||
| 82 | INIT(v0); | ||
| 83 | r += -one; | ||
| 84 | BUG_ON(atomic64_add_return(-one, &v) != r); | ||
| 85 | BUG_ON(v.counter != r); | ||
| 86 | |||
| 87 | INIT(v0); | ||
| 88 | r -= onestwos; | ||
| 89 | BUG_ON(atomic64_sub_return(onestwos, &v) != r); | ||
| 90 | BUG_ON(v.counter != r); | ||
| 91 | |||
| 92 | INIT(v0); | ||
| 93 | r -= -one; | ||
| 94 | BUG_ON(atomic64_sub_return(-one, &v) != r); | ||
| 95 | BUG_ON(v.counter != r); | ||
| 96 | 152 | ||
| 97 | INIT(v0); | 153 | INIT(v0); |
| 98 | atomic64_inc(&v); | 154 | atomic64_inc(&v); |
| @@ -100,33 +156,15 @@ static __init void test_atomic64(void) | |||
| 100 | BUG_ON(v.counter != r); | 156 | BUG_ON(v.counter != r); |
| 101 | 157 | ||
| 102 | INIT(v0); | 158 | INIT(v0); |
| 103 | r += one; | ||
| 104 | BUG_ON(atomic64_inc_return(&v) != r); | ||
| 105 | BUG_ON(v.counter != r); | ||
| 106 | |||
| 107 | INIT(v0); | ||
| 108 | atomic64_dec(&v); | 159 | atomic64_dec(&v); |
| 109 | r -= one; | 160 | r -= one; |
| 110 | BUG_ON(v.counter != r); | 161 | BUG_ON(v.counter != r); |
| 111 | 162 | ||
| 112 | INIT(v0); | 163 | INC_RETURN_FAMILY_TEST(64, v0); |
| 113 | r -= one; | 164 | DEC_RETURN_FAMILY_TEST(64, v0); |
| 114 | BUG_ON(atomic64_dec_return(&v) != r); | ||
| 115 | BUG_ON(v.counter != r); | ||
| 116 | |||
| 117 | INIT(v0); | ||
| 118 | BUG_ON(atomic64_xchg(&v, v1) != v0); | ||
| 119 | r = v1; | ||
| 120 | BUG_ON(v.counter != r); | ||
| 121 | |||
| 122 | INIT(v0); | ||
| 123 | BUG_ON(atomic64_cmpxchg(&v, v0, v1) != v0); | ||
| 124 | r = v1; | ||
| 125 | BUG_ON(v.counter != r); | ||
| 126 | 165 | ||
| 127 | INIT(v0); | 166 | XCHG_FAMILY_TEST(64, v0, v1); |
| 128 | BUG_ON(atomic64_cmpxchg(&v, v2, v1) != v0); | 167 | CMPXCHG_FAMILY_TEST(64, v0, v1, v2); |
| 129 | BUG_ON(v.counter != r); | ||
| 130 | 168 | ||
| 131 | INIT(v0); | 169 | INIT(v0); |
| 132 | BUG_ON(atomic64_add_unless(&v, one, v0)); | 170 | BUG_ON(atomic64_add_unless(&v, one, v0)); |
