atomic primitives again
Subsystems (8)
cover atomic primitives again
It would be nice if these could get in week 2 of the window. Though they'll need wide compile testing (which I haven't been able to provide), actual new arch specific code is limited to ARM.
Compiled and booted on i386 and i686 configs, ppc64.
Signature · 3 lines
SUSE Labs, Novell Inc. Send instant messages to your online friends http://au.messenger.yahoo.com
PATCH 1/5 i386: generic cmpxchg
1/5
oops I can't count.
Signature · 1 line
SUSE Labs, Novell Inc.
Changelog
* Make cmpxchg generally available on the i386 platform.
* Provide emulation of cmpxchg suitable for uniprocessor if built and run on 386.
* Cut down patch and small style changes.
arch/i386/kernel/cpu/intel.c +51 -0
@@ -6,6 +6,7 @@#include <linux/bitops.h> #include <linux/smp.h> #include <linux/thread_info.h> +#include <linux/module.h> #include <asm/processor.h> #include <asm/msr.h>
@@ -264,5 +265,55 @@ __init int intel_cpu_init(void)return 0 ; } +#ifndef CONFIG_X86_CMPXCHG +unsigned long cmpxchg_386_u8 (volatile void *ptr,u8 old,u8 new) +{ +u8 prev; +unsigned long flags; + +/* Poor man's cmpxchg for 386. Unsuitable for SMP */ +local_irq_save (flags); + prev = *(u8 *)ptr; +if (prev == old) + *(u8 *)ptr = new; +local_irq_restore (flags); +return prev; +} + +EXPORT_SYMBOL (cmpxchg_386_u8); + +unsigned long cmpxchg_386_u16 (volatile void *ptr,u16 old,u16 new) +{ +u16 prev; +unsigned long flags; + +/* Poor man's cmpxchg for 386. Unsuitable for SMP */ +local_irq_save (flags); + prev = *(u16 *)ptr; +if (prev == old) + *(u16 *)ptr = new; +local_irq_restore (flags); +return prev; +} + +EXPORT_SYMBOL (cmpxchg_386_u16); + +unsigned long cmpxchg_386_u32 (volatile void *ptr,u32 old,u32 new) +{ +u32 prev; +unsigned long flags; + +/* Poor man's cmpxchg for 386. Unsuitable for SMP */ +local_irq_save (flags); + prev = *(u32 *)ptr; +if (prev == old) + *(u32 *)ptr = new; +local_irq_restore (flags); +return prev; +} + +EXPORT_SYMBOL (cmpxchg_386_u32); +#endif +// arch_initcall(intel_cpu_init);
include/asm-i386/system.h +39 -3
55 lines not on this page · raw message
PATCH 2/5 atomic: cmpxchg
2/5
Signature · 1 line
SUSE Labs, Novell Inc.
Introduce an atomic_cmpxchg operation.
include/asm-i386/atomic.h +2 -0
@@ -215,6 +215,8 @@ static __inline__ int atomic_sub_return(return atomic_add_return (-i,v); } +#define atomic_cmpxchg (v, old, new) ((int)cmpxchg(&((v)->counter), old, new)) +#define atomic_inc_return (v) (atomic_add_return(1,v))#define atomic_dec_return (v) (atomic_sub_return(1,v))
include/asm-ia64/atomic.h +2 -0
@@ -88,6 +88,8 @@ ia64_atomic64_sub (__s64 i, atomic64_t *return new; } +#define atomic_cmpxchg (v, old, new) ((int)cmpxchg(&((v)->counter), old, new)) +#define atomic_add_return (i,v) \ ({ \ int __ia64_aar_i = (i); \
include/asm-x86_64/atomic.h +2 -0
@@ -360,6 +360,8 @@ static __inline__ int atomic_sub_return(return atomic_add_return (-i,v); } +#define atomic_cmpxchg (v, old, new) ((int)cmpxchg(&((v)->counter), old, new)) +#define atomic_inc_return (v) (atomic_add_return(1,v))#define atomic_dec_return (v) (atomic_sub_return(1,v))
Documentation/atomic_ops.txt +15 -0
@@ -115,6 +115,21 @@ boolean is return which indicates whethe is negative. It requires explicit memory barrier semantics around the operation. +Finally: + + int atomic_cmpxchg(atomic_t *v, int old, int new); + +This performs an atomic compare exchange operation on the atomic value v, +with the given old and new values. Like all atomic_xxx operations, +atomic_cmpxchg will only satisfy its atomicity semantics as long as all +other accesses of *v are performed through atomic_xxx operations. + +atomic_cmpxchg requires explicit memory barriers around the operation. + +The semantics for atomic_cmpxchg are the same as those defined for 'cas' +below. + + If a caller requires memory barrier semantics around an atomic_t operation which does not return a value, a set of interfaces are defined which accomplish this:
arch/sparc/lib/atomic32.c +14 -0
@@ -38,6 +38,20 @@ int __atomic_add_return(int i, atomic_treturn ret; } +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; + +spin_unlock_irqrestore (ATOMIC_HASH (v), flags); +return ret; +} +void atomic_set (atomic_t *v,int i) {unsigned long flags;
include/asm-sparc/atomic.h +1 -0
@@ -19,6 +19,7 @@ typedef struct { volatile int counter; }#define ATOMIC_INIT (i) { (i) }extern int __atomic_add_return (int ,atomic_t *); +extern int atomic_cmpxchg (atomic_t *,int ,int );extern void atomic_set (atomic_t *,int );#define atomic_read (v) ((v)->counter)
include/asm-alpha/atomic.h +2 -0
@@ -177,6 +177,8 @@ static __inline__ long atomic64_sub_retureturn result; } +#define atomic_cmpxchg (v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +#define atomic_dec_return (v) atomic_sub_return(1,(v))#define atomic64_dec_return (v) atomic64_sub_return(1,(v))
include/asm-m68k/atomic.h +2 -0
@@ -139,6 +139,8 @@ static inline void atomic_set_mask(unsig __asm__ __volatile__("orl %1,%0" :"+m" (*v) :"id" (mask)); } +#define atomic_cmpxchg (v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +/* Atomic operations are already serializing */ #define smp_mb__before_atomic_dec () barrier()#define smp_mb__after_atomic_dec () barrier()
include/asm-m68knommu/atomic.h +2 -0
@@ -128,6 +128,8 @@ static inline int atomic_sub_return(intreturn temp; } +#define atomic_cmpxchg (v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +#define atomic_dec_return (v) atomic_sub_return(1,(v))#define atomic_inc_return (v) atomic_add_return(1,(v))
include/asm-mips/atomic.h +2 -0
@@ -287,6 +287,8 @@ static __inline__ int atomic_sub_if_posireturn result; } +#define atomic_cmpxchg (v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +#define atomic_dec_return (v) atomic_sub_return(1,(v))#define atomic_inc_return (v) atomic_add_return(1,(v))
include/asm-parisc/atomic.h +1 -0
@@ -164,6 +164,7 @@ static __inline__ int atomic_read(const }/* exported interface */ +#define atomic_cmpxchg (v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))#define atomic_add (i,v) ((void)(__atomic_add_return( ((int)i),(v))))#define atomic_sub (i,v) ((void)(__atomic_add_return(-((int)i),(v))))
include/asm-s390/atomic.h +2 -0
@@ -198,6 +198,8 @@ atomic_compare_and_swap(int expected_oldreturn retval; } +#define atomic_cmpxchg (v, o, n) (atomic_compare_and_swap((o), (n), &((v)->counter))) +#define smp_mb__before_atomic_dec () smp_mb()#define smp_mb__after_atomic_dec () smp_mb()#define smp_mb__before_atomic_inc () smp_mb()
include/asm-sparc64/atomic.h +2 -0
@@ -70,6 +70,8 @@ extern int atomic64_sub_ret(int, atomic6#define atomic_add_negative (i, v) (atomic_add_ret(i, v) < 0)#define atomic64_add_negative (i, v) (atomic64_add_ret(i, v) < 0) +#define atomic_cmpxchg (v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +/* Atomic operations are already serializing */ #ifdef CONFIG_SMP #define smp_mb__before_atomic_dec () membar_storeload_loadload();
include/asm-arm26/atomic.h +14 -0
@@ -62,6 +62,20 @@ static inline int atomic_sub_return(intreturn val; } +static inline int atomic_cmpxchg (atomic_t *v,int old,int new) +{ +int ret; +unsigned long flags; + +local_irq_save (flags); + ret = v->counter; +if (likely (ret == old)) + v->counter = new; +local_irq_restore (flags); + +return ret; +} +static inline void atomic_clear_mask (unsigned long mask,unsigned long *addr) {unsigned long flags;
include/asm-frv/atomic.h +2 -0
@@ -414,4 +414,6 @@ extern uint32_t __cmpxchg_32(uint32_t *v#endif +#define atomic_cmpxchg (v, old, new) ((int)cmpxchg(&((v)->counter), old, new)) +#endif /* _ASM_ATOMIC_H */
include/asm-h8300/atomic.h +12 -0
@@ -82,6 +82,18 @@ static __inline__ int atomic_dec_and_tesreturn ret ==0 ; } +static __inline__int atomic_cmpxchg (atomic_t *v,int old,int new) +{ +int ret; +unsigned long flags; +local_irq_save (flags); + ret = v->counter; +if (likely (ret == old)) + v->counter = new; +local_irq_restore (flags); +return ret; +} +static __inline__void atomic_clear_mask (unsigned long mask,unsigned long *v) { __asm__ __volatile__("stc ccr,r1l\n\t"
include/asm-sh64/atomic.h +14 -0
@@ -99,6 +99,20 @@ static __inline__ int atomic_sub_return(#define atomic_inc (v) atomic_add(1,(v))#define atomic_dec (v) atomic_sub(1,(v)) +static __inline__int atomic_cmpxchg (atomic_t *v,int old,int new) +{ +int ret; +unsigned long flags; + +local_irq_save (flags); + ret = v->counter; +if (likely (ret == old)) + v->counter = new; +local_irq_restore (flags); + +return ret; +} +static __inline__void atomic_clear_mask (unsigned int mask,atomic_t *v) {unsigned long flags;
include/asm-v850/atomic.h +14 -0
@@ -90,6 +90,20 @@ static __inline__ void atomic_clear_mask#define atomic_dec_and_test (v) (atomic_sub_return (1, (v)) == 0)#define atomic_add_negative (i,v) (atomic_add_return ((i), (v)) < 0) +static __inline__int atomic_cmpxchg (atomic_t *v,int old,int new) +{ +int ret; +unsigned long flags; + +local_irq_save (flags); + ret = v->counter; +if (likely (ret == old)) + v->counter = new; +local_irq_restore (flags); + +return ret; +} +/* Atomic operations are already serializing on ARM */ #define smp_mb__before_atomic_dec () barrier()#define smp_mb__after_atomic_dec () barrier()
include/asm-xtensa/atomic.h +1 -0
@@ -223,6 +223,7 @@ static inline int atomic_sub_return(int*/ #define atomic_add_negative (i,v) (atomic_add_return((i),(v)) < 0) +#define atomic_cmpxchg (v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))static inline void atomic_clear_mask (unsigned int mask,atomic_t *v) {
include/asm-sh/atomic.h +14 -0
@@ -87,6 +87,20 @@ static __inline__ int atomic_sub_return(#define atomic_inc (v) atomic_add(1,(v))#define atomic_dec (v) atomic_sub(1,(v)) +static __inline__int atomic_cmpxchg (atomic_t *v,int old,int new) +{ +int ret; +unsigned long flags; + +local_irq_save (flags); + ret = v->counter; +if (likely (ret == old)) + v->counter = new; +local_irq_restore (flags); + +return ret; +} +static __inline__void atomic_clear_mask (unsigned int mask,atomic_t *v) {unsigned long flags;
include/asm-arm/atomic.h +32 -0
@@ -80,6 +80,23 @@ static inline int atomic_sub_return(intreturn result; } +static inline int atomic_cmpxchg (atomic_t *ptr,int old,int new) +{ +u32 oldval, res; + +do { + __asm__ __volatile__("@ atomic_cmpxchg\n" +"ldrex %1, [%2]\n" +"teq %1, %3\n" +"strexeq %0, %4, [%2]\n" + :"=&r" (res),"=&r" (oldval) + :"r" (&ptr->counter),"r" (old),"r" (new) + :"cc" ); + }while (res); + +return oldval; +} +static inline void atomic_clear_mask (unsigned long mask,unsigned long *addr) {unsigned long tmp, tmp2;
@@ -131,6 +148,21 @@ static inline int atomic_sub_return(intreturn val; } +static inline int atomic_cmpxchg (atomic_t *v,int old,int new) +{ +int ret; +unsigned long flags; + +local_irq_save (flags); + ret = v->counter; +if (likely (ret == old)) + v->counter = new; +local_irq_restore (flags); + +return ret; +} + +static inline void atomic_clear_mask (unsigned long mask,unsigned long *addr) static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) {unsigned long flags;
include/asm-cris/atomic.h +13 -0
@@ -123,6 +123,19 @@ extern __inline__ int atomic_inc_and_tesreturn retval; } +static __inline__int atomic_cmpxchg (atomic_t *v,int old,int new) +{ +int ret; +unsigned long flags; +cris_atomic_save (v, flags); + ret = v->counter; +if (likely (ret == old)) + v->counter = new; +cris_atomic_restore (v, flags); +return ret; +} + +static inline void atomic_clear_mask (unsigned long mask,unsigned long *addr) /* Atomic operations are already serializing */#define smp_mb__before_atomic_dec () barrier()#define smp_mb__after_atomic_dec () barrier()
include/asm-powerpc/atomic.h +2 -0
@@ -172,6 +172,8 @@ static __inline__ int atomic_dec_return(return t; } +#define atomic_cmpxchg (v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +#define atomic_sub_and_test (a, v) (atomic_sub_return((a), (v)) == 0)#define atomic_dec_and_test (v) (atomic_dec_return((v)) == 0)
PATCH 3/5 atomic: inc_not_zero
3/5
Signature · 1 line
SUSE Labs, Novell Inc.
Introduce an atomic_inc_not_zero operation. Make this a special case of atomic_add_unless because lockless pagecache actually wants atomic_inc_not_negativeone due to its offset refcount.
include/asm-alpha/atomic.h +10 -0
@@ -179,6 +179,16 @@ static __inline__ long atomic64_sub_retu#define atomic_cmpxchg (v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +#define atomic_add_unless (v, a, u) \ +({ \ + int c, old; \ + c = atomic_read(v); \ + while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ + c = old; \ + c != (u); \ +}) +#define atomic_inc_not_zero (v) atomic_add_unless((v), 1, 0) +#define atomic_dec_return (v) atomic_sub_return(1,(v))#define atomic64_dec_return (v) atomic64_sub_return(1,(v))
include/asm-arm26/atomic.h +15 -0
@@ -76,6 +76,21 @@ static inline int atomic_cmpxchg(atomic_return ret; } +static inline int atomic_add_unless (atomic_t *v,int a,int u) +{ +int ret; +unsigned long flags; + +local_irq_save (flags); + ret = v->counter; +if (ret != u) + v->counter += a; +local_irq_restore (flags); + +return ret != u; +} +#define atomic_inc_not_zero (v) atomic_add_unless((v), 1, 0) +static inline void atomic_clear_mask (unsigned long mask,unsigned long *addr) {unsigned long flags;
include/asm-frv/atomic.h +10 -0
@@ -416,4 +416,14 @@ extern uint32_t __cmpxchg_32(uint32_t *v#define atomic_cmpxchg (v, old, new) ((int)cmpxchg(&((v)->counter), old, new)) +#define atomic_add_unless (v, a, u) \ +({ \ + int c, old; \ + c = atomic_read(v); \ + while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ + c = old; \ + c != (u); \ +}) +#define atomic_inc_not_zero (v) atomic_add_unless((v), 1, 0) +#endif /* _ASM_ATOMIC_H */
include/asm-h8300/atomic.h +13 -0
@@ -94,6 +94,19 @@ static __inline__ int atomic_cmpxchg(atoreturn ret; } +static __inline__int atomic_add_unless (atomic_t *v,int a,int u) +{ +int ret; +unsigned long flags; +local_irq_save (flags); + ret = v->counter; +if (ret != u) + v->counter += a; +local_irq_restore (flags); +return ret != u; +} +#define atomic_inc_not_zero (v) atomic_add_unless((v), 1, 0) +static __inline__void atomic_clear_mask (unsigned long mask,unsigned long *v) { __asm__ __volatile__("stc ccr,r1l\n\t"
include/asm-i386/atomic.h +19 -0
@@ -217,6 +217,25 @@ static __inline__ int atomic_sub_return(#define atomic_cmpxchg (v, old, new) ((int)cmpxchg(&((v)->counter), old, new)) +/** +* atomic_add_unless - add unless the number is a given value +* @v: pointer of type atomic_t +* @a: the amount to add to v... +* @u: ...unless v is equal to u. +* +* Atomically adds @a to @v, so long as it was not @u. +* Returns non-zero if @v was not @u, and zero otherwise. +*/ +#define atomic_add_unless (v, a, u) \ +({ \ + int c, old; \ + c = atomic_read(v); \ + while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ + c = old; \ + c != (u); \ +}) +#define atomic_inc_not_zero (v) atomic_add_unless((v), 1, 0) +#define atomic_inc_return (v) (atomic_add_return(1,v))#define atomic_dec_return (v) (atomic_sub_return(1,v))
include/asm-ia64/atomic.h +10 -0
@@ -90,6 +90,16 @@ ia64_atomic64_sub (__s64 i, atomic64_t *#define atomic_cmpxchg (v, old, new) ((int)cmpxchg(&((v)->counter), old, new)) +#define atomic_add_unless (v, a, u) \ +({ \ + int c, old; \ + c = atomic_read(v); \ + while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ + c = old; \ + c != (u); \ +}) +#define atomic_inc_not_zero (v) atomic_add_unless((v), 1, 0) +#define atomic_add_return (i,v) \ ({ \ int __ia64_aar_i = (i); \
include/asm-m68k/atomic.h +10 -0
@@ -141,6 +141,16 @@ static inline void atomic_set_mask(unsig#define atomic_cmpxchg (v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +#define atomic_add_unless (v, a, u) \ +({ \ + int c, old; \ + c = atomic_read(v); \ + while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ + c = old; \ + c != (u); \ +}) +#define atomic_inc_not_zero (v) atomic_add_unless((v), 1, 0) +/* Atomic operations are already serializing */ #define smp_mb__before_atomic_dec () barrier()#define smp_mb__after_atomic_dec () barrier()
include/asm-m68knommu/atomic.h +10 -0
@@ -130,6 +130,16 @@ static inline int atomic_sub_return(int#define atomic_cmpxchg (v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +#define atomic_add_unless (v, a, u) \ +({ \ + int c, old; \ + c = atomic_read(v); \ + while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ + c = old; \ + c != (u); \ +}) +#define atomic_inc_not_zero (v) atomic_add_unless((v), 1, 0) +#define atomic_dec_return (v) atomic_sub_return(1,(v))#define atomic_inc_return (v) atomic_add_return(1,(v))
include/asm-mips/atomic.h +19 -0
@@ -289,6 +289,25 @@ static __inline__ int atomic_sub_if_posi#define atomic_cmpxchg (v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +/** +* atomic_add_unless - add unless the number is a given value +* @v: pointer of type atomic_t +* @a: the amount to add to v... +* @u: ...unless v is equal to u. +* +* Atomically adds @a to @v, so long as it was not @u. +* Returns non-zero if @v was not @u, and zero otherwise. +*/ +#define atomic_add_unless (v, a, u) \ +({ \ + int c, old; \ + c = atomic_read(v); \ + while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ + c = old; \ + c != (u); \ +}) +#define atomic_inc_not_zero (v) atomic_add_unless((v), 1, 0) +#define atomic_dec_return (v) atomic_sub_return(1,(v))#define atomic_inc_return (v) atomic_add_return(1,(v))
include/asm-parisc/atomic.h +19 -0
@@ -166,6 +166,25 @@ static __inline__ int atomic_read(const/* exported interface */ #define atomic_cmpxchg (v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +/** +* atomic_add_unless - add unless the number is a given value +* @v: pointer of type atomic_t +* @a: the amount to add to v... +* @u: ...unless v is equal to u. +* +* Atomically adds @a to @v, so long as it was not @u. +* Returns non-zero if @v was not @u, and zero otherwise. +*/ +#define atomic_add_unless (v, a, u) \ +({ \ + int c, old; \ + c = atomic_read(v); \ + while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ + c = old; \ + c != (u); \ +}) +#define atomic_inc_not_zero (v) atomic_add_unless((v), 1, 0) +#define atomic_add (i,v) ((void)(__atomic_add_return( ((int)i),(v))))#define atomic_sub (i,v) ((void)(__atomic_add_return(-((int)i),(v))))#define atomic_inc (v) ((void)(__atomic_add_return( 1,(v))))
include/asm-s390/atomic.h +10 -0
@@ -200,6 +200,16 @@ atomic_compare_and_swap(int expected_old#define atomic_cmpxchg (v, o, n) (atomic_compare_and_swap((o), (n), &((v)->counter))) +#define atomic_add_unless (v, a, u) \ +({ \ + int c, old; \ + c = atomic_read(v); \ + while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ + c = old; \ + c != (u); \ +}) +#define atomic_inc_not_zero (v) atomic_add_unless((v), 1, 0) +#define smp_mb__before_atomic_dec () smp_mb()#define smp_mb__after_atomic_dec () smp_mb()#define smp_mb__before_atomic_inc () smp_mb()
include/asm-sh/atomic.h +15 -0
@@ -101,6 +101,21 @@ static __inline__ int atomic_cmpxchg(atoreturn ret; } +static __inline__int atomic_add_unless (atomic_t *v,int a,int u) +{ +int ret; +unsigned long flags; + +local_irq_save (flags); + ret = v->counter; +if (ret != u) + v->counter += a; +local_irq_restore (flags); + +return ret != u; +} +#define atomic_inc_not_zero (v) atomic_add_unless((v), 1, 0) +static __inline__void atomic_clear_mask (unsigned int mask,atomic_t *v) {unsigned long flags;
include/asm-sh64/atomic.h +15 -0
@@ -113,6 +113,21 @@ static __inline__ int atomic_cmpxchg(atoreturn ret; } +static __inline__int atomic_add_unless (atomic_t *v,int a,int u) +{ +int ret; +unsigned long flags; + +local_irq_save (flags); + ret = v->counter; +if (ret != u) + v->counter += a; +local_irq_restore (flags); + +return ret != u; +} +#define atomic_inc_not_zero (v) atomic_add_unless((v), 1, 0) +static __inline__void atomic_clear_mask (unsigned int mask,atomic_t *v) {unsigned long flags;
include/asm-sparc/atomic.h +3 -0
@@ -20,6 +20,7 @@ typedef struct { volatile int counter; }extern int __atomic_add_return (int ,atomic_t *);extern int atomic_cmpxchg (atomic_t *,int ,int ); +extern int atomic_add_unless (atomic_t *,int ,int );extern void atomic_set (atomic_t *,int );#define atomic_read (v) ((v)->counter)
@@ -49,6 +50,8 @@ extern void atomic_set(atomic_t *, int);#define atomic_dec_and_test (v) (atomic_dec_return(v) == 0)#define atomic_sub_and_test (i, v) (atomic_sub_return(i, v) == 0) +#define atomic_inc_not_zero (v) atomic_add_unless((v), 1, 0) +/* This is the old 24-bit implementation. It's still used internally * by some sparc-specific code, notably the semaphore implementation. */
include/asm-sparc64/atomic.h +10 -0
@@ -72,6 +72,16 @@ extern int atomic64_sub_ret(int, atomic6#define atomic_cmpxchg (v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +#define atomic_add_unless (v, a, u) \ +({ \ + int c, old; \ + c = atomic_read(v); \ + while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ + c = old; \ + c != (u); \ +}) +#define atomic_inc_not_zero (v) atomic_add_unless((v), 1, 0) +/* Atomic operations are already serializing */ #ifdef CONFIG_SMP #define smp_mb__before_atomic_dec () membar_storeload_loadload();
include/asm-v850/atomic.h +16 -0
@@ -104,6 +104,22 @@ static __inline__ int atomic_cmpxchg(atoreturn ret; } +static __inline__int atomic_add_unless (atomic_t *v,int a,int u) +{ +int ret; +unsigned long flags; + +local_irq_save (flags); + ret = v->counter; +if (ret != u) + v->counter += a; +local_irq_restore (flags); + +return ret != u; +} + +#define atomic_inc_not_zero (v) atomic_add_unless((v), 1, 0) +/* Atomic operations are already serializing on ARM */ #define smp_mb__before_atomic_dec () barrier()#define smp_mb__after_atomic_dec () barrier()
include/asm-x86_64/atomic.h +19 -0
@@ -362,6 +362,25 @@ static __inline__ int atomic_sub_return(#define atomic_cmpxchg (v, old, new) ((int)cmpxchg(&((v)->counter), old, new)) +/** +* atomic_add_unless - add unless the number is a given value +* @v: pointer of type atomic_t +* @a: the amount to add to v... +* @u: ...unless v is equal to u. +* +* Atomically adds @a to @v, so long as it was not @u. +* Returns non-zero if @v was not @u, and zero otherwise. +*/ +#define atomic_add_unless (v, a, u) \ +({ \ + int c, old; \ + c = atomic_read(v); \ + while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ + c = old; \ + c != (u); \ +}) +#define atomic_inc_not_zero (v) atomic_add_unless((v), 1, 0) +#define atomic_inc_return (v) (atomic_add_return(1,v))#define atomic_dec_return (v) (atomic_sub_return(1,v))
include/asm-xtensa/atomic.h +19 -0
@@ -225,6 +225,25 @@ static inline int atomic_sub_return(int#define atomic_cmpxchg (v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +/** +* atomic_add_unless - add unless the number is a given value +* @v: pointer of type atomic_t +* @a: the amount to add to v... +* @u: ...unless v is equal to u. +* +* Atomically adds @a to @v, so long as it was not @u. +* Returns non-zero if @v was not @u, and zero otherwise. +*/ +#define atomic_add_unless (v, a, u) \ +({ \ + int c, old; \ + c = atomic_read(v); \ + while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ + c = old; \ + c != (u); \ +}) +#define atomic_inc_not_zero (v) atomic_add_unless((v), 1, 0) +static inline void atomic_clear_mask (unsigned int mask,atomic_t *v) {unsigned int all_f =-1 ;
include/asm-cris/atomic.h +13 -0
@@ -135,6 +135,19 @@ static __inline__ int atomic_cmpxchg(atoreturn ret; } +static __inline__int atomic_add_unless (atomic_t *v,int a,int u) +{ +int ret; +unsigned long flags; +cris_atomic_save (v, flags); + ret = v->counter; +if (ret != u) + v->counter += a; +cris_atomic_restore (v, flags); +return ret != u; +} +#define atomic_inc_not_zero (v) atomic_add_unless((v), 1, 0) +static inline void atomic_clear_mask (unsigned long mask,unsigned long *addr) /* Atomic operations are already serializing */#define smp_mb__before_atomic_dec () barrier()
arch/sparc/lib/atomic32.c +14 -0
@@ -52,6 +52,20 @@ int atomic_cmpxchg(atomic_t *v, int old,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; +} + +static inline void atomic_clear_mask (unsigned long mask,unsigned long *addr) +/* Atomic operations are already serializing */ void atomic_set(atomic_t *v, int i) {unsigned long flags;
Documentation/atomic_ops.txt +13 -1
@@ -115,7 +115,7 @@ boolean is return which indicates whethe is negative. It requires explicit memory barrier semantics around the operation. -Finally: +Then: int atomic_cmpxchg(atomic_t *v, int old, int new);
@@ -129,6 +129,18 @@ atomic_cmpxchg requires explicit memory The semantics for atomic_cmpxchg are the same as those defined for 'cas' below. +Finally: + + int atomic_add_unless(atomic_t *v, int a, int u); + +If the atomic value v is not equal to u, this function adds a to v, and +returns non zero. If v is equal to u then it returns zero. This is done as +an atomic operation. + +atomic_add_unless requires explicit memory barriers around the operation. + +atomic_inc_not_zero, equivalent to atomic_add_unless(v, 1, 0) + If a caller requires memory barrier semantics around an atomic_t operation which does not return a value, a set of interfaces are
include/asm-arm/atomic.h +10 -0
@@ -174,6 +174,16 @@ static inline void atomic_clear_mask(uns#endif /* __LINUX_ARM_ARCH__ */ +static inline int atomic_add_unless (atomic_t *v,int a,int u) +{ +int c, old; + c =atomic_read (v); +while (c != u && (old =atomic_cmpxchg ((v), c, c + a)) != c) + c = old; +return c != u; +} +#define atomic_inc_not_zero (v) atomic_add_unless((v), 1, 0) +#define atomic_add (i, v) (void) atomic_add_return(i, v)#define atomic_inc (v) (void) atomic_add_return(1, v)#define atomic_sub (i, v) (void) atomic_sub_return(i, v)
include/asm-powerpc/atomic.h +25 -0
@@ -174,6 +174,31 @@ static __inline__ int atomic_dec_return(#define atomic_cmpxchg (v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +/** +* atomic_add_unless - add unless the number is a given value +* @v: pointer of type atomic_t +* @a: the amount to add to v... +* @u: ...unless v is equal to u. +* +* Atomically adds @a to @v, so long as it was not @u. +* Returns non-zero if @v was not @u, and zero otherwise. +*/ +#define atomic_add_unless (v, a, u) \ +({ \ + int c, old; \ + c = atomic_read(v); \ + for (;;) { \ + if (unlikely(c == (u))) \ + break; \ + old = atomic_cmpxchg((v), c, c + (a)); \ + if (likely(old == c)) \ + break; \ + c = old; \ + } \ + c != (u); \ +}) +#define atomic_inc_not_zero (v) atomic_add_unless((v), 1, 0) +#define atomic_sub_and_test (a, v) (atomic_sub_return((a), (v)) == 0)#define atomic_dec_and_test (v) (atomic_dec_return((v)) == 0)
PATCH 4/5 rcu file: use atomic
4/5
Signature · 1 line
SUSE Labs, Novell Inc.
Use atomic_inc_not_zero for rcu files instead of specal case rcuref.
include/linux/rcuref.h deleted +0 -220
@@ -1,220 +0,0 @@ -/* -* rcuref.h -* -* Reference counting for elements of lists/arrays protected by -* RCU. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* Copyright (C) IBM Corporation, 2005 -* -* Author: Dipankar Sarma <[email protected]> -* Ravikiran Thirumalai <[email protected]> -* -* See Documentation/RCU/rcuref.txt for detailed user guide. -* -*/ - -#ifndef _RCUREF_H_ -#define _RCUREF_H_ - -#ifdef __KERNEL__ - -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/spinlock.h> -#include <asm/atomic.h> - -/* -* These APIs work on traditional atomic_t counters used in the -* kernel for reference counting. Under special circumstances -* where a lock-free get() operation races with a put() operation -* these APIs can be used. See Documentation/RCU/rcuref.txt. -*/ - -#ifdef __HAVE_ARCH_CMPXCHG - -/** -* rcuref_inc - increment refcount for object. -* @rcuref: reference counter in the object in question. -* -* This should be used only for objects where we use RCU and -* use the rcuref_inc_lf() api to acquire a reference -* in a lock-free reader-side critical section. -*/ -static inline void rcuref_inc (atomic_t *rcuref) -{ -atomic_inc (rcuref); -} - -/** -* rcuref_dec - decrement refcount for object. -* @rcuref: reference counter in the object in question. -* -* This should be used only for objects where we use RCU and -* use the rcuref_inc_lf() api to acquire a reference -* in a lock-free reader-side critical section. -*/ -static inline void rcuref_dec (atomic_t *rcuref) -{ -atomic_dec (rcuref); -} - -/** -* rcuref_dec_and_test - decrement refcount for object and test -* @rcuref: reference counter in the object. -* @release: pointer to the function that will clean up the object -* when the last reference to the object is released. -* This pointer is required. -* -* Decrement the refcount, and if 0, return 1. Else return 0. -* -* This should be used only for objects where we use RCU and -* use the rcuref_inc_lf() api to acquire a reference -* in a lock-free reader-side critical section. -*/ -static inline int rcuref_dec_and_test (atomic_t *rcuref) -{ -return atomic_dec_and_test (rcuref); -} - -/* -* cmpxchg is needed on UP too, if deletions to the list/array can happen -* in interrupt context. -*/ - -/** -* rcuref_inc_lf - Take reference to an object in a read-side -* critical section protected by RCU. -* @rcuref: reference counter in the object in question. -* -* Try and increment the refcount by 1. The increment might fail if -* the reference counter has been through a 1 to 0 transition and -* is no longer part of the lock-free list. -* Returns non-zero on successful increment and zero otherwise. -*/ -static inline int rcuref_inc_lf (atomic_t *rcuref) -{ -int c, old; - c =atomic_read (rcuref); -while (c && (old =cmpxchg (&rcuref->counter, c, c +1 )) != c) - c = old; -return c; -} - -#else /* !__HAVE_ARCH_CMPXCHG */ - -extern spinlock_t __rcuref_hash[]; - -/* -* Use a hash table of locks to protect the reference count -* since cmpxchg is not available in this arch. -*/ -#ifdef CONFIG_SMP -#define RCUREF_HASH_SIZE 4 -#define RCUREF_HASH (k) \ - (&__rcuref_hash[(((unsigned long)k)>>8) & (RCUREF_HASH_SIZE-1)]) -#else -#define RCUREF_HASH_SIZE 1 -#define RCUREF_HASH (k) &__rcuref_hash[0] -#endif /* CONFIG_SMP */ - -/** -* rcuref_inc - increment refcount for object. -* @rcuref: reference counter in the object in question. -* -* This should be used only for objects where we use RCU and -* use the rcuref_inc_lf() api to acquire a reference in a lock-free -* reader-side critical section. -*/ -static inline void rcuref_inc (atomic_t *rcuref) -{ -unsigned long flags; -spin_lock_irqsave (RCUREF_HASH (rcuref), flags); - rcuref->counter +=1 ; -spin_unlock_irqrestore (RCUREF_HASH (rcuref), flags); -} - -/** -* rcuref_dec - decrement refcount for object. -* @rcuref: reference counter in the object in question. -* -* This should be used only for objects where we use RCU and -* use the rcuref_inc_lf() api to acquire a reference in a lock-free -* reader-side critical section. -*/ -static inline void rcuref_dec (atomic_t *rcuref) -{ -unsigned long flags; -spin_lock_irqsave (RCUREF_HASH (rcuref), flags); - rcuref->counter -=1 ; -spin_unlock_irqrestore (RCUREF_HASH (rcuref), flags); -} - -/** -* rcuref_dec_and_test - decrement refcount for object and test -* @rcuref: reference counter in the object. -* @release: pointer to the function that will clean up the object -* when the last reference to the object is released. -* This pointer is required. -* -* Decrement the refcount, and if 0, return 1. Else return 0. -* -* This should be used only for objects where we use RCU and -* use the rcuref_inc_lf() api to acquire a reference in a lock-free -* reader-side critical section. -*/ -static inline int rcuref_dec_and_test (atomic_t *rcuref) -{ -unsigned long flags; -spin_lock_irqsave (RCUREF_HASH (rcuref), flags); - rcuref->counter--; -if (!rcuref->counter) { -spin_unlock_irqrestore (RCUREF_HASH (rcuref), flags); -return 1 ; - }else { -spin_unlock_irqrestore (RCUREF_HASH (rcuref), flags); -return 0 ; - } -} - -/** -* rcuref_inc_lf - Take reference to an object of a lock-free collection -* by traversing a lock-free list/array. -* @rcuref: reference counter in the object in question. -* -* Try and increment the refcount by 1. The increment might fail if -* the reference counter has been through a 1 to 0 transition and -* object is no longer part of the lock-free list. -* Returns non-zero on successful increment and zero otherwise. -*/ -static inline int rcuref_inc_lf (atomic_t *rcuref) -{ -int ret; -unsigned long flags; -spin_lock_irqsave (RCUREF_HASH (rcuref), flags); -if (rcuref->counter) - ret = rcuref->counter++; -else - ret =0 ; -spin_unlock_irqrestore (RCUREF_HASH (rcuref), flags); -return ret; -} - - -#endif /* !__HAVE_ARCH_CMPXCHG */ - -#endif /* __KERNEL__ */ -#endif /* _RCUREF_H_ */
fs/aio.c +1 -2
@@ -29,7 +29,6 @@#include <linux/highmem.h> #include <linux/workqueue.h> #include <linux/security.h> -#include <linux/rcuref.h> #include <asm/kmap_types.h> #include <asm/uaccess.h>
@@ -500,7 +499,7 @@ static int __aio_put_req(struct kioctx */* Must be done under the lock to serialise against cancellation. * Call this aio_fput as it duplicates fput via the fput_work. */ -if (unlikely (rcuref_dec_and_test (&req->ki_filp->f_count))) { +if (unlikely (atomic_dec_and_test (&req->ki_filp->f_count))) {get_ioctx (ctx);spin_lock (&fput_lock);list_add (&req->ki_list, &fput_head);
fs/file_table.c +4 -4
@@ -117,7 +117,7 @@ EXPORT_SYMBOL(get_empty_filp); void fastcall fput(struct file *file) { -if (rcuref_dec_and_test (&file->f_count)) +if (atomic_dec_and_test (&file->f_count))__fput (file); }
@@ -166,7 +166,7 @@ struct file fastcall *fget(unsigned intrcu_read_lock (); file =fcheck_files (files, fd);if (file) { -if (!rcuref_inc_lf (&file->f_count)) { +if (!atomic_inc_not_zero (&file->f_count)) {/* File object ref couldn't be taken */ rcu_read_unlock ();return NULL ;
@@ -198,7 +198,7 @@ struct file fastcall *fget_light(unsignercu_read_lock (); file =fcheck_files (files, fd);if (file) { -if (rcuref_inc_lf (&file->f_count)) +if (atomic_inc_not_zero (&file->f_count)) *fput_needed =1 ;else /* Didn't get the reference, someone's freed */
@@ -213,7 +213,7 @@ struct file fastcall *fget_light(unsignevoid put_filp (struct file *file) { -if (rcuref_dec_and_test (&file->f_count)) { +if (atomic_dec_and_test (&file->f_count)) {security_file_free (file);file_kill (file);file_free (file);
include/linux/fs.h +1 -2
@@ -9,7 +9,6 @@#include <linux/config.h> #include <linux/limits.h> #include <linux/ioctl.h> -#include <linux/rcuref.h> /* * It's silly to have NR_OPEN bigger than NR_FILE, but you can change
@@ -610,7 +609,7 @@ extern spinlock_t files_lock;#define file_list_lock () spin_lock(&files_lock);#define file_list_unlock () spin_unlock(&files_lock); -#define get_file (x) rcuref_inc(&(x)->f_count) +#define get_file (x) atomic_inc(&(x)->f_count)#define file_count (x) atomic_read(&(x)->f_count)#define MAX_NON_LFS ((1UL<<31) - 1)
Documentation/RCU/rcuref.txt +40 -47
114 lines not on this page · raw message
kernel/rcupdate.c +0 -14
@@ -45,7 +45,6 @@#include <linux/percpu.h> #include <linux/notifier.h> #include <linux/rcupdate.h> -#include <linux/rcuref.h> #include <linux/cpu.h> /* Definition for rcupdate control block. */
@@ -73,19 +72,6 @@ DEFINE_PER_CPU(struct rcu_data, rcu_bh_d static DEFINE_PER_CPU(struct tasklet_struct, rcu_tasklet) = {NULL};static int maxbatch =10000 ; -#ifndef __HAVE_ARCH_CMPXCHG -/* -* We use an array of spinlocks for the rcurefs -- similar to ones in sparc -* 32 bit atomic_t implementations, and a hash function similar to that -* for our refcounting needs. -* Can't help multiprocessors which donot have cmpxchg :( -*/ - -spinlock_t __rcuref_hash[RCUREF_HASH_SIZE ] = { - [0 ... (RCUREF_HASH_SIZE -1 )] =SPIN_LOCK_UNLOCKED -}; -#endif -/** * call_rcu - Queue an RCU callback for invocation after a grace period. * @head: structure to be used for queueing the RCU updates.
security/selinux/hooks.c +1 -1
@@ -1662,7 +1662,7 @@ static inline void flush_unauthorized_ficontinue ; }if (devnull) { -rcuref_inc (&devnull->f_count); +atomic_inc (&devnull->f_count); }else { devnull =dentry_open (dget (selinux_null),mntget (selinuxfs_mount),O_RDWR );if (!devnull) {
kernel/rcutorture.c +0 -1
@@ -39,7 +39,6 @@#include <linux/moduleparam.h> #include <linux/percpu.h> #include <linux/notifier.h> -#include <linux/rcuref.h> #include <linux/cpu.h> #include <linux/random.h> #include <linux/delay.h>
PATCH 5/5 atomic: dec_and_lock use atomic
5/5
Signature · 1 line
SUSE Labs, Novell Inc.
Use new atomic primitives for atomic_dec_and_lock
lib/dec_and_lock.c +6 -43
@@ -1,47 +1,11 @@#include <linux/module.h> #include <linux/spinlock.h> #include <asm/atomic.h> -#include <asm/system.h> -#ifdef __HAVE_ARCH_CMPXCHG/* * This is an implementation of the notion of "decrement a * reference count, and return locked if it decremented to zero". * -* This implementation can be used on any architecture that -* has a cmpxchg, and where atomic->value is an int holding -* the value of the atomic (i.e. the high bits aren't used -* for a lock or anything like that). -*/ -int _atomic_dec_and_lock (atomic_t *atomic,spinlock_t *lock) -{ -int counter; -int newcount; - -for (;;) { - counter =atomic_read (atomic); - newcount = counter -1 ; -if (!newcount) -break ;/* do it the slow way */ - - newcount =cmpxchg (&atomic->counter, counter, newcount); -if (newcount == counter) -return 0 ; - } - -spin_lock (lock); -if (atomic_dec_and_test (atomic)) -return 1 ; -spin_unlock (lock); -return 0 ; -} -#else -/* -* This is an architecture-neutral, but slow, -* implementation of the notion of "decrement -* a reference count, and return locked if it -* decremented to zero". -* * NOTE NOTE NOTE! This is _not_ equivalent to * * if (atomic_dec_and_test(&atomic)) {
@@ -52,21 +16,20 @@ int _atomic_dec_and_lock(atomic_t *atomi* * because the spin-lock and the decrement must be * "atomic". -* -* This slow version gets the spinlock unconditionally, -* and releases it if it isn't needed. Architectures -* are encouraged to come up with better approaches, -* this is trivially done efficiently using a load-locked -* store-conditional approach, for example. */ int _atomic_dec_and_lock (atomic_t *atomic,spinlock_t *lock) { +#ifdef CONFIG_SMP +/* Subtract 1 from counter unless that drops it to 0 (ie. it was 1) */ +if (atomic_add_unless (atomic,-1 ,1 )) +return 0 ; +#endif +/* Otherwise do it the slow way */ spin_lock (lock);if (atomic_dec_and_test (atomic))return 1 ;spin_unlock (lock);return 0 ; } -#endif EXPORT_SYMBOL (_atomic_dec_and_lock);
Re: [patch 2/5] atomic: cmpxchg
In reply to Nick PigginQuoted 38 lines · Nick Piggin
Index:
linux-2.6/include/asm-arm/atomic.h
===================================================================include/asm-arm/atomic.h +23
-0@@ -80,6 +80,23 @@ static inline int atomic_sub_return(intreturn result; } +static inline int atomic_cmpxchg (atomic_t *ptr,int old,int new) +{ +u32 oldval, res; + +do { + __asm__ __volatile__("@ atomic_cmpxchg\n" +"ldrex %1, [%2]\n" +"teq %1, %3\n" +"strexeq %0, %4, [%2]\n" + :"=&r" (res),"=&r" (oldval) + :"r" (&ptr->counter),"r" (old),"r" (new) + :"cc" ); + }while (res); + +return oldval; +} +static inline void atomic_clear_mask (unsigned long mask,unsigned long *addr) {unsigned long tmp, tmp2;@@ -131,6 +148,21 @@ static inline int atomic_sub_return(intreturn val; } +static inline int atomic_cmpxchg (atomic_t *v,int old,int new) +{ +int ret; +unsigned long flags; + +local_irq_save (flags);
include/asm-arm/atomic.h static inline int atomic_sub_return(int · line 166
Quoted 10 lines
include/asm-arm/atomic.h +9
-0+ ret = v->counter; +if (likely (ret == old)) + v->counter = new; +local_irq_restore (flags); + +return ret; +} + +static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
This is obviously going to break ARM...
Signature · 3 lines
Russell King Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/ maintainer of: 2.6 Serial core
Re: [patch 2/5] atomic: cmpxchg
Quoted 45 lines · Russell King
Quoted 43 lines · Nick Piggin
Index:
linux-2.6/include/asm-arm/atomic.h
===================================================================include/asm-arm/atomic.h +28
-0@@ -80,6 +80,23 @@ static inline int atomic_sub_return(intreturn result; } +static inline int atomic_cmpxchg (atomic_t *ptr,int old,int new) +{ +u32 oldval, res; + +do { + __asm__ __volatile__("@ atomic_cmpxchg\n" +"ldrex %1, [%2]\n" +"teq %1, %3\n" +"strexeq %0, %4, [%2]\n" + :"=&r" (res),"=&r" (oldval) + :"r" (&ptr->counter),"r" (old),"r" (new) + :"cc" ); + }while (res); + +return oldval; +} +static inline void atomic_clear_mask (unsigned long mask,unsigned long *addr) {unsigned long tmp, tmp2;@@ -131,6 +148,21 @@ static inline int atomic_sub_return(intreturn val; } +static inline int atomic_cmpxchg (atomic_t *v,int old,int new) +{ +int ret; +unsigned long flags; + +local_irq_save (flags); + ret = v->counter; +if (likely (ret == old)) + v->counter = new; +local_irq_restore (flags); +
Quoted 9 lines
include/asm-arm/atomic.h static inline int atomic_sub_return(int · line 166
Quoted 5 lines
include/asm-arm/atomic.h +4
-0+return ret; +} + +static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)This is obviously going to break ARM...
Ah dang sorry. Must be a cut-n-paste-o.
While you're here, does the assembly code for the SMP version look OK? You basically provided me with it but I don't think you saw its final form.
Signature · 3 lines
SUSE Labs, Novell Inc. Send instant messages to your online friends http://au.messenger.yahoo.com
Re: [patch 2/5] atomic: cmpxchg
Quoted 3 lines · Nick Piggin
While you're here, does the assembly code for the SMP version look OK? You basically provided me with it but I don't think you saw its final form.
Looks fine. The only comment is changing the "r" (old) to be "Ir" (old). The "I" tells the compiler that it may also use a constant for that argument, which may allow it to optimise the code a bit better.
Signature · 3 lines
Russell King Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/ maintainer of: 2.6 Serial core
Re: [patch 2/5] atomic: cmpxchg
Quoted 7 lines · Russell King
Quoted 3 lines · Nick Piggin
While you're here, does the assembly code for the SMP version look OK? You basically provided me with it but I don't think you saw its final form.
Quoted 5 lines
Looks fine. The only comment is changing the "r" (old) to be "Ir" (old). The "I" tells the compiler that it may also use a constant for that argument, which may allow it to optimise the code a bit better.
Thanks. Will submit a new patch after this round of feedback.
Signature · 3 lines
SUSE Labs, Novell Inc. Send instant messages to your online friends http://au.messenger.yahoo.com