This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc 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]

powerpc pthread_once bug fix


This fixes some bugs in the powerpc pthread_once code.  Ref
gcc.gnu.org/bugzilla/show_bug.cgi?id=52839#c10

Release barriers are needed to ensure any memory written by
init_routine is seen by other threads before *once_control changes.
In the case of clear_once_control we need to flush any partially
written state.

2012-06-28  Alan Modra  <amodra@gmail.com>

	* sysdeps/unix/sysv/linux/powerpc/pthread_once.c (__pthread_once):
	Add release barrier before setting once_control to say
	initialisation is done.  Add hints on lwarx.  Use macro in
	place of isync.
	(clear_once_control): Add release barrier.


diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c b/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c
index 4e3d7bd..bb1ebf2 100644
--- a/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c
+++ b/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c
@@ -28,6 +28,7 @@ clear_once_control (void *arg)
 {
   pthread_once_t *once_control = (pthread_once_t *) arg;
 
+  __asm __volatile (__lll_rel_instr);
   *once_control = 0;
   lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
 }
@@ -47,15 +48,15 @@ __pthread_once (pthread_once_t *once_control, void (*init_routine) (void))
 	 oldval = *once_control;
 	 if ((oldval & 2) == 0)
 	   *once_control = newval;
-	 Do this atomically.
+	 Do this atomically with an acquire barrier.
       */
       newval = __fork_generation | 1;
-      __asm __volatile ("1:	lwarx	%0,0,%3\n"
+      __asm __volatile ("1:	lwarx	%0,0,%3" MUTEX_HINT_ACQ "\n"
 			"	andi.	%1,%0,2\n"
 			"	bne	2f\n"
 			"	stwcx.	%4,0,%3\n"
 			"	bne	1b\n"
-			"2:	isync"
+			"2:	" __lll_acq_instr
 			: "=&r" (oldval), "=&r" (tmp), "=m" (*once_control)
 			: "r" (once_control), "r" (newval), "m" (*once_control)
 			: "cr0");
@@ -87,8 +88,18 @@ __pthread_once (pthread_once_t *once_control, void (*init_routine) (void))
   pthread_cleanup_pop (0);
 
 
-  /* Add one to *once_control to take the bottom 2 bits from 01 to 10.  */
-  atomic_increment (once_control);
+  /* Add one to *once_control to take the bottom 2 bits from 01 to 10.
+     A release barrier is needed to ensure memory written by init_routine
+     is seen in other threads before *once_control changes.  */
+  int tmp;
+  __asm __volatile (__lll_rel_instr "\n"
+		    "1:	lwarx	%0,0,%2" MUTEX_HINT_REL "\n"
+		    "	addi	%0,%0,1\n"
+		    "	stwcx.	%0,0,%2\n"
+		    "	bne-	1b"
+		    : "=&r" (tmp), "=m" (*once_control)
+		    : "r" (once_control), "m" (*once_control)
+		    : "cr0");
 
   /* Wake up all other threads.  */
   lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);

-- 
Alan Modra
Australia Development Lab, IBM


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