X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=include%2Fasm-mips%2Fatomic.h;h=c8c6a5a8c5aa7aa42de1f660189b5a629dcbb571;hb=9bf4aaab3e101692164d49b7ca357651eb691cb6;hp=1262c6eafb955f5c73fe3bee9a05d88b45d7c59b;hpb=db216c3d5e4c040e557a50f8f5d35d5c415e8c1c;p=linux-2.6.git diff --git a/include/asm-mips/atomic.h b/include/asm-mips/atomic.h index 1262c6eaf..c8c6a5a8c 100644 --- a/include/asm-mips/atomic.h +++ b/include/asm-mips/atomic.h @@ -9,7 +9,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996, 97, 99, 2000, 03 by Ralf Baechle + * Copyright (C) 1996, 97, 99, 2000, 03, 04 by Ralf Baechle */ /* @@ -127,6 +127,32 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v) return result; } +/* + * atomic_sub_if_positive - add integer to atomic variable + * @v: pointer of type atomic_t + * + * Atomically test @v and decrement if it is greater than 0. + * The function returns the old value of @v minus 1. + */ +static __inline__ int atomic_sub_if_positive(int i, atomic_t * v) +{ + unsigned long temp, result; + + __asm__ __volatile__( + "1: ll %1, %2 # atomic_sub_if_positive\n" + " subu %0, %1, %3 \n" + " bltz %0, 1f \n" + " sc %0, %2 \n" + " beqz %0, 1b \n" + " sync \n" + "1: \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); + + return result; +} + #else /* @@ -192,6 +218,28 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v) return temp; } +/* + * atomic_sub_if_positive - add integer to atomic variable + * @v: pointer of type atomic_t + * + * Atomically test @v and decrement if it is greater than 0. + * The function returns the old value of @v minus 1. + */ +static __inline__ int atomic_sub_if_positive(int i, atomic_t * v) +{ + unsigned long flags; + int temp; + + spin_lock_irqsave(&atomic_lock, flags); + temp = v->counter; + temp -= i; + if (temp >= 0) + v->counter = temp; + spin_unlock_irqrestore(&atomic_lock, flags); + + return temp; +} + #endif /* CONFIG_CPU_HAS_LLSC */ #define atomic_dec_return(v) atomic_sub_return(1,(v)) @@ -228,6 +276,12 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v) */ #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0) +/* + * atomic_dec_if_positive - decrement by 1 if old value positive + * @v: pointer of type atomic_t + */ +#define atomic_dec_if_positive(v) atomic_sub_if_positive(1, v) + /* * atomic_inc - increment atomic variable * @v: pointer of type atomic_t @@ -284,7 +338,7 @@ typedef struct { volatile __s64 counter; } atomic64_t; * * Atomically adds @i to @v. */ -static __inline__ void atomic64_add(int i, atomic64_t * v) +static __inline__ void atomic64_add(long i, atomic64_t * v) { unsigned long temp; @@ -304,7 +358,7 @@ static __inline__ void atomic64_add(int i, atomic64_t * v) * * Atomically subtracts @i from @v. */ -static __inline__ void atomic64_sub(int i, atomic64_t * v) +static __inline__ void atomic64_sub(long i, atomic64_t * v) { unsigned long temp; @@ -320,7 +374,7 @@ static __inline__ void atomic64_sub(int i, atomic64_t * v) /* * Same as above, but return the result value */ -static __inline__ int atomic64_add_return(int i, atomic64_t * v) +static __inline__ long atomic64_add_return(long i, atomic64_t * v) { unsigned long temp, result; @@ -338,7 +392,7 @@ static __inline__ int atomic64_add_return(int i, atomic64_t * v) return result; } -static __inline__ int atomic64_sub_return(int i, atomic64_t * v) +static __inline__ long atomic64_sub_return(long i, atomic64_t * v) { unsigned long temp, result; @@ -356,6 +410,32 @@ static __inline__ int atomic64_sub_return(int i, atomic64_t * v) return result; } +/* + * atomic64_sub_if_positive - add integer to atomic variable + * @v: pointer of type atomic64_t + * + * Atomically test @v and decrement if it is greater than 0. + * The function returns the old value of @v minus 1. + */ +static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v) +{ + unsigned long temp, result; + + __asm__ __volatile__( + "1: lld %1, %2 # atomic64_sub_if_positive\n" + " dsubu %0, %1, %3 \n" + " bltz %0, 1f \n" + " scd %0, %2 \n" + " beqz %0, 1b \n" + " sync \n" + "1: \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); + + return result; +} + #else /* @@ -368,7 +448,7 @@ static __inline__ int atomic64_sub_return(int i, atomic64_t * v) * * Atomically adds @i to @v. */ -static __inline__ void atomic64_add(int i, atomic64_t * v) +static __inline__ void atomic64_add(long i, atomic64_t * v) { unsigned long flags; @@ -384,7 +464,7 @@ static __inline__ void atomic64_add(int i, atomic64_t * v) * * Atomically subtracts @i from @v. */ -static __inline__ void atomic64_sub(int i, atomic64_t * v) +static __inline__ void atomic64_sub(long i, atomic64_t * v) { unsigned long flags; @@ -393,10 +473,10 @@ static __inline__ void atomic64_sub(int i, atomic64_t * v) spin_unlock_irqrestore(&atomic_lock, flags); } -static __inline__ int atomic64_add_return(int i, atomic64_t * v) +static __inline__ long atomic64_add_return(long i, atomic64_t * v) { unsigned long flags; - int temp; + long temp; spin_lock_irqsave(&atomic_lock, flags); temp = v->counter; @@ -407,10 +487,10 @@ static __inline__ int atomic64_add_return(int i, atomic64_t * v) return temp; } -static __inline__ int atomic64_sub_return(int i, atomic64_t * v) +static __inline__ long atomic64_sub_return(long i, atomic64_t * v) { unsigned long flags; - int temp; + long temp; spin_lock_irqsave(&atomic_lock, flags); temp = v->counter; @@ -421,6 +501,28 @@ static __inline__ int atomic64_sub_return(int i, atomic64_t * v) return temp; } +/* + * atomic64_sub_if_positive - add integer to atomic variable + * @v: pointer of type atomic64_t + * + * Atomically test @v and decrement if it is greater than 0. + * The function returns the old value of @v minus 1. + */ +static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v) +{ + unsigned long flags; + long temp; + + spin_lock_irqsave(&atomic_lock, flags); + temp = v->counter; + temp -= i; + if (temp >= 0) + v->counter = temp; + spin_unlock_irqrestore(&atomic_lock, flags); + + return temp; +} + #endif /* CONFIG_CPU_HAS_LLDSCD */ #define atomic64_dec_return(v) atomic64_sub_return(1,(v)) @@ -457,6 +559,12 @@ static __inline__ int atomic64_sub_return(int i, atomic64_t * v) */ #define atomic64_dec_and_test(v) (atomic64_sub_return(1, (v)) == 0) +/* + * atomic64_dec_if_positive - decrement by 1 if old value positive + * @v: pointer of type atomic64_t + */ +#define atomic64_dec_if_positive(v) atomic64_sub_if_positive(1, v) + /* * atomic64_inc - increment atomic variable * @v: pointer of type atomic64_t