Patchwork Use atomics in remaining libgomp/config/linux sources

login
register
mail settings
Submitter Alan Modra
Date Dec. 1, 2011, 9:44 a.m.
Message ID <20111201094419.GG28621@bubble.grove.modra.org>
Download mbox | patch
Permalink /patch/128676/
State New
Headers show

Comments

Alan Modra - Dec. 1, 2011, 9:44 a.m.
This converts the remaining files in libgomp/config/linux/ to use
atomics.  gomp_init_thread_affinity fairly obviously needs no
barriers;  I wasn't so sure about ptrlock, so tried without the
acquire/release barriers and found a number of the loop tests failed.
So it seems the usual lock barriers are needed.  I also fixed a
slightly confusing use of compare_and_swap in gomp_ptrlock_set,
followed by an unconditional store in gomp_ptrlock_set_slow.  If we're
going to write to the thing anyway, we may as well not use the compare
form.

Bootstrapped etc. powerpc-linux.  I did see a libgomp testsuite
failure when testing this (pr51376), but virgin gcc also has the same
failure.

	* config/linux/affinity.c: Use atomic rather than sync builtin.
	* config/linux/lock.c: Likewise.
	* config/linux/ptrlock.h: Likewise.
	* config/linux/ptrlock.c: Likewise.
	* config/linux/ptrlock.h (gomp_ptrlock_set): Always write here..
	* config/linux/ptrlock.c (gomp_ptrlock_set_slow): ..not here.
	* config/linux/futex.h (atomic_write_barrier): Delete unused function.
	* config/linux/alpha/futex.h (atomic_write_barrier): Likewise.
	* config/linux/ia64/futex.h (atomic_write_barrier): Likewise.
	* config/linux/mips/futex.h (atomic_write_barrier): Likewise.
	* config/linux/powerpc/futex.h (atomic_write_barrier): Likewise.
	* config/linux/s390/futex.h (atomic_write_barrier): Likewise.
	* config/linux/sparc/futex.h (atomic_write_barrier): Likewise.
	* config/linux/x86/futex.h (atomic_write_barrier): Likewise.
Richard Henderson - Dec. 1, 2011, 4:49 p.m.
On 12/01/2011 01:44 AM, Alan Modra wrote:
> 	* config/linux/affinity.c: Use atomic rather than sync builtin.
> 	* config/linux/lock.c: Likewise.
> 	* config/linux/ptrlock.h: Likewise.
> 	* config/linux/ptrlock.c: Likewise.
> 	* config/linux/ptrlock.h (gomp_ptrlock_set): Always write here..
> 	* config/linux/ptrlock.c (gomp_ptrlock_set_slow): ..not here.
> 	* config/linux/futex.h (atomic_write_barrier): Delete unused function.
> 	* config/linux/alpha/futex.h (atomic_write_barrier): Likewise.
> 	* config/linux/ia64/futex.h (atomic_write_barrier): Likewise.
> 	* config/linux/mips/futex.h (atomic_write_barrier): Likewise.
> 	* config/linux/powerpc/futex.h (atomic_write_barrier): Likewise.
> 	* config/linux/s390/futex.h (atomic_write_barrier): Likewise.
> 	* config/linux/sparc/futex.h (atomic_write_barrier): Likewise.
> 	* config/linux/x86/futex.h (atomic_write_barrier): Likewise.

Ok.


r~

Patch

