Hi Peter, On Mon, Dec 19, 2022 at 04:35:25PM +0100, Peter Zijlstra wrote: > Hi, > > Since Linus hated on cmpxchg_double(), a few patches to get rid of it, as proposed here: > > https://lkml.kernel.org/r/Y2U3WdU61FvYlpUh@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx > > based on tip/master because Linus' tree is moving a wee bit fast at the moment. > > 0day robot is all green for building, very limited testing on arm64/s390 > for obvious raisins -- I tried to get the asm right, but please, double > check. > I added some test cases for cmpxcgh128 APIs, and found two issues. I will reply separately in the patches. The test cases themselves are at the end, let me know if you want to me to send a proper patch. Regards, Boqun ------------------------------------------------------------>8 Subject: [PATCH] atomic: Add test cases for cmpxchg128 family Besides for 32bit and 64bit cmpxchg, we only test via atomic_cmpxchg_* APIs, add tests via cmpxchg* APIs while we are at it. Signed-off-by: Boqun Feng <boqun.feng@xxxxxxxxx> --- lib/atomic64_test.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/lib/atomic64_test.c b/lib/atomic64_test.c index d9d170238165..7f79d0704ba8 100644 --- a/lib/atomic64_test.c +++ b/lib/atomic64_test.c @@ -76,12 +76,19 @@ do { \ BUG_ON(atomic##bit##_read(&v) != expect); \ } while (0) +#define TEST_ARGS_PLAIN(_, op, init, ret, expect, args...) \ +do { \ + __WRITE_ONCE(n, init); \ + BUG_ON(op(&n, ##args) != ret); \ + BUG_ON(__READ_ONCE(n) != 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) \ +#define ATOMIC_CMPXCHG_FAMILY_TEST(bit, init, new, wrong) \ do { \ FAMILY_TEST(TEST_ARGS, bit, cmpxchg, \ init, init, new, init, new); \ @@ -89,6 +96,14 @@ do { \ init, init, init, wrong, new); \ } while (0) +#define CMPXCHG_FAMILY_TEST(bit, init, new, wrong) \ +do { \ + FAMILY_TEST(TEST_ARGS_PLAIN, _, cmpxchg##bit, \ + init, init, new, init, new); \ + FAMILY_TEST(TEST_ARGS_PLAIN, _, cmpxchg##bit, \ + init, init, init, wrong, new); \ +} while (0) + #define INC_RETURN_FAMILY_TEST(bit, i) \ do { \ FAMILY_TEST(TEST_ARGS, bit, inc_return, \ @@ -109,6 +124,7 @@ static __init void test_atomic(void) int one = 1; atomic_t v; + int n; int r; TEST(, add, +=, onestwos); @@ -139,6 +155,7 @@ static __init void test_atomic(void) DEC_RETURN_FAMILY_TEST(, v0); XCHG_FAMILY_TEST(, v0, v1); + ATOMIC_CMPXCHG_FAMILY_TEST(, v0, v1, onestwos); CMPXCHG_FAMILY_TEST(, v0, v1, onestwos); } @@ -155,6 +172,7 @@ static __init void test_atomic64(void) int r_int; atomic64_t v = ATOMIC64_INIT(v0); + long long n = 0; long long r = v0; BUG_ON(v.counter != r); @@ -201,6 +219,7 @@ static __init void test_atomic64(void) DEC_RETURN_FAMILY_TEST(64, v0); XCHG_FAMILY_TEST(64, v0, v1); + ATOMIC_CMPXCHG_FAMILY_TEST(64, v0, v1, v2); CMPXCHG_FAMILY_TEST(64, v0, v1, v2); INIT(v0); @@ -245,10 +264,30 @@ static __init void test_atomic64(void) BUG_ON(!r_int); } +#ifdef system_has_cmpxchg128 +static __init void test_atomic128(void) +{ + long long v0 = 0xaaa31337c001d00dLL; + long long v1 = 0xdeadbeefdeafcafeLL; + long long v2 = 0xfaceabadf00df001LL; + long long v3 = 0x8000000000000000LL; + + s128 init = ((s128)v0 << 64) + v1; + s128 new = ((s128)v1 << 64) + v0; + s128 wrong = ((s128)v2 << 64) + v3; + s128 n = 1; + + CMPXCHG_FAMILY_TEST(128, init, new, wrong); +} +#else +static __init void test_atomic128(void) {} +#endif + static __init int test_atomics_init(void) { test_atomic(); test_atomic64(); + test_atomic128(); #ifdef CONFIG_X86 pr_info("passed for %s platform %s CX8 and %s SSE\n", -- 2.38.1