diff options
-rw-r--r-- | arch/s390/include/asm/atomic_ops.h | 44 |
1 files changed, 37 insertions, 7 deletions
diff --git a/arch/s390/include/asm/atomic_ops.h b/arch/s390/include/asm/atomic_ops.h index b028c5309bef..2b379d1d9046 100644 --- a/arch/s390/include/asm/atomic_ops.h +++ b/arch/s390/include/asm/atomic_ops.h @@ -178,26 +178,54 @@ static __always_inline int __atomic_cmpxchg(int *ptr, int old, int new) return old; } +static __always_inline long __atomic64_cmpxchg(long *ptr, long old, long new) +{ + asm volatile( + " csg %[old],%[new],%[ptr]" + : [old] "+d" (old), [ptr] "+QS" (*ptr) + : [new] "d" (new) + : "cc", "memory"); + return old; +} + +#ifdef __GCC_ASM_FLAG_OUTPUTS__ + static __always_inline bool __atomic_cmpxchg_bool(int *ptr, int old, int new) { - int old_expected = old; + int cc; asm volatile( " cs %[old],%[new],%[ptr]" - : [old] "+d" (old), [ptr] "+Q" (*ptr) + : [old] "+d" (old), [ptr] "+Q" (*ptr), "=@cc" (cc) : [new] "d" (new) - : "cc", "memory"); - return old == old_expected; + : "memory"); + return cc == 0; } -static __always_inline long __atomic64_cmpxchg(long *ptr, long old, long new) +static __always_inline bool __atomic64_cmpxchg_bool(long *ptr, long old, long new) { + int cc; + asm volatile( " csg %[old],%[new],%[ptr]" - : [old] "+d" (old), [ptr] "+QS" (*ptr) + : [old] "+d" (old), [ptr] "+QS" (*ptr), "=@cc" (cc) + : [new] "d" (new) + : "memory"); + return cc == 0; +} + +#else /* __GCC_ASM_FLAG_OUTPUTS__ */ + +static __always_inline bool __atomic_cmpxchg_bool(int *ptr, int old, int new) +{ + int old_expected = old; + + asm volatile( + " cs %[old],%[new],%[ptr]" + : [old] "+d" (old), [ptr] "+Q" (*ptr) : [new] "d" (new) : "cc", "memory"); - return old; + return old == old_expected; } static __always_inline bool __atomic64_cmpxchg_bool(long *ptr, long old, long new) @@ -212,4 +240,6 @@ static __always_inline bool __atomic64_cmpxchg_bool(long *ptr, long old, long ne return old == old_expected; } +#endif /* __GCC_ASM_FLAG_OUTPUTS__ */ + #endif /* __ARCH_S390_ATOMIC_OPS__ */ |