diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-23 23:44:19 -0500 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-23 23:44:19 -0500 |
| commit | 1ebbe2b20091d306453a5cf480a87e6cd28ae76f (patch) | |
| tree | f5cd7a0fa69b8b1938cb5a0faed2e7b0628072a5 /include/asm-powerpc/atomic.h | |
| parent | ac58c9059da8886b5e8cde012a80266b18ca146e (diff) | |
| parent | 674a396c6d2ba0341ebdd7c1c9950f32f018e2dd (diff) | |
Merge branch 'linus'
Diffstat (limited to 'include/asm-powerpc/atomic.h')
| -rw-r--r-- | include/asm-powerpc/atomic.h | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h index 147a38dcc766..bb3c0ab7e667 100644 --- a/include/asm-powerpc/atomic.h +++ b/include/asm-powerpc/atomic.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | typedef struct { volatile int counter; } atomic_t; | 8 | typedef struct { volatile int counter; } atomic_t; |
| 9 | 9 | ||
| 10 | #ifdef __KERNEL__ | 10 | #ifdef __KERNEL__ |
| 11 | #include <linux/compiler.h> | ||
| 11 | #include <asm/synch.h> | 12 | #include <asm/synch.h> |
| 12 | #include <asm/asm-compat.h> | 13 | #include <asm/asm-compat.h> |
| 13 | 14 | ||
| @@ -176,20 +177,29 @@ static __inline__ int atomic_dec_return(atomic_t *v) | |||
| 176 | * Atomically adds @a to @v, so long as it was not @u. | 177 | * Atomically adds @a to @v, so long as it was not @u. |
| 177 | * Returns non-zero if @v was not @u, and zero otherwise. | 178 | * Returns non-zero if @v was not @u, and zero otherwise. |
| 178 | */ | 179 | */ |
| 179 | #define atomic_add_unless(v, a, u) \ | 180 | static __inline__ int atomic_add_unless(atomic_t *v, int a, int u) |
| 180 | ({ \ | 181 | { |
| 181 | int c, old; \ | 182 | int t; |
| 182 | c = atomic_read(v); \ | 183 | |
| 183 | for (;;) { \ | 184 | __asm__ __volatile__ ( |
| 184 | if (unlikely(c == (u))) \ | 185 | LWSYNC_ON_SMP |
| 185 | break; \ | 186 | "1: lwarx %0,0,%1 # atomic_add_unless\n\ |
| 186 | old = atomic_cmpxchg((v), c, c + (a)); \ | 187 | cmpw 0,%0,%3 \n\ |
| 187 | if (likely(old == c)) \ | 188 | beq- 2f \n\ |
| 188 | break; \ | 189 | add %0,%2,%0 \n" |
| 189 | c = old; \ | 190 | PPC405_ERR77(0,%2) |
| 190 | } \ | 191 | " stwcx. %0,0,%1 \n\ |
| 191 | c != (u); \ | 192 | bne- 1b \n" |
| 192 | }) | 193 | ISYNC_ON_SMP |
| 194 | " subf %0,%2,%0 \n\ | ||
| 195 | 2:" | ||
| 196 | : "=&r" (t) | ||
| 197 | : "r" (&v->counter), "r" (a), "r" (u) | ||
| 198 | : "cc", "memory"); | ||
| 199 | |||
| 200 | return t != u; | ||
| 201 | } | ||
| 202 | |||
| 193 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | 203 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) |
| 194 | 204 | ||
| 195 | #define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0) | 205 | #define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0) |
