summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorHeiko Carstens <hca@linux.ibm.com>2024-11-26 14:28:27 +0100
committerHeiko Carstens <hca@linux.ibm.com>2024-11-28 14:14:34 +0100
commit889221c4d78d754023bec8edec13d11a13b3fb51 (patch)
treea24da4365500394d1b004dfd1d50fadaab94b620 /arch
parent84ac96587b2a7a27d2aba250009c45dffb8ab4b6 (diff)
downloadlwn-889221c4d78d754023bec8edec13d11a13b3fb51.tar.gz
lwn-889221c4d78d754023bec8edec13d11a13b3fb51.zip
s390/spinlock: Use flag output constraint for arch_cmpxchg_niai8()
Add a new variant of arch_cmpxchg_niai8() which makes use of the flag output constraint, which allows the compiler to generate slightly better code. Also rename arch_cmpxchg_niai8() to arch_try_cmpxchg_niai8() which reflects the purpose of the function and makes it consistent with other "try" variants. Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/lib/spinlock.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c
index c27c0f2a8018..a81a01c44927 100644
--- a/arch/s390/lib/spinlock.c
+++ b/arch/s390/lib/spinlock.c
@@ -15,6 +15,7 @@
#include <linux/percpu.h>
#include <linux/io.h>
#include <asm/alternative.h>
+#include <asm/asm.h>
int spin_retry = -1;
@@ -81,7 +82,24 @@ static inline int arch_load_niai4(int *lock)
return owner;
}
-static inline int arch_cmpxchg_niai8(int *lock, int old, int new)
+#ifdef __HAVE_ASM_FLAG_OUTPUTS__
+
+static inline int arch_try_cmpxchg_niai8(int *lock, int old, int new)
+{
+ int cc;
+
+ asm_inline volatile(
+ ALTERNATIVE("nop", ".insn rre,0xb2fa0000,8,0", ALT_FACILITY(49)) /* NIAI 8 */
+ " cs %[old],%[new],%[lock]\n"
+ : [old] "+d" (old), [lock] "+Q" (*lock), "=@cc" (cc)
+ : [new] "d" (new)
+ : "memory");
+ return cc == 0;
+}
+
+#else /* __HAVE_ASM_FLAG_OUTPUTS__ */
+
+static inline int arch_try_cmpxchg_niai8(int *lock, int old, int new)
{
int expected = old;
@@ -94,6 +112,8 @@ static inline int arch_cmpxchg_niai8(int *lock, int old, int new)
return expected == old;
}
+#endif /* __HAVE_ASM_FLAG_OUTPUTS__ */
+
static inline struct spin_wait *arch_spin_decode_tail(int lock)
{
int ix, cpu;
@@ -226,7 +246,7 @@ static inline void arch_spin_lock_classic(arch_spinlock_t *lp)
/* Try to get the lock if it is free. */
if (!owner) {
new = (old & _Q_TAIL_MASK) | lockval;
- if (arch_cmpxchg_niai8(&lp->lock, old, new)) {
+ if (arch_try_cmpxchg_niai8(&lp->lock, old, new)) {
/* Got the lock */
return;
}