This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] atomic.h : standardizing atomic primitives


Hi Peter,

Thanks for testing Andrew's fixes. I am wondering about what happened to
the Powerpc recursive include problems Andrew experienced. Quoting him :

"OK, I fixed eight separate compile errors in this patch series and
now powerpc is being very ugly with a twisty maze of include
dependencies.

I'm giving up.  Someone should publish a suite of cross-compilers for us
so stuff like this doesn't need to happen."

I see that you have removed the include <asm/atomic.h> from bitops.h and
system.h in powerpc. If it compiles on every architectures, then it's a
good approach.

I planned to post a new patch which uses macros for cmpxchg and xchg in
asm-generic/atomic.h instead of inline functions. It would remove the
dependency on system.h. However, if your modifications work well on
every architecture, my fix might not be needed. Anyone has a preferred
solution ? I have not been able to setup my cross-compiler test bench
yet due to some hardware issues and waited for it before I released
further fixes, but if you want to try my macro-based fix, I could post
it.

And about the alpha build, Does the assembler errors also happen without
this patch ?

Regards,

Mathieu


* Peter Zijlstra (a.p.zijlstra@chello.nl) wrote:
> 
> atomic.h : standardizing atomic primitives
> 
> It mainly adds support for missing 64 bits cmpxchg and 64 bits atomic add
> unless. Therefore, principally 64 bits architectures are targeted by these
> patches. It also adds the complete list of atomic operations on the atomic_long
> type.
> 
> build tested on:
> 
> arm-pxa255-idp_defconfig-xbuild
> i386-defconfig-xbuild
> ia64-defconfig-xbuild
> mips-ip32_defconfig-xbuild
> mips-yosemite_defconfig-xbuild
> parisc-a500_defconfig-xbuild  -- needs parisc-2.6 tree
> powerpc-ppc64_defconfig-xbuild
> sparc64-defconfig-xbuild
> sparc-defconfig-xbuild
> um-x86_64-defconfig-xbuild
> x86_64-defconfig-xbuild
> 
> notable exception: alpha (assembler errors, guess binutils funkyness)
> 
> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
> Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
> ---
>  include/asm-alpha/atomic.h   |   51 ++++++++++++
>  include/asm-generic/atomic.h |  169 +++++++++++++++++++++++++++++++++++++++++++
>  include/asm-i386/atomic.h    |    7 +
>  include/asm-ia64/atomic.h    |   25 +++++-
>  include/asm-mips/atomic.h    |   28 ++++++-
>  include/asm-parisc/atomic.h  |   29 ++++++-
>  include/asm-powerpc/atomic.h |   40 +++++++++-
>  include/asm-powerpc/bitops.h |    1 
>  include/asm-powerpc/system.h |    1 
>  include/asm-sparc64/atomic.h |   25 +++++-
>  include/asm-x86_64/atomic.h  |   38 ++++++++-
>  11 files changed, 392 insertions(+), 22 deletions(-)
> 
> Index: linux-2.6/include/asm-alpha/atomic.h
> ===================================================================
> --- linux-2.6.orig/include/asm-alpha/atomic.h
> +++ linux-2.6/include/asm-alpha/atomic.h
> @@ -175,19 +175,64 @@ static __inline__ long atomic64_sub_retu
>  	return result;
>  }
>  
> -#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
> +#define atomic64_cmpxchg(v, old, new) \
> +	((__typeof__((v)->counter))cmpxchg(&((v)->counter), old, new))
> +#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
> +
> +#define atomic_cmpxchg(v, old, new) \
> +	((__typeof__((v)->counter))cmpxchg(&((v)->counter), old, new))
>  #define atomic_xchg(v, new) (xchg(&((v)->counter), 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;						\
> +	__typeof__((v)->counter) c, old;			\
>  	c = atomic_read(v);					\
> -	while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
> +	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)
>  
> +/**
> + * atomic64_add_unless - add unless the number is a given value
> + * @v: pointer of type atomic64_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 atomic64_add_unless(v, a, u)				\
> +({								\
> +	__typeof__((v)->counter) c, old;			\
> +	c = atomic64_read(v);					\
> +	for (;;) {						\
> +		if (unlikely(c == (u)))				\
> +			break;					\
> +		old = atomic64_cmpxchg((v), c, c + (a));	\
> +		if (likely(old == c))				\
> +			break;					\
> +		c = old;					\
> +	}							\
> +	c != (u);						\
> +})
> +#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
> +
>  #define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
>  #define atomic64_add_negative(a, v) (atomic64_add_return((a), (v)) < 0)
>  
> Index: linux-2.6/include/asm-generic/atomic.h
> ===================================================================
> --- linux-2.6.orig/include/asm-generic/atomic.h
> +++ linux-2.6/include/asm-generic/atomic.h
> @@ -8,6 +8,7 @@
>   * edit all arch specific atomic.h files.
>   */
>  
> +#include <asm/system.h>
>  #include <asm/types.h>
>  
>  /*
> @@ -66,6 +67,90 @@ static inline void atomic_long_sub(long 
>  	atomic64_sub(i, v);
>  }
>  
> +static inline int atomic_long_sub_and_test(long i, atomic_long_t *l)
> +{
> +	atomic64_t *v = (atomic64_t *)l;
> +
> +	return atomic64_sub_and_test(i, v);
> +}
> +
> +static inline int atomic_long_dec_and_test(atomic_long_t *l)
> +{
> +	atomic64_t *v = (atomic64_t *)l;
> +
> +	return atomic64_dec_and_test(v);
> +}
> +
> +static inline int atomic_long_inc_and_test(atomic_long_t *l)
> +{
> +	atomic64_t *v = (atomic64_t *)l;
> +
> +	return atomic64_inc_and_test(v);
> +}
> +
> +static inline int atomic_long_add_negative(long i, atomic_long_t *l)
> +{
> +	atomic64_t *v = (atomic64_t *)l;
> +
> +	return atomic64_add_negative(i, v);
> +}
> +
> +static inline long atomic_long_add_return(long i, atomic_long_t *l)
> +{
> +	atomic64_t *v = (atomic64_t *)l;
> +
> +	return (long)atomic64_add_return(i, v);
> +}
> +
> +static inline long atomic_long_sub_return(long i, atomic_long_t *l)
> +{
> +	atomic64_t *v = (atomic64_t *)l;
> +
> +	return (long)atomic64_sub_return(i, v);
> +}
> +
> +static inline long atomic_long_inc_return(atomic_long_t *l)
> +{
> +	atomic64_t *v = (atomic64_t *)l;
> +
> +	return (long)atomic64_inc_return(v);
> +}
> +
> +static inline long atomic_long_dec_return(atomic_long_t *l)
> +{
> +	atomic64_t *v = (atomic64_t *)l;
> +
> +	return (long)atomic64_dec_return(v);
> +}
> +
> +static inline long atomic_long_add_unless(atomic_long_t *l, long a, long u)
> +{
> +	atomic64_t *v = (atomic64_t *)l;
> +
> +	return (long)atomic64_add_unless(v, a, u);
> +}
> +
> +static inline long atomic_long_inc_not_zero(atomic_long_t *l)
> +{
> +	atomic64_t *v = (atomic64_t *)l;
> +
> +	return (long)atomic64_inc_not_zero(v);
> +}
> +
> +static inline long atomic_long_cmpxchg(atomic_long_t *l, long old, long new)
> +{
> +	atomic64_t *v = (atomic64_t *)l;
> +
> +	return (long)atomic64_cmpxchg(v, old, new);
> +}
> +
> +static inline long atomic_long_xchg(atomic_long_t *l, long new)
> +{
> +	atomic64_t *v = (atomic64_t *)l;
> +
> +	return (long)atomic64_xchg(v, new);
> +}
> +
>  #else  /*  BITS_PER_LONG == 64  */
>  
>  typedef atomic_t atomic_long_t;
> @@ -113,6 +198,90 @@ static inline void atomic_long_sub(long 
>  	atomic_sub(i, v);
>  }
>  
> +static inline int atomic_long_sub_and_test(long i, atomic_long_t *l)
> +{
> +	atomic_t *v = (atomic_t *)l;
> +
> +	return atomic_sub_and_test(i, v);
> +}
> +
> +static inline int atomic_long_dec_and_test(atomic_long_t *l)
> +{
> +	atomic_t *v = (atomic_t *)l;
> +
> +	return atomic_dec_and_test(v);
> +}
> +
> +static inline int atomic_long_inc_and_test(atomic_long_t *l)
> +{
> +	atomic_t *v = (atomic_t *)l;
> +
> +	return atomic_inc_and_test(v);
> +}
> +
> +static inline int atomic_long_add_negative(long i, atomic_long_t *l)
> +{
> +	atomic_t *v = (atomic_t *)l;
> +
> +	return atomic_add_negative(i, v);
> +}
> +
> +static inline long atomic_long_add_return(long i, atomic_long_t *l)
> +{
> +	atomic_t *v = (atomic_t *)l;
> +
> +	return (long)atomic_add_return(i, v);
> +}
> +
> +static inline long atomic_long_sub_return(long i, atomic_long_t *l)
> +{
> +	atomic_t *v = (atomic_t *)l;
> +
> +	return (long)atomic_sub_return(i, v);
> +}
> +
> +static inline long atomic_long_inc_return(atomic_long_t *l)
> +{
> +	atomic_t *v = (atomic_t *)l;
> +
> +	return (long)atomic_inc_return(v);
> +}
> +
> +static inline long atomic_long_dec_return(atomic_long_t *l)
> +{
> +	atomic_t *v = (atomic_t *)l;
> +
> +	return (long)atomic_dec_return(v);
> +}
> +
> +static inline long atomic_long_add_unless(atomic_long_t *l, long a, long u)
> +{
> +	atomic_t *v = (atomic_t *)l;
> +
> +	return (long)atomic_add_unless(v, a, u);
> +}
> +
> +static inline long atomic_long_inc_not_zero(atomic_long_t *l)
> +{
> +	atomic_t *v = (atomic_t *)l;
> +
> +	return (long)atomic_inc_not_zero(v);
> +}
> +
> +static inline long atomic_long_cmpxchg(atomic_long_t *l, long old, long new)
> +{
> +	atomic_t *v = (atomic_t *)l;
> +
> +	return (long)atomic_cmpxchg(v, old, new);
> +}
> +
> +static inline long atomic_long_xchg(atomic_long_t *l, long new)
> +{
> +	atomic_t *v = (atomic_t *)l;
> +
> +	return (long)atomic_xchg(v, new);
> +}
> +
>  #endif  /*  BITS_PER_LONG == 64  */
>  
>  #endif  /*  _ASM_GENERIC_ATOMIC_H  */
> Index: linux-2.6/include/asm-i386/atomic.h
> ===================================================================
> --- linux-2.6.orig/include/asm-i386/atomic.h
> +++ linux-2.6/include/asm-i386/atomic.h
> @@ -207,8 +207,9 @@ 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_xchg(v, new) (xchg(&((v)->counter), new))
> +#define atomic_cmpxchg(v, old, new) \
> +	((__typeof__((v)->counter))cmpxchg(&((v)->counter), (old), (new)))
> +#define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
>  
>  /**
>   * atomic_add_unless - add unless the number is a given value
> @@ -221,7 +222,7 @@ static __inline__ int atomic_sub_return(
>   */
>  #define atomic_add_unless(v, a, u)				\
>  ({								\
> -	int c, old;						\
> +	__typeof__((v)->counter) c, old;			\
>  	c = atomic_read(v);					\
>  	for (;;) {						\
>  		if (unlikely(c == (u)))				\
> Index: linux-2.6/include/asm-ia64/atomic.h
> ===================================================================
> --- linux-2.6.orig/include/asm-ia64/atomic.h
> +++ linux-2.6/include/asm-ia64/atomic.h
> @@ -88,12 +88,17 @@ ia64_atomic64_sub (__s64 i, atomic64_t *
>  	return new;
>  }
>  
> -#define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new))
> +#define atomic_cmpxchg(v, old, new) \
> +	((__typeof__((v)->counter))cmpxchg(&((v)->counter), old, new))
>  #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
>  
> +#define atomic64_cmpxchg(v, old, new) \
> +	((__typeof__((v)->counter))cmpxchg(&((v)->counter), old, new))
> +#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
> +
>  #define atomic_add_unless(v, a, u)				\
>  ({								\
> -	int c, old;						\
> +	__typeof__(v->counter) c, old;				\
>  	c = atomic_read(v);					\
>  	for (;;) {						\
>  		if (unlikely(c == (u)))				\
> @@ -107,6 +112,22 @@ ia64_atomic64_sub (__s64 i, atomic64_t *
>  })
>  #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
>  
> +#define atomic64_add_unless(v, a, u)				\
> +({								\
> +	__typeof__(v->counter) c, old;				\
> +	c = atomic64_read(v);					\
> +	for (;;) {						\
> +		if (unlikely(c == (u)))				\
> +			break;					\
> +		old = atomic64_cmpxchg((v), c, c + (a));	\
> +		if (likely(old == c))				\
> +			break;					\
> +		c = old;					\
> +	}							\
> +	c != (u);						\
> +})
> +#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
> +
>  #define atomic_add_return(i,v)						\
>  ({									\
>  	int __ia64_aar_i = (i);						\
> Index: linux-2.6/include/asm-mips/atomic.h
> ===================================================================
> --- linux-2.6.orig/include/asm-mips/atomic.h
> +++ linux-2.6/include/asm-mips/atomic.h
> @@ -291,8 +291,8 @@ static __inline__ int atomic_sub_if_posi
>  	return result;
>  }
>  
> -#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
> -#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
> +#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
> +#define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
>  
>  /**
>   * atomic_add_unless - add unless the number is a given value
> @@ -305,7 +305,7 @@ static __inline__ int atomic_sub_if_posi
>   */
>  #define atomic_add_unless(v, a, u)				\
>  ({								\
> -	int c, old;						\
> +	__typeof__((v)->counter) c, old;			\
>  	c = atomic_read(v);					\
>  	while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
>  		c = old;					\
> @@ -651,6 +651,28 @@ static __inline__ long atomic64_sub_if_p
>  	return result;
>  }
>  
> +#define atomic64_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
> +#define atomic64_xchg(v, new) (xchg(&((v)->counter), (new)))
> +
> +/**
> + * atomic64_add_unless - add unless the number is a given value
> + * @v: pointer of type atomic64_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 atomic64_add_unless(v, a, u)				\
> +({								\
> +	__typeof__((v)->counter) c, old;			\
> +	c = atomic_read(v);					\
> +	while (c != (u) && (old = atomic64_cmpxchg((v), c, c + (a))) != c) \
> +		c = old;					\
> +	c != (u);						\
> +})
> +#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
> +
>  #define atomic64_dec_return(v) atomic64_sub_return(1,(v))
>  #define atomic64_inc_return(v) atomic64_add_return(1,(v))
>  
> Index: linux-2.6/include/asm-parisc/atomic.h
> ===================================================================
> --- linux-2.6.orig/include/asm-parisc/atomic.h
> +++ linux-2.6/include/asm-parisc/atomic.h
> @@ -163,7 +163,8 @@ static __inline__ int atomic_read(const 
>  }
>  
>  /* exported interface */
> -#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
> +#define atomic_cmpxchg(v, o, n) \
> +	((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
>  #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
>  
>  /**
> @@ -177,7 +178,7 @@ static __inline__ int atomic_read(const 
>   */
>  #define atomic_add_unless(v, a, u)				\
>  ({								\
> -	int c, old;						\
> +	__typeof__((v)->counter) c, old;						\
>  	c = atomic_read(v);					\
>  	while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
>  		c = old;					\
> @@ -270,6 +271,30 @@ atomic64_read(const atomic64_t *v)
>  #define atomic64_dec_and_test(v)	(atomic64_dec_return(v) == 0)
>  #define atomic64_sub_and_test(i,v)	(atomic64_sub_return((i),(v)) == 0)
>  
> +/* exported interface */
> +#define atomic64_cmpxchg(v, o, n) \
> +	((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
> +#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
> +
> +/**
> + * atomic64_add_unless - add unless the number is a given value
> + * @v: pointer of type atomic64_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 atomic64_add_unless(v, a, u)				\
> +({								\
> +	__typeof__((v)->counter) c, old;						\
> +	c = atomic64_read(v);					\
> +	while (c != (u) && (old = atomic64_cmpxchg((v), c, c + (a))) != c) \
> +		c = old;					\
> +	c != (u);						\
> +})
> +#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
> +
>  #endif /* CONFIG_64BIT */
>  
>  #include <asm-generic/atomic.h>
> Index: linux-2.6/include/asm-powerpc/atomic.h
> ===================================================================
> --- linux-2.6.orig/include/asm-powerpc/atomic.h
> +++ linux-2.6/include/asm-powerpc/atomic.h
> @@ -165,7 +165,8 @@ static __inline__ int atomic_dec_return(
>  	return t;
>  }
>  
> -#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
> +#define atomic_cmpxchg(v, o, n) \
> +	((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
>  #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
>  
>  /**
> @@ -413,6 +414,43 @@ static __inline__ long atomic64_dec_if_p
>  	return t;
>  }
>  
> +#define atomic64_cmpxchg(v, o, n) \
> +	((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
> +#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
> +
> +/**
> + * atomic64_add_unless - add unless the number is a given value
> + * @v: pointer of type atomic64_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.
> + */
> +static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
> +{
> +	long t;
> +
> +	__asm__ __volatile__ (
> +	LWSYNC_ON_SMP
> +"1:	ldarx	%0,0,%1		# atomic_add_unless\n\
> +	cmpd	0,%0,%3 \n\
> +	beq-	2f \n\
> +	add	%0,%2,%0 \n"
> +"	stdcx.	%0,0,%1 \n\
> +	bne-	1b \n"
> +	ISYNC_ON_SMP
> +"	subf	%0,%2,%0 \n\
> +2:"
> +	: "=&r" (t)
> +	: "r" (&v->counter), "r" (a), "r" (u)
> +	: "cc", "memory");
> +
> +	return t != u;
> +}
> +
> +#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
> +
>  #endif /* __powerpc64__ */
>  
>  #include <asm-generic/atomic.h>
> Index: linux-2.6/include/asm-powerpc/bitops.h
> ===================================================================
> --- linux-2.6.orig/include/asm-powerpc/bitops.h
> +++ linux-2.6/include/asm-powerpc/bitops.h
> @@ -39,7 +39,6 @@
>  #ifdef __KERNEL__
>  
>  #include <linux/compiler.h>
> -#include <asm/atomic.h>
>  #include <asm/asm-compat.h>
>  #include <asm/synch.h>
>  
> Index: linux-2.6/include/asm-powerpc/system.h
> ===================================================================
> --- linux-2.6.orig/include/asm-powerpc/system.h
> +++ linux-2.6/include/asm-powerpc/system.h
> @@ -7,7 +7,6 @@
>  #include <linux/kernel.h>
>  
>  #include <asm/hw_irq.h>
> -#include <asm/atomic.h>
>  
>  /*
>   * Memory barrier.
> Index: linux-2.6/include/asm-sparc64/atomic.h
> ===================================================================
> --- linux-2.6.orig/include/asm-sparc64/atomic.h
> +++ linux-2.6/include/asm-sparc64/atomic.h
> @@ -70,12 +70,13 @@ 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)))
> +#define atomic_cmpxchg(v, o, n) \
> +	((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
>  #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
>  
>  #define atomic_add_unless(v, a, u)				\
>  ({								\
> -	int c, old;						\
> +	__typeof__((v)->counter) c, old;			\
>  	c = atomic_read(v);					\
>  	for (;;) {						\
>  		if (unlikely(c == (u)))				\
> @@ -89,6 +90,26 @@ extern int atomic64_sub_ret(int, atomic6
>  })
>  #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
>  
> +#define atomic64_cmpxchg(v, o, n) \
> +	((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
> +#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
> +
> +#define atomic64_add_unless(v, a, u)				\
> +({								\
> +	__typeof__((v)->counter) c, old;			\
> +	c = atomic64_read(v);					\
> +	for (;;) {						\
> +		if (unlikely(c == (u)))				\
> +			break;					\
> +		old = atomic64_cmpxchg((v), c, c + (a));	\
> +		if (likely(old == c))				\
> +			break;					\
> +		c = old;					\
> +	}							\
> +	likely(c != (u));					\
> +})
> +#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
> +
>  /* Atomic operations are already serializing */
>  #ifdef CONFIG_SMP
>  #define smp_mb__before_atomic_dec()	membar_storeload_loadload();
> Index: linux-2.6/include/asm-x86_64/atomic.h
> ===================================================================
> --- linux-2.6.orig/include/asm-x86_64/atomic.h
> +++ linux-2.6/include/asm-x86_64/atomic.h
> @@ -375,8 +375,8 @@ static __inline__ long atomic64_add_retu
>  	long __i = i;
>  	__asm__ __volatile__(
>  		LOCK_PREFIX "xaddq %0, %1;"
> -		:"=r"(i)
> -		:"m"(v->counter), "0"(i));
> +		:"+r" (i), "+m" (v->counter)
> +		: : "memory");
>  	return i + __i;
>  }
>  
> @@ -388,7 +388,12 @@ static __inline__ long atomic64_sub_retu
>  #define atomic64_inc_return(v)  (atomic64_add_return(1,v))
>  #define atomic64_dec_return(v)  (atomic64_sub_return(1,v))
>  
> -#define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new))
> +#define atomic64_cmpxchg(v, old, new) \
> +	((__typeof__((v)->counter))cmpxchg(&((v)->counter), old, new))
> +#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
> +
> +#define atomic_cmpxchg(v, old, new) \
> +	((__typeof__((v)->counter))cmpxchg(&((v)->counter), old, new))
>  #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
>  
>  /**
> @@ -402,7 +407,7 @@ static __inline__ long atomic64_sub_retu
>   */
>  #define atomic_add_unless(v, a, u)				\
>  ({								\
> -	int c, old;						\
> +	__typeof__((v)->counter) c, old;			\
>  	c = atomic_read(v);					\
>  	for (;;) {						\
>  		if (unlikely(c == (u)))				\
> @@ -416,6 +421,31 @@ static __inline__ long atomic64_sub_retu
>  })
>  #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
>  
> +/**
> + * atomic64_add_unless - add unless the number is a given value
> + * @v: pointer of type atomic64_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 atomic64_add_unless(v, a, u)				\
> +({								\
> +	__typeof__((v)->counter) c, old;			\
> +	c = atomic64_read(v);					\
> +	for (;;) {						\
> +		if (unlikely(c == (u)))				\
> +			break;					\
> +		old = atomic64_cmpxchg((v), c, c + (a));	\
> +		if (likely(old == c))				\
> +			break;					\
> +		c = old;					\
> +	}							\
> +	c != (u);						\
> +})
> +#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
> +
>  /* These are x86-specific, used by some header files */
>  #define atomic_clear_mask(mask, addr) \
>  __asm__ __volatile__(LOCK_PREFIX "andl %0,%1" \
> 
> 

-- 
OpenPGP public key:              http://krystal.dyndns.org:8080/key/compudj.gpg
Key fingerprint:     8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]