This is the mail archive of the libc-hacker@sourceware.cygnus.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


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

Re: Patch: HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS


On Mon, Jun 19, 2000 at 11:07:51AM -0700, Geoff Keating wrote:
> 
> Great!  I've been wondering which semantic compare_and_swap had for
> ages.  Could you please clean this up and put it into the code, so
> that future programmers don't have to e-mail you too?
> 

Here it is.

> At present, the ppc compare_and_swap is conservative and ensures that
> it completes after previous writes but before subsequent writes.
> 

You may optimize ppc with HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS 
now :-).


-- 
H.J. Lu (hjl@gnu.org)
---
2000-06-19  H.J. Lu  <hjl@gnu.org>

	* spinlock.h (HAS_COMPARE_AND_SWAP): Defined if
	HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS is defined.
	(compare_and_swap_with_release_semantics): New. Default to
	compare_and_swap if HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
	is not defined.

	* spinlock.c (__pthread_unlock): Call
	compare_and_swap_with_release_semantics () instead of
	compare_and_swap ().

Index: spinlock.c
===================================================================
RCS file: /work/cvs/gnu/glibc/linuxthreads/spinlock.c,v
retrieving revision 1.1.1.2
diff -u -p -r1.1.1.2 spinlock.c
--- spinlock.c	2000/06/09 18:40:09	1.1.1.2
+++ spinlock.c	2000/06/19 16:49:27
@@ -95,7 +95,9 @@ again:
     /* No threads are waiting for this lock.  Please note that we also
        enter this case if the lock is not taken at all.  If this wouldn't
        be done here we would crash further down.  */
-    if (! compare_and_swap(&lock->__status, oldstatus, 0, &lock->__spinlock))
+    if (! compare_and_swap_with_release_semantics (&lock->__status,
+						   oldstatus, 0,
+						   &lock->__spinlock))
       goto again;
     return 0;
   }
@@ -126,9 +128,9 @@ again:
     /* If max prio thread is at head, remove it with compare-and-swap
        to guard against concurrent lock operation */
     thr = (pthread_descr) oldstatus;
-    if (! compare_and_swap(&lock->__status,
-                           oldstatus, (long)(thr->p_nextlock),
-                           &lock->__spinlock))
+    if (! compare_and_swap_with_release_semantics
+	    (&lock->__status, oldstatus, (long)(thr->p_nextlock),
+	     &lock->__spinlock))
       goto again;
   } else {
     /* No risk of concurrent access, remove max prio thread normally */
Index: spinlock.h
===================================================================
RCS file: /work/cvs/gnu/glibc/linuxthreads/spinlock.h,v
retrieving revision 1.1.1.2
diff -u -p -r1.1.1.2 spinlock.h
--- spinlock.h	2000/06/09 18:40:09	1.1.1.2
+++ spinlock.h	2000/06/19 18:20:20
@@ -12,6 +12,25 @@
 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        */
 /* GNU Library General Public License for more details.                 */
 
+
+/* There are 2 compare and swap synchronization primitives with
+   different semantics:
+
+	1. compare_and_swap, which has acquire semantics (i.e. it
+	completes befor subsequent writes.)
+	2. compare_and_swap_with_release_semantics, which has release
+	semantics (it completes after previous writes.)
+
+   For those platforms on which they are the same. HAS_COMPARE_AND_SWAP
+   should be defined. For those platforms on which they are different, 
+   HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS has to be defined.  */
+
+#ifndef HAS_COMPARE_AND_SWAP
+#ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
+#define HAS_COMPARE_AND_SWAP
+#endif
+#endif
+
 #if defined(TEST_FOR_COMPARE_AND_SWAP)
 
 extern int __pthread_has_cas;
@@ -29,6 +48,18 @@ static inline int compare_and_swap(long 
 
 #elif defined(HAS_COMPARE_AND_SWAP)
 
+#ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
+
+static inline int
+compare_and_swap_with_release_semantics (long * ptr, long oldval,
+					 long newval, int * spinlock)
+{
+  return __compare_and_swap_with_release_semantics (ptr, oldval,
+						    newval);
+}
+
+#endif
+
 static inline int compare_and_swap(long * ptr, long oldval, long newval,
                                    int * spinlock)
 {
@@ -46,6 +77,10 @@ static inline int compare_and_swap(long 
   return __pthread_compare_and_swap(ptr, oldval, newval, spinlock);
 }
 
+#endif
+
+#ifndef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
+#define compare_and_swap_with_release_semantics compare_and_swap
 #endif
 
 /* Internal locks */

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