diff options
author | Richard Henderson <rth@twiddle.net> | 2013-07-11 11:04:20 -0400 |
---|---|---|
committer | Matt Turner <mattst88@gmail.com> | 2013-07-19 16:54:24 -0400 |
commit | 748a76b5152e8f38edf8afbf6f4cd6e326ad9e62 (patch) | |
tree | d9df502d39bb7d2c8a689de740b32fb10be14f58 /arch | |
parent | 6da7539734d4e0f5caeea1e0efbb74d7b83db1ca (diff) |
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>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/alpha/Kconfig | 1 | ||||
-rw-r--r-- | arch/alpha/include/asm/atomic.h | 28 |
2 files changed, 29 insertions, 0 deletions
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 | |||
15 | select ARCH_WANT_OPTIONAL_GPIOLIB | 15 | select ARCH_WANT_OPTIONAL_GPIOLIB |
16 | select ARCH_WANT_IPC_PARSE_VERSION | 16 | select ARCH_WANT_IPC_PARSE_VERSION |
17 | select ARCH_HAVE_NMI_SAFE_CMPXCHG | 17 | select ARCH_HAVE_NMI_SAFE_CMPXCHG |
18 | select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE | ||
18 | select GENERIC_SMP_IDLE_THREAD | 19 | select GENERIC_SMP_IDLE_THREAD |
19 | select GENERIC_CMOS_UPDATE | 20 | select GENERIC_CMOS_UPDATE |
20 | select GENERIC_STRNCPY_FROM_USER | 21 | 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) | |||
238 | return !c; | 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 | #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) | 269 | #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) |
242 | 270 | ||
243 | #define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) | 271 | #define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) |