From 748a76b5152e8f38edf8afbf6f4cd6e326ad9e62 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 11 Jul 2013 08:04:20 -0700 Subject: [PATCH] alpha: Implement atomic64_dec_if_positive Reviewed-and-Tested-by: Matt Turner Signed-off-by: Matt Turner Signed-off-by: Richard Henderson --- arch/alpha/Kconfig | 1 + arch/alpha/include/asm/atomic.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 837a1f2d8b96..082d9b4b5472 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -15,6 +15,7 @@ config ALPHA select ARCH_WANT_OPTIONAL_GPIOLIB select ARCH_WANT_IPC_PARSE_VERSION select ARCH_HAVE_NMI_SAFE_CMPXCHG + select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select GENERIC_SMP_IDLE_THREAD select GENERIC_CMOS_UPDATE select GENERIC_STRNCPY_FROM_USER diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h index 0dc18fc4d925..78b03ef39f6f 100644 --- a/arch/alpha/include/asm/atomic.h +++ b/arch/alpha/include/asm/atomic.h @@ -238,6 +238,34 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u) return !c; } +/* + * atomic64_dec_if_positive - decrement by 1 if old value positive + * @v: pointer of type atomic_t + * + * The function returns the old value of *v minus 1, even if + * the atomic variable, v, was not decremented. + */ +static inline long atomic64_dec_if_positive(atomic64_t *v) +{ + long old, tmp; + smp_mb(); + __asm__ __volatile__( + "1: ldq_l %[old],%[mem]\n" + " subq %[old],1,%[tmp]\n" + " ble %[old],2f\n" + " stq_c %[tmp],%[mem]\n" + " beq %[tmp],3f\n" + "2:\n" + ".subsection 2\n" + "3: br 1b\n" + ".previous" + : [old] "=&r"(old), [tmp] "=&r"(tmp) + : [mem] "m"(*v) + : "memory"); + smp_mb(); + return old - 1; +} + #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) #define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)