X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fsparc%2Flib%2Fatomic32.c;h=53ddcd9d1e60917b8312f60aa5f293c97f0aaeab;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=e28a6af2a0aff83d17951f7bc5359985420bd3b8;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/arch/sparc/lib/atomic32.c b/arch/sparc/lib/atomic32.c index e28a6af2a..53ddcd9d1 100644 --- a/arch/sparc/lib/atomic32.c +++ b/arch/sparc/lib/atomic32.c @@ -20,8 +20,9 @@ spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] = { #else /* SMP */ +static DEFINE_SPINLOCK(dummy); #define ATOMIC_HASH_SIZE 1 -#define ATOMIC_HASH(a) 0 +#define ATOMIC_HASH(a) (&dummy) #endif /* SMP */ @@ -36,17 +37,81 @@ int __atomic_add_return(int i, atomic_t *v) spin_unlock_irqrestore(ATOMIC_HASH(v), flags); return ret; } +EXPORT_SYMBOL(__atomic_add_return); -void atomic_set(atomic_t *v, int i) +int atomic_cmpxchg(atomic_t *v, int old, int new) { + int ret; unsigned long flags; + spin_lock_irqsave(ATOMIC_HASH(v), flags); + ret = v->counter; + if (likely(ret == old)) + v->counter = new; - v->counter = i; + spin_unlock_irqrestore(ATOMIC_HASH(v), flags); + return ret; +} + +int atomic_add_unless(atomic_t *v, int a, int u) +{ + int ret; + unsigned long flags; + spin_lock_irqsave(ATOMIC_HASH(v), flags); + ret = v->counter; + if (ret != u) + v->counter += a; spin_unlock_irqrestore(ATOMIC_HASH(v), flags); + return ret != u; } -EXPORT_SYMBOL(__atomic_add_return); +/* Atomic operations are already serializing */ +void atomic_set(atomic_t *v, int i) +{ + unsigned long flags; + + spin_lock_irqsave(ATOMIC_HASH(v), flags); + v->counter = i; + spin_unlock_irqrestore(ATOMIC_HASH(v), flags); +} EXPORT_SYMBOL(atomic_set); +unsigned long ___set_bit(unsigned long *addr, unsigned long mask) +{ + unsigned long old, flags; + + spin_lock_irqsave(ATOMIC_HASH(addr), flags); + old = *addr; + *addr = old | mask; + spin_unlock_irqrestore(ATOMIC_HASH(addr), flags); + + return old & mask; +} +EXPORT_SYMBOL(___set_bit); + +unsigned long ___clear_bit(unsigned long *addr, unsigned long mask) +{ + unsigned long old, flags; + + spin_lock_irqsave(ATOMIC_HASH(addr), flags); + old = *addr; + *addr = old & ~mask; + spin_unlock_irqrestore(ATOMIC_HASH(addr), flags); + + return old & mask; +} +EXPORT_SYMBOL(___clear_bit); + +unsigned long ___change_bit(unsigned long *addr, unsigned long mask) +{ + unsigned long old, flags; + + spin_lock_irqsave(ATOMIC_HASH(addr), flags); + old = *addr; + *addr = old ^ mask; + spin_unlock_irqrestore(ATOMIC_HASH(addr), flags); + + return old & mask; +} +EXPORT_SYMBOL(___change_bit);