aboutsummaryrefslogtreecommitdiff
path: root/arch/s390/include/asm/atomic.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/include/asm/atomic.h')
-rw-r--r--arch/s390/include/asm/atomic.h19
1 files changed, 19 insertions, 0 deletions
diff --git a/arch/s390/include/asm/atomic.h b/arch/s390/include/asm/atomic.h
index 451bfbb9db3..76daea11718 100644
--- a/arch/s390/include/asm/atomic.h
+++ b/arch/s390/include/asm/atomic.h
@@ -15,6 +15,7 @@
#include <linux/compiler.h>
#include <linux/types.h>
+#include <asm/system.h>
#define ATOMIC_INIT(i) { (i) }
@@ -274,6 +275,7 @@ static inline void atomic64_clear_mask(unsigned long long mask, atomic64_t *v)
static inline int atomic64_add_unless(atomic64_t *v, long long a, long long u)
{
long long c, old;
+
c = atomic64_read(v);
for (;;) {
if (unlikely(c == u))
@@ -286,6 +288,23 @@ static inline int atomic64_add_unless(atomic64_t *v, long long a, long long u)
return c != u;
}
+static inline long long atomic64_dec_if_positive(atomic64_t *v)
+{
+ long long c, old, dec;
+
+ c = atomic64_read(v);
+ for (;;) {
+ dec = c - 1;
+ if (unlikely(dec < 0))
+ break;
+ old = atomic64_cmpxchg((v), c, dec);
+ if (likely(old == c))
+ break;
+ c = old;
+ }
+ return dec;
+}
+
#define atomic64_add(_i, _v) atomic64_add_return(_i, _v)
#define atomic64_add_negative(_i, _v) (atomic64_add_return(_i, _v) < 0)
#define atomic64_inc(_v) atomic64_add_return(1, _v)