From 76a0b73e8102c5bfb5cb791e34992472f5d1d33e Mon Sep 17 00:00:00 2001 From: Torvald Riegel Date: Tue, 14 Jun 2016 15:12:00 +0200 Subject: [PATCH] Remove atomic_compare_and_exchange_bool_rel. atomic_compare_and_exchange_bool_rel and catomic_compare_and_exchange_bool_rel are removed and replaced with the new C11-like atomic_compare_exchange_weak_release. The concurrent code in nscd/cache.c has not been reviewed yet, so this patch does not add detailed comments. * nscd/cache.c (cache_add): Use new C11-like atomic operation instead of atomic_compare_and_exchange_bool_rel. * nptl/pthread_mutex_unlock.c (__pthread_mutex_unlock_full): Likewise. * include/atomic.h (atomic_compare_and_exchange_bool_rel, catomic_compare_and_exchange_bool_rel): Remove. * sysdeps/aarch64/atomic-machine.h (atomic_compare_and_exchange_bool_rel): Likewise. * sysdeps/alpha/atomic-machine.h (atomic_compare_and_exchange_bool_rel): Likewise. * sysdeps/arm/atomic-machine.h (atomic_compare_and_exchange_bool_rel): Likewise. * sysdeps/mips/atomic-machine.h (atomic_compare_and_exchange_bool_rel): Likewise. * sysdeps/tile/atomic-machine.h (atomic_compare_and_exchange_bool_rel): Likewise. --- ChangeLog | 30 +++++++++++++++++++ include/atomic.h | 17 ----------- nptl/pthread_mutex_unlock.c | 34 ++++++++++++++-------- nscd/cache.c | 12 ++++---- sysdeps/aarch64/atomic-machine.h | 4 --- sysdeps/alpha/atomic-machine.h | 4 --- sysdeps/arm/atomic-machine.h | 4 --- sysdeps/microblaze/atomic-machine.h | 6 ---- sysdeps/mips/atomic-machine.h | 8 ----- sysdeps/powerpc/atomic-machine.h | 6 ---- sysdeps/powerpc/powerpc32/atomic-machine.h | 19 ------------ sysdeps/powerpc/powerpc64/atomic-machine.h | 33 --------------------- sysdeps/tile/atomic-machine.h | 5 ---- 13 files changed, 58 insertions(+), 124 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3d6dad2167..eaf8fed118 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +2016-06-24 Torvald Riegel + + * nscd/cache.c (cache_add): Use new C11-like atomic operation instead + of atomic_compare_and_exchange_bool_rel. + * nptl/pthread_mutex_unlock.c (__pthread_mutex_unlock_full): Likewise. + * include/atomic.h (atomic_compare_and_exchange_bool_rel, + catomic_compare_and_exchange_bool_rel): Remove. + * sysdeps/aarch64/atomic-machine.h + (atomic_compare_and_exchange_bool_rel): Likewise. + * sysdeps/alpha/atomic-machine.h + (atomic_compare_and_exchange_bool_rel): Likewise. + * sysdeps/arm/atomic-machine.h + (atomic_compare_and_exchange_bool_rel): Likewise. + * sysdeps/mips/atomic-machine.h + (atomic_compare_and_exchange_bool_rel): Likewise. + * sysdeps/microblaze/atomic-machine.h + ( __arch_compare_and_exchange_bool_8_rel, + __arch_compare_and_exchange_bool_16_rel): Likewise. + * sysdeps/powerpc/atomic-machine.h + ( __arch_compare_and_exchange_bool_8_rel, + __arch_compare_and_exchange_bool_16_rel): Likewise. + * sysdeps/powerpc/powerpc32/atomic-machine.h + ( __arch_compare_and_exchange_bool_32_rel, + __arch_compare_and_exchange_bool_64_rel): Likewise. + * sysdeps/powerpc/powerpc64/atomic-machine.h + ( __arch_compare_and_exchange_bool_32_rel, + __arch_compare_and_exchange_bool_64_rel): Likewise. + * sysdeps/tile/atomic-machine.h + (atomic_compare_and_exchange_bool_rel): Likewise. + 2016-06-23 Joseph Myers [BZ #20296] diff --git a/include/atomic.h b/include/atomic.h index 5e8bfffa08..ad3db2562e 100644 --- a/include/atomic.h +++ b/include/atomic.h @@ -159,23 +159,6 @@ #endif -#ifndef catomic_compare_and_exchange_bool_rel -# ifndef atomic_compare_and_exchange_bool_rel -# define catomic_compare_and_exchange_bool_rel(mem, newval, oldval) \ - catomic_compare_and_exchange_bool_acq (mem, newval, oldval) -# else -# define catomic_compare_and_exchange_bool_rel(mem, newval, oldval) \ - atomic_compare_and_exchange_bool_rel (mem, newval, oldval) -# endif -#endif - - -#ifndef atomic_compare_and_exchange_bool_rel -# define atomic_compare_and_exchange_bool_rel(mem, newval, oldval) \ - atomic_compare_and_exchange_bool_acq (mem, newval, oldval) -#endif - - /* Store NEWVALUE in *MEM and return the old value. */ #ifndef atomic_exchange_acq # define atomic_exchange_acq(mem, newvalue) \ diff --git a/nptl/pthread_mutex_unlock.c b/nptl/pthread_mutex_unlock.c index 334ce38342..82aaa95d7b 100644 --- a/nptl/pthread_mutex_unlock.c +++ b/nptl/pthread_mutex_unlock.c @@ -237,15 +237,24 @@ __pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr) int private = (robust ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex) : PTHREAD_MUTEX_PSHARED (mutex)); - if ((mutex->__data.__lock & FUTEX_WAITERS) != 0 - || atomic_compare_and_exchange_bool_rel (&mutex->__data.__lock, 0, - THREAD_GETMEM (THREAD_SELF, - tid))) + /* Unlock the mutex using a CAS unless there are futex waiters or our + TID is not the value of __lock anymore, in which case we let the + kernel take care of the situation. Use release MO in the CAS to + synchronize with acquire MO in lock acquisitions. */ + int l = atomic_load_relaxed (&mutex->__data.__lock); + do { - INTERNAL_SYSCALL_DECL (__err); - INTERNAL_SYSCALL (futex, __err, 2, &mutex->__data.__lock, - __lll_private_flag (FUTEX_UNLOCK_PI, private)); + if (((l & FUTEX_WAITERS) != 0) + || (l != THREAD_GETMEM (THREAD_SELF, tid))) + { + INTERNAL_SYSCALL_DECL (__err); + INTERNAL_SYSCALL (futex, __err, 2, &mutex->__data.__lock, + __lll_private_flag (FUTEX_UNLOCK_PI, private)); + break; + } } + while (!atomic_compare_exchange_weak_release (&mutex->__data.__lock, + &l, 0)); THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); break; @@ -278,15 +287,16 @@ __pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr) /* One less user. */ --mutex->__data.__nusers; - /* Unlock. */ - int newval, oldval; + /* Unlock. Use release MO in the CAS to synchronize with acquire MO in + lock acquisitions. */ + int newval; + int oldval = atomic_load_relaxed (&mutex->__data.__lock); do { - oldval = mutex->__data.__lock; newval = oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK; } - while (atomic_compare_and_exchange_bool_rel (&mutex->__data.__lock, - newval, oldval)); + while (!atomic_compare_exchange_weak_release (&mutex->__data.__lock, + &oldval, newval)); if ((oldval & ~PTHREAD_MUTEX_PRIO_CEILING_MASK) > 1) lll_futex_wake (&mutex->__data.__lock, 1, diff --git a/nscd/cache.c b/nscd/cache.c index 3021abd41e..daa0b2bfd1 100644 --- a/nscd/cache.c +++ b/nscd/cache.c @@ -178,12 +178,12 @@ cache_add (int type, const void *key, size_t len, struct datahead *packet, assert ((newp->packet & BLOCK_ALIGN_M1) == 0); /* Put the new entry in the first position. */ - do - newp->next = table->head->array[hash]; - while (atomic_compare_and_exchange_bool_rel (&table->head->array[hash], - (ref_t) ((char *) newp - - table->data), - (ref_t) newp->next)); + /* TODO Review concurrency. Use atomic_exchange_release. */ + newp->next = atomic_load_relaxed (&table->head->array[hash]); + while (!atomic_compare_exchange_weak_release (&table->head->array[hash], + (ref_t *) &newp->next, + (ref_t) ((char *) newp + - table->data))); /* Update the statistics. */ if (packet->notfound) diff --git a/sysdeps/aarch64/atomic-machine.h b/sysdeps/aarch64/atomic-machine.h index 28c80dc42d..6708b9bc7c 100644 --- a/sysdeps/aarch64/atomic-machine.h +++ b/sysdeps/aarch64/atomic-machine.h @@ -115,10 +115,6 @@ typedef uintmax_t uatomic_max_t; /* Compare and exchange with "release" semantics, ie barrier before. */ -# define atomic_compare_and_exchange_bool_rel(mem, new, old) \ - __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \ - mem, new, old, __ATOMIC_RELEASE) - # define atomic_compare_and_exchange_val_rel(mem, new, old) \ __atomic_val_bysize (__arch_compare_and_exchange_val, int, \ mem, new, old, __ATOMIC_RELEASE) diff --git a/sysdeps/alpha/atomic-machine.h b/sysdeps/alpha/atomic-machine.h index d96cb7aa93..882d8000f7 100644 --- a/sysdeps/alpha/atomic-machine.h +++ b/sysdeps/alpha/atomic-machine.h @@ -210,10 +210,6 @@ typedef uintmax_t uatomic_max_t; /* Compare and exchange with "release" semantics, ie barrier before. */ -#define atomic_compare_and_exchange_bool_rel(mem, new, old) \ - __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \ - mem, new, old, __MB, "") - #define atomic_compare_and_exchange_val_rel(mem, new, old) \ __atomic_val_bysize (__arch_compare_and_exchange_val, int, \ mem, new, old, __MB, "") diff --git a/sysdeps/arm/atomic-machine.h b/sysdeps/arm/atomic-machine.h index dd5e7141a4..916c09a57d 100644 --- a/sysdeps/arm/atomic-machine.h +++ b/sysdeps/arm/atomic-machine.h @@ -87,10 +87,6 @@ void __arm_link_error (void); /* Compare and exchange with "release" semantics, ie barrier before. */ -# define atomic_compare_and_exchange_bool_rel(mem, new, old) \ - __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \ - mem, new, old, __ATOMIC_RELEASE) - # define atomic_compare_and_exchange_val_rel(mem, new, old) \ __atomic_val_bysize (__arch_compare_and_exchange_val, int, \ mem, new, old, __ATOMIC_RELEASE) diff --git a/sysdeps/microblaze/atomic-machine.h b/sysdeps/microblaze/atomic-machine.h index af7acacc96..229fd4975d 100644 --- a/sysdeps/microblaze/atomic-machine.h +++ b/sysdeps/microblaze/atomic-machine.h @@ -47,12 +47,6 @@ typedef uintmax_t uatomic_max_t; #define __arch_compare_and_exchange_bool_16_acq(mem, newval, oldval) \ (abort (), 0) -#define __arch_compare_and_exchange_bool_8_rel(mem, newval, oldval) \ - (abort (), 0) - -#define __arch_compare_and_exchange_bool_16_rel(mem, newval, oldval) \ - (abort (), 0) - #define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ ({ \ __typeof (*(mem)) __tmp; \ diff --git a/sysdeps/mips/atomic-machine.h b/sysdeps/mips/atomic-machine.h index a60e4fbac8..771166b1e2 100644 --- a/sysdeps/mips/atomic-machine.h +++ b/sysdeps/mips/atomic-machine.h @@ -149,10 +149,6 @@ typedef uintmax_t uatomic_max_t; /* Compare and exchange with "release" semantics, ie barrier before. */ -# define atomic_compare_and_exchange_bool_rel(mem, new, old) \ - __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \ - mem, new, old, __ATOMIC_RELEASE) - # define atomic_compare_and_exchange_val_rel(mem, new, old) \ __atomic_val_bysize (__arch_compare_and_exchange_val, int, \ mem, new, old, __ATOMIC_RELEASE) @@ -330,10 +326,6 @@ typedef uintmax_t uatomic_max_t; /* Compare and exchange with "release" semantics, ie barrier before. */ -# define atomic_compare_and_exchange_bool_rel(mem, new, old) \ - __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \ - mem, new, old, MIPS_SYNC_STR, "") - # define atomic_compare_and_exchange_val_rel(mem, new, old) \ __atomic_val_bysize (__arch_compare_and_exchange_val, int, \ mem, new, old, MIPS_SYNC_STR, "") diff --git a/sysdeps/powerpc/atomic-machine.h b/sysdeps/powerpc/atomic-machine.h index 8b0e1e7284..c6b9eea1f4 100644 --- a/sysdeps/powerpc/atomic-machine.h +++ b/sysdeps/powerpc/atomic-machine.h @@ -53,12 +53,6 @@ typedef uintmax_t uatomic_max_t; #define __arch_compare_and_exchange_bool_16_acq(mem, newval, oldval) \ (abort (), 0) -#define __arch_compare_and_exchange_bool_8_rel(mem, newval, oldval) \ - (abort (), 0) - -#define __arch_compare_and_exchange_bool_16_rel(mem, newval, oldval) \ - (abort (), 0) - #ifdef UP # define __ARCH_ACQ_INSTR "" # define __ARCH_REL_INSTR "" diff --git a/sysdeps/powerpc/powerpc32/atomic-machine.h b/sysdeps/powerpc/powerpc32/atomic-machine.h index 1d407b3490..40a8b7b966 100644 --- a/sysdeps/powerpc/powerpc32/atomic-machine.h +++ b/sysdeps/powerpc/powerpc32/atomic-machine.h @@ -58,22 +58,6 @@ __tmp != 0; \ }) -#define __arch_compare_and_exchange_bool_32_rel(mem, newval, oldval) \ -({ \ - unsigned int __tmp; \ - __asm __volatile (__ARCH_REL_INSTR "\n" \ - "1: lwarx %0,0,%1" MUTEX_HINT_REL "\n" \ - " subf. %0,%2,%0\n" \ - " bne 2f\n" \ - " stwcx. %3,0,%1\n" \ - " bne- 1b\n" \ - "2: " \ - : "=&r" (__tmp) \ - : "b" (mem), "r" (oldval), "r" (newval) \ - : "cr0", "memory"); \ - __tmp != 0; \ -}) - /* Powerpc32 processors don't implement the 64-bit (doubleword) forms of load and reserve (ldarx) and store conditional (stdcx.) instructions. So for powerpc32 we stub out the 64-bit forms. */ @@ -83,9 +67,6 @@ #define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ (abort (), (__typeof (*mem)) 0) -#define __arch_compare_and_exchange_bool_64_rel(mem, newval, oldval) \ - (abort (), 0) - #define __arch_compare_and_exchange_val_64_rel(mem, newval, oldval) \ (abort (), (__typeof (*mem)) 0) diff --git a/sysdeps/powerpc/powerpc64/atomic-machine.h b/sysdeps/powerpc/powerpc64/atomic-machine.h index 751487a3a7..797131865e 100644 --- a/sysdeps/powerpc/powerpc64/atomic-machine.h +++ b/sysdeps/powerpc/powerpc64/atomic-machine.h @@ -58,23 +58,6 @@ __tmp != 0; \ }) -#define __arch_compare_and_exchange_bool_32_rel(mem, newval, oldval) \ -({ \ - unsigned int __tmp, __tmp2; \ - __asm __volatile (__ARCH_REL_INSTR "\n" \ - " clrldi %1,%1,32\n" \ - "1: lwarx %0,0,%2" MUTEX_HINT_REL "\n" \ - " subf. %0,%1,%0\n" \ - " bne 2f\n" \ - " stwcx. %4,0,%2\n" \ - " bne- 1b\n" \ - "2: " \ - : "=&r" (__tmp), "=r" (__tmp2) \ - : "b" (mem), "1" (oldval), "r" (newval) \ - : "cr0", "memory"); \ - __tmp != 0; \ -}) - /* * Only powerpc64 processors support Load doubleword and reserve index (ldarx) * and Store doubleword conditional indexed (stdcx) instructions. So here @@ -96,22 +79,6 @@ __tmp != 0; \ }) -#define __arch_compare_and_exchange_bool_64_rel(mem, newval, oldval) \ -({ \ - unsigned long __tmp; \ - __asm __volatile (__ARCH_REL_INSTR "\n" \ - "1: ldarx %0,0,%1" MUTEX_HINT_REL "\n" \ - " subf. %0,%2,%0\n" \ - " bne 2f\n" \ - " stdcx. %3,0,%1\n" \ - " bne- 1b\n" \ - "2: " \ - : "=&r" (__tmp) \ - : "b" (mem), "r" (oldval), "r" (newval) \ - : "cr0", "memory"); \ - __tmp != 0; \ -}) - #define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ ({ \ __typeof (*(mem)) __tmp; \ diff --git a/sysdeps/tile/atomic-machine.h b/sysdeps/tile/atomic-machine.h index 651e0d930a..336518c68d 100644 --- a/sysdeps/tile/atomic-machine.h +++ b/sysdeps/tile/atomic-machine.h @@ -55,11 +55,6 @@ typedef uintmax_t uatomic_max_t; atomic_full_barrier (); \ atomic_compare_and_exchange_val_acq ((mem), (n), (o)); \ }) -#define atomic_compare_and_exchange_bool_rel(mem, n, o) \ - ({ \ - atomic_full_barrier (); \ - atomic_compare_and_exchange_bool_acq ((mem), (n), (o)); \ - }) #define atomic_exchange_rel(mem, n) \ ({ \ atomic_full_barrier (); \