From mboxrd@z Thu Jan 1 00:00:00 1970 From: pbonzini@redhat.com (Paolo Bonzini) Date: Fri, 12 Nov 2010 09:57:27 +0100 Subject: [ltt-dev] [PATCH 2/2] introduce uatomic_and and uatomic_or In-Reply-To: <1289552247-18130-1-git-send-email-pbonzini@redhat.com> References: <1289552247-18130-1-git-send-email-pbonzini@redhat.com> Message-ID: <1289552247-18130-3-git-send-email-pbonzini@redhat.com> These are useful to flip single bits. Signed-off-by: Paolo Bonzini --- 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