about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTorvald Riegel <triegel@redhat.com>2016-06-14 15:12:00 +0200
committerTorvald Riegel <triegel@redhat.com>2016-06-24 23:04:40 +0300
commit76a0b73e8102c5bfb5cb791e34992472f5d1d33e (patch)
tree2fcd8ece66b944eed3ca046d79651c7a7573736f
parent40244be3729149ff440caf18e445ec17b0d0b511 (diff)
downloadglibc-76a0b73e8102c5bfb5cb791e34992472f5d1d33e.tar.gz
glibc-76a0b73e8102c5bfb5cb791e34992472f5d1d33e.tar.xz
glibc-76a0b73e8102c5bfb5cb791e34992472f5d1d33e.zip
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.
-rw-r--r--ChangeLog30
-rw-r--r--include/atomic.h17
-rw-r--r--nptl/pthread_mutex_unlock.c34
-rw-r--r--nscd/cache.c12
-rw-r--r--sysdeps/aarch64/atomic-machine.h4
-rw-r--r--sysdeps/alpha/atomic-machine.h4
-rw-r--r--sysdeps/arm/atomic-machine.h4
-rw-r--r--sysdeps/microblaze/atomic-machine.h6
-rw-r--r--sysdeps/mips/atomic-machine.h8
-rw-r--r--sysdeps/powerpc/atomic-machine.h6
-rw-r--r--sysdeps/powerpc/powerpc32/atomic-machine.h19
-rw-r--r--sysdeps/powerpc/powerpc64/atomic-machine.h33
-rw-r--r--sysdeps/tile/atomic-machine.h5
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  <triegel@redhat.com>
+
+	* 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  <joseph@codesourcery.com>
 
 	[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 ();                                     \