Re: [RFC][PATCH 00/12] Introduce cmpxchg128() -- aka. the demise of cmpxchg_double()

Boqun Feng
2022-12-22T01:21:44Z

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@hirez.programming.kicks-ass.net
>
> 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@gmail.com>
---
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