Index: libgomp/config/linux/affinity.c
===================================================================
--- libgomp/config/linux/affinity.c	(revision 181830)
+++ libgomp/config/linux/affinity.c	(working copy)
@@ -109,7 +109,7 @@  gomp_init_thread_affinity (pthread_attr_
   unsigned int cpu;
   cpu_set_t cpuset;
 
-  cpu = __sync_fetch_and_add (&affinity_counter, 1);
+  cpu = __atomic_fetch_add (&affinity_counter, 1, MEMMODEL_RELAXED);
   cpu %= gomp_cpu_affinity_len;
   CPU_ZERO (&cpuset);
   CPU_SET (gomp_cpu_affinity[cpu], &cpuset);
Index: libgomp/config/linux/lock.c
===================================================================
--- libgomp/config/linux/lock.c	(revision 181830)
+++ libgomp/config/linux/lock.c	(working copy)
@@ -1,4 +1,4 @@ 
-/* Copyright (C) 2005, 2008, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2008, 2009, 2011 Free Software Foundation, Inc.
    Contributed by Richard Henderson <rth@redhat.com>.
 
    This file is part of the GNU OpenMP Library (libgomp).
@@ -62,7 +62,10 @@  gomp_unset_lock_30 (omp_lock_t *lock)
 int
 gomp_test_lock_30 (omp_lock_t *lock)
 {
-  return __sync_bool_compare_and_swap (lock, 0, 1);
+  int oldval = 0;
+
+  return __atomic_compare_exchange_n (lock, &oldval, 1, false,
+				      MEMMODEL_ACQUIRE, MEMMODEL_RELAXED);
 }
 
 void
@@ -104,11 +107,14 @@  int
 gomp_test_nest_lock_30 (omp_nest_lock_t *lock)
 {
   void *me = gomp_icv (true);
+  int oldval;
 
   if (lock->owner == me)
     return ++lock->count;
 
-  if (__sync_bool_compare_and_swap (&lock->lock, 0, 1))
+  oldval = 0;
+  if (__atomic_compare_exchange_n (&lock->lock, &oldval, 1, false,
+				   MEMMODEL_ACQUIRE, MEMMODEL_RELAXED))
     {
       lock->owner = me;
       lock->count = 1;
@@ -184,8 +190,9 @@  gomp_set_nest_lock_25 (omp_nest_lock_25_
 
   while (1)
     {
-      otid = __sync_val_compare_and_swap (&lock->owner, 0, tid);
-      if (otid == 0)
+      otid = 0;
+      if (__atomic_compare_exchange_n (&lock->owner, &otid, tid, false,
+				       MEMMODEL_ACQUIRE, MEMMODEL_RELAXED))
 	{
 	  lock->count = 1;
 	  return;
@@ -207,7 +214,7 @@  gomp_unset_nest_lock_25 (omp_nest_lock_2
 
   if (--lock->count == 0)
     {
-      __sync_lock_release (&lock->owner);
+      __atomic_store_n (&lock->owner, 0, MEMMODEL_RELEASE);
       futex_wake (&lock->owner, 1);
     }
 }
@@ -217,8 +224,9 @@  gomp_test_nest_lock_25 (omp_nest_lock_25
 {
   int otid, tid = gomp_tid ();
 
-  otid = __sync_val_compare_and_swap (&lock->owner, 0, tid);
-  if (otid == 0)
+  otid = 0;
+  if (__atomic_compare_exchange_n (&lock->owner, &otid, tid, false,
+				   MEMMODEL_ACQUIRE, MEMMODEL_RELAXED))
     {
       lock->count = 1;
       return 1;
Index: libgomp/config/linux/ptrlock.h
===================================================================
--- libgomp/config/linux/ptrlock.h	(revision 181830)
+++ libgomp/config/linux/ptrlock.h	(working copy)
@@ -1,4 +1,4 @@ 
-/* Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc.
    Contributed by Jakub Jelinek <jakub@redhat.com>.
 
    This file is part of the GNU OpenMP Library (libgomp).
@@ -24,7 +24,14 @@ 
 
 /* This is a Linux specific implementation of a mutex synchronization
    mechanism for libgomp.  This type is private to the library.  This
-   implementation uses atomic instructions and the futex syscall.  */
+   implementation uses atomic instructions and the futex syscall.
+
+   A ptrlock has four states:
+   0/NULL Initial
+   1      Owned by me, I get to write a pointer to ptrlock.
+   2      Some thread is waiting on the ptrlock.
+   >2     Ptrlock contains a valid pointer.
+   It is not valid to gain the ptrlock and then write a NULL to it.  */
 
 #ifndef GOMP_PTRLOCK_H
 #define GOMP_PTRLOCK_H 1
@@ -39,20 +46,25 @@  static inline void gomp_ptrlock_init (go
 extern void *gomp_ptrlock_get_slow (gomp_ptrlock_t *ptrlock);
 static inline void *gomp_ptrlock_get (gomp_ptrlock_t *ptrlock)
 {
+  uintptr_t oldval;
+
   if ((uintptr_t) *ptrlock > 2)
     return *ptrlock;
 
-  if (__sync_bool_compare_and_swap (ptrlock, NULL, (uintptr_t) 1))
+  oldval = 0;
+  if (__atomic_compare_exchange_n (ptrlock, &oldval, 1, false,
+				   MEMMODEL_ACQUIRE, MEMMODEL_ACQUIRE))
     return NULL;
 
   return gomp_ptrlock_get_slow (ptrlock);
 }
 
-extern void gomp_ptrlock_set_slow (gomp_ptrlock_t *ptrlock, void *ptr);
+extern void gomp_ptrlock_set_slow (gomp_ptrlock_t *ptrlock);
 static inline void gomp_ptrlock_set (gomp_ptrlock_t *ptrlock, void *ptr)
 {
-  if (!__sync_bool_compare_and_swap (ptrlock, (uintptr_t) 1, ptr))
-    gomp_ptrlock_set_slow (ptrlock, ptr);
+  void *wait = __atomic_exchange_n (ptrlock, ptr, MEMMODEL_RELEASE);
+  if ((uintptr_t) wait != 1)
+    gomp_ptrlock_set_slow (ptrlock);
 }
 
 static inline void gomp_ptrlock_destroy (gomp_ptrlock_t *ptrlock)
Index: libgomp/config/linux/ptrlock.c
===================================================================
--- libgomp/config/linux/ptrlock.c	(revision 181830)
+++ libgomp/config/linux/ptrlock.c	(working copy)
@@ -1,4 +1,4 @@ 
-/* Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc.
    Contributed by Jakub Jelinek <jakub@redhat.com>.
 
    This file is part of the GNU OpenMP Library (libgomp).
@@ -34,7 +34,10 @@  void *
 gomp_ptrlock_get_slow (gomp_ptrlock_t *ptrlock)
 {
   int *intptr;
-  __sync_bool_compare_and_swap (ptrlock, 1, 2);
+  uintptr_t oldval = 1;
+
+  __atomic_compare_exchange_n (ptrlock, &oldval, 2, false,
+			       MEMMODEL_RELAXED, MEMMODEL_RELAXED);
 
   /* futex works on ints, not pointers.
      But a valid work share pointer will be at least
@@ -53,11 +56,10 @@  gomp_ptrlock_get_slow (gomp_ptrlock_t *p
 }
 
 void
-gomp_ptrlock_set_slow (gomp_ptrlock_t *ptrlock, void *ptr)
+gomp_ptrlock_set_slow (gomp_ptrlock_t *ptrlock)
 {
   int *intptr;
 
-  *ptrlock = ptr;
   __asm volatile ("" : "=r" (intptr) : "0" (ptrlock));
 #if __BYTE_ORDER == __BIG_ENDIAN
   if (sizeof (*ptrlock) > sizeof (int))
Index: libgomp/config/linux/alpha/futex.h
===================================================================
--- libgomp/config/linux/alpha/futex.h	(revision 181830)
+++ libgomp/config/linux/alpha/futex.h	(working copy)
@@ -101,9 +101,3 @@  cpu_relax (void)
 {
   __asm volatile ("" : : : "memory");
 }
-
-static inline void
-atomic_write_barrier (void)
-{
-  __asm volatile ("wmb" : : : "memory");
-}
Index: libgomp/config/linux/ia64/futex.h
===================================================================
--- libgomp/config/linux/ia64/futex.h	(revision 181830)
+++ libgomp/config/linux/ia64/futex.h	(working copy)
@@ -86,9 +86,3 @@  cpu_relax (void)
 {
   __asm volatile ("hint @pause" : : : "memory");
 }
-
-static inline void
-atomic_write_barrier (void)
-{
-  __sync_synchronize ();
-}
Index: libgomp/config/linux/mips/futex.h
===================================================================
--- libgomp/config/linux/mips/futex.h	(revision 181830)
+++ libgomp/config/linux/mips/futex.h	(working copy)
@@ -64,9 +64,3 @@  cpu_relax (void)
 {
   __asm volatile ("" : : : "memory");
 }
-
-static inline void
-atomic_write_barrier (void)
-{
-  __sync_synchronize ();
-}
Index: libgomp/config/linux/powerpc/futex.h
===================================================================
--- libgomp/config/linux/powerpc/futex.h	(revision 181830)
+++ libgomp/config/linux/powerpc/futex.h	(working copy)
@@ -84,9 +84,3 @@  cpu_relax (void)
 {
   __asm volatile ("" : : : "memory");
 }
-
-static inline void
-atomic_write_barrier (void)
-{
-  __asm volatile ("eieio" : : : "memory");
-}
Index: libgomp/config/linux/s390/futex.h
===================================================================
--- libgomp/config/linux/s390/futex.h	(revision 181830)
+++ libgomp/config/linux/s390/futex.h	(working copy)
@@ -76,9 +76,3 @@  cpu_relax (void)
 {
   __asm volatile ("" : : : "memory");
 }
-
-static inline void
-atomic_write_barrier (void)
-{
-  __sync_synchronize ();
-}
Index: libgomp/config/linux/sparc/futex.h
===================================================================
--- libgomp/config/linux/sparc/futex.h	(revision 181830)
+++ libgomp/config/linux/sparc/futex.h	(working copy)
@@ -96,13 +96,3 @@  cpu_relax (void)
   __asm volatile ("" : : : "memory");
 #endif
 }
-
-static inline void
-atomic_write_barrier (void)
-{
-#if defined __arch64__ || defined __sparc_v9__
-  __asm volatile ("membar #StoreStore" : : : "memory");
-#else
-  __sync_synchronize ();
-#endif
-}
Index: libgomp/config/linux/x86/futex.h
===================================================================
--- libgomp/config/linux/x86/futex.h	(revision 181830)
+++ libgomp/config/linux/x86/futex.h	(working copy)
@@ -145,9 +145,3 @@  cpu_relax (void)
 {
   __asm volatile ("rep; nop" : : : "memory");
 }
-
-static inline void
-atomic_write_barrier (void)
-{
-  __sync_synchronize ();
-}
Index: libgomp/config/linux/futex.h
===================================================================
--- libgomp/config/linux/futex.h	(revision 181830)
+++ libgomp/config/linux/futex.h	(working copy)
@@ -67,9 +67,3 @@  cpu_relax (void)
 {
   __asm volatile ("" : : : "memory");
 }
-
-static inline void
-atomic_write_barrier (void)
-{
-  __sync_synchronize ();
-}