Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

alpha: Implement atomic64_dec_if_positive

Reviewed-and-Tested-by: Matt Turner <mattst88@gmail.com>
Signed-off-by: Matt Turner <mattst88@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>

authored by

Richard Henderson and committed by
Matt Turner
748a76b5 6da75397

+29
+1
arch/alpha/Kconfig
··· 15 15 select ARCH_WANT_OPTIONAL_GPIOLIB 16 16 select ARCH_WANT_IPC_PARSE_VERSION 17 17 select ARCH_HAVE_NMI_SAFE_CMPXCHG 18 + select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE 18 19 select GENERIC_SMP_IDLE_THREAD 19 20 select GENERIC_CMOS_UPDATE 20 21 select GENERIC_STRNCPY_FROM_USER
+28
arch/alpha/include/asm/atomic.h
··· 238 238 return !c; 239 239 } 240 240 241 + /* 242 + * atomic64_dec_if_positive - decrement by 1 if old value positive 243 + * @v: pointer of type atomic_t 244 + * 245 + * The function returns the old value of *v minus 1, even if 246 + * the atomic variable, v, was not decremented. 247 + */ 248 + static inline long atomic64_dec_if_positive(atomic64_t *v) 249 + { 250 + long old, tmp; 251 + smp_mb(); 252 + __asm__ __volatile__( 253 + "1: ldq_l %[old],%[mem]\n" 254 + " subq %[old],1,%[tmp]\n" 255 + " ble %[old],2f\n" 256 + " stq_c %[tmp],%[mem]\n" 257 + " beq %[tmp],3f\n" 258 + "2:\n" 259 + ".subsection 2\n" 260 + "3: br 1b\n" 261 + ".previous" 262 + : [old] "=&r"(old), [tmp] "=&r"(tmp) 263 + : [mem] "m"(*v) 264 + : "memory"); 265 + smp_mb(); 266 + return old - 1; 267 + } 268 + 241 269 #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) 242 270 243 271 #define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)