[ltt-dev] [PATCH 2/2] introduce uatomic_and and uatomic_or

Mathieu Desnoyers compudj at krystal.dyndns.org
Fri Nov 12 07:15:33 EST 2010


* Mathieu Desnoyers (compudj at krystal.dyndns.org) wrote:
> * Paolo Bonzini (pbonzini at redhat.com) wrote:
> > These are useful to flip single bits.
> 
> I'm trying to figure out the semantic of these operations.
> 
> are they
> 
> uatomic_add / uatomic_or or uatomic_add_return / uatomic_or_return ?

It looks like they return the previous value of the variable. So for
consistency with "uatomic_add_return", we should return the value after
the modification. However, given that we're changing the value with the
mask in a way that's not reversible, this means we would lose
information for "and" and "or".

One way we could do it is to specify that what we return is the value
before the op like this:

uatomic_return_add()
uatomic_return_or()

The other question is:

do we really want the "uatomic_or/uatomic_and" to return something ?

Thoughts ?

Mathieu

> 
> Thanks,
> 
> Mathieu
> 
> > 
> > Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
> > ---
> >  tests/test_uatomic.c   |    6 ++
> >  urcu/uatomic_generic.h |  220 ++++++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 226 insertions(+), 0 deletions(-)
> > 
> > diff --git a/tests/test_uatomic.c b/tests/test_uatomic.c
> > index 5682655..f14ed56 100644
> > --- a/tests/test_uatomic.c
> > +++ b/tests/test_uatomic.c
> > @@ -39,6 +39,12 @@ do {						\
> >  	v = uatomic_sub_return(ptr, 1);		\
> >  	assert(v == 121);			\
> >  	assert(uatomic_read(ptr) == 121);	\
> > +	v = uatomic_and(ptr, 0x47);		\
> > +	assert(v == 121);			\
> > +	assert(uatomic_read(ptr) == 0x41);	\
> > +	v = uatomic_or(ptr, 120);		\
> > +	assert(v == 0x41);			\
> > +	assert(uatomic_read(ptr) == 121);	\
> >  } while (0)
> >  
> >  int main(int argc, char **argv)
> > diff --git a/urcu/uatomic_generic.h b/urcu/uatomic_generic.h
> > index 383ddfa..7f3bc00 100644
> > --- a/urcu/uatomic_generic.h
> > +++ b/urcu/uatomic_generic.h
> > @@ -87,6 +87,74 @@ unsigned long _uatomic_cmpxchg(void *addr, unsigned long old,
> >  						sizeof(*(addr))))
> >  
> >  
> > +/* uatomic_and */
> > +
> > +#ifndef uatomic_and
> > +static inline __attribute__((always_inline))
> > +unsigned long _uatomic_and(void *addr, unsigned long val,
> > +				 int len)
> > +{
> > +	switch (len) {
> > +#ifdef UATOMIC_HAS_ATOMIC_BYTE
> > +	case 1:
> > +		return __sync_fetch_and_and_1(addr, val);
> > +#endif
> > +#ifdef UATOMIC_HAS_ATOMIC_SHORT
> > +	case 2:
> > +		return __sync_fetch_and_and_2(addr, val);
> > +#endif
> > +	case 4:
> > +		return __sync_fetch_and_and_4(addr, val);
> > +#if (BITS_PER_LONG == 64)
> > +	case 8:
> > +		return __sync_fetch_and_and_8(addr, val);
> > +#endif
> > +	}
> > +	_uatomic_link_error();
> > +	return 0;
> > +}
> > +
> > +
> > +#define uatomic_and(addr, v)					\
> > +	((__typeof__(*(addr))) _uatomic_and((addr),		\
> > +					    (unsigned long)(v),	\
> > +					    sizeof(*(addr))))
> > +#endif /* #ifndef uatomic_and */
> > +
> > +/* uatomic_or */
> > +
> > +#ifndef uatomic_or
> > +static inline __attribute__((always_inline))
> > +unsigned long _uatomic_or(void *addr, unsigned long val,
> > +				 int len)
> > +{
> > +	switch (len) {
> > +#ifdef UATOMIC_HAS_ATOMIC_BYTE
> > +	case 1:
> > +		return __sync_fetch_and_or_1(addr, val);
> > +#endif
> > +#ifdef UATOMIC_HAS_ATOMIC_SHORT
> > +	case 2:
> > +		return __sync_fetch_and_or_2(addr, val);
> > +#endif
> > +	case 4:
> > +		return __sync_fetch_and_or_4(addr, val);
> > +#if (BITS_PER_LONG == 64)
> > +	case 8:
> > +		return __sync_fetch_and_or_8(addr, val);
> > +#endif
> > +	}
> > +	_uatomic_link_error();
> > +	return 0;
> > +}
> > +
> > +
> > +#define uatomic_or(addr, v)					\
> > +	((__typeof__(*(addr))) _uatomic_or((addr),		\
> > +					   (unsigned long)(v),	\
> > +					   sizeof(*(addr))))
> > +#endif /* #ifndef uatomic_or */
> > +
> >  /* uatomic_add_return */
> >  
> >  #ifndef uatomic_add_return
> > @@ -186,6 +254,158 @@ unsigned long _uatomic_exchange(void *addr, unsigned long val, int len)
> >  
> >  #else /* #ifndef uatomic_cmpxchg */
> >  
> > +#ifndef uatomic_and
> > +/* uatomic_and */
> > +
> > +static inline __attribute__((always_inline))
> > +unsigned long _uatomic_and(void *addr, unsigned long val, int len)
> > +{
> > +	switch (len) {
> > +#ifdef UATOMIC_HAS_ATOMIC_BYTE
> > +	case 1:
> > +	{
> > +		unsigned char old, oldt;
> > +
> > +		oldt = uatomic_read((unsigned char *)addr);
> > +		do {
> > +			old = oldt;
> > +			oldt = uatomic_cmpxchg((unsigned char *)addr,
> > +                                               old, old & val);
> > +		} while (oldt != old);
> > +
> > +		return old;
> > +	}
> > +#endif
> > +#ifdef UATOMIC_HAS_ATOMIC_SHORT
> > +	case 2:
> > +	{
> > +		unsigned short old, oldt;
> > +
> > +		oldt = uatomic_read((unsigned short *)addr);
> > +		do {
> > +			old = oldt;
> > +			oldt = uatomic_cmpxchg((unsigned short *)addr,
> > +                                               old, old & val);
> > +		} while (oldt != old);
> > +
> > +		return old;
> > +	}
> > +#endif
> > +	case 4:
> > +	{
> > +		unsigned int old, oldt;
> > +
> > +		oldt = uatomic_read((unsigned int *)addr);
> > +		do {
> > +			old = oldt;
> > +			oldt = uatomic_cmpxchg((unsigned int *)addr,
> > +                                               old, old & val);
> > +		} while (oldt != old);
> > +
> > +		return old;
> > +	}
> > +#if (BITS_PER_LONG == 64)
> > +	case 8:
> > +	{
> > +		unsigned long old, oldt;
> > +
> > +		oldt = uatomic_read((unsigned long *)addr);
> > +		do {
> > +			old = oldt;
> > +			oldt = uatomic_cmpxchg((unsigned long *)addr,
> > +                                               old, old & val);
> > +		} while (oldt != old);
> > +
> > +		return old;
> > +	}
> > +#endif
> > +	}
> > +	_uatomic_link_error();
> > +	return 0;
> > +}
> > +
> > +#define uatomic_and(addr, v)					\
> > +	((__typeof__(*(addr))) _uatomic_and((addr),		\
> > +					    (unsigned long)(v),	\
> > +					    sizeof(*(addr))))
> > +#endif /* #ifndef uatomic_and */
> > +
> > +#ifndef uatomic_or
> > +/* uatomic_or */
> > +
> > +static inline __attribute__((always_inline))
> > +unsigned long _uatomic_or(void *addr, unsigned long val, int len)
> > +{
> > +	switch (len) {
> > +#ifdef UATOMIC_HAS_ATOMIC_BYTE
> > +	case 1:
> > +	{
> > +		unsigned char old, oldt;
> > +
> > +		oldt = uatomic_read((unsigned char *)addr);
> > +		do {
> > +			old = oldt;
> > +			oldt = uatomic_cmpxchg((unsigned char *)addr,
> > +                                               old, old | val);
> > +		} while (oldt != old);
> > +
> > +		return old;
> > +	}
> > +#endif
> > +#ifdef UATOMIC_HAS_ATOMIC_SHORT
> > +	case 2:
> > +	{
> > +		unsigned short old, oldt;
> > +
> > +		oldt = uatomic_read((unsigned short *)addr);
> > +		do {
> > +			old = oldt;
> > +			oldt = uatomic_cmpxchg((unsigned short *)addr,
> > +                                               old, old | val);
> > +		} while (oldt != old);
> > +
> > +		return old;
> > +	}
> > +#endif
> > +	case 4:
> > +	{
> > +		unsigned int old, oldt;
> > +
> > +		oldt = uatomic_read((unsigned int *)addr);
> > +		do {
> > +			old = oldt;
> > +			oldt = uatomic_cmpxchg((unsigned int *)addr,
> > +                                               old, old | val);
> > +		} while (oldt != old);
> > +
> > +		return old;
> > +	}
> > +#if (BITS_PER_LONG == 64)
> > +	case 8:
> > +	{
> > +		unsigned long old, oldt;
> > +
> > +		oldt = uatomic_read((unsigned long *)addr);
> > +		do {
> > +			old = oldt;
> > +			oldt = uatomic_cmpxchg((unsigned long *)addr,
> > +                                               old, old | val);
> > +		} while (oldt != old);
> > +
> > +		return old;
> > +	}
> > +#endif
> > +	}
> > +	_uatomic_link_error();
> > +	return 0;
> > +}
> > +
> > +#define uatomic_or(addr, v)					\
> > +	((__typeof__(*(addr))) _uatomic_or((addr),		\
> > +					   (unsigned long)(v),	\
> > +					   sizeof(*(addr))))
> > +#endif /* #ifndef uatomic_or */
> > +
> >  #ifndef uatomic_add_return
> >  /* uatomic_add_return */
> >  
> > -- 
> > 1.7.3.2
> > 
> > 
> > _______________________________________________
> > ltt-dev mailing list
> > ltt-dev at lists.casi.polymtl.ca
> > http://lists.casi.polymtl.ca/cgi-bin/mailman/listinfo/ltt-dev
> > 
> 
> -- 
> Mathieu Desnoyers
> Operating System Efficiency R&D Consultant
> EfficiOS Inc.
> http://www.efficios.com
> 
> _______________________________________________
> ltt-dev mailing list
> ltt-dev at lists.casi.polymtl.ca
> http://lists.casi.polymtl.ca/cgi-bin/mailman/listinfo/ltt-dev
> 

-- 
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com




More information about the lttng-dev mailing list