linux-atomic.c (__sync_lock_release_4): New.
authorJohn David Anglin <danglin@gcc.gnu.org>
Thu, 17 Jul 2014 23:18:50 +0000 (23:18 +0000)
committerJohn David Anglin <danglin@gcc.gnu.org>
Thu, 17 Jul 2014 23:18:50 +0000 (23:18 +0000)
* config/pa/linux-atomic.c (__sync_lock_release_4): New.
(SYNC_LOCK_RELEASE): Update to use __kernel_cmpxchg for release.
Don't use SYNC_LOCK_RELEASE for int type.

From-SVN: r212767

libgcc/ChangeLog
libgcc/config/pa/linux-atomic.c

index 2efd331..b659f80 100644 (file)
@@ -1,3 +1,9 @@
+2014-07-17  John David Anglin  <danglin@gcc.gnu.org>
+
+       * config/pa/linux-atomic.c (__sync_lock_release_4): New.
+       (SYNC_LOCK_RELEASE): Update to use __kernel_cmpxchg for release.
+       Don't use SYNC_LOCK_RELEASE for int type.
+
 2014-07-14  Richard Biener  <rguenther@suse.de>
 
        * libgcov.h (struct gcov_fn_info): Make ctrs size 1.
index d92d6ef..e70d7d7 100644 (file)
@@ -293,13 +293,34 @@ __sync_lock_test_and_set_4 (int *ptr, int val)
 SUBWORD_TEST_AND_SET (unsigned short, 2)
 SUBWORD_TEST_AND_SET (unsigned char,  1)
 
+void HIDDEN
+__sync_lock_release_4 (int *ptr)
+{
+  int failure, oldval;
+
+  do {
+    oldval = *ptr;
+    failure = __kernel_cmpxchg (oldval, 0, ptr);
+  } while (failure != 0);
+}
+
 #define SYNC_LOCK_RELEASE(TYPE, WIDTH)                                 \
   void HIDDEN                                                          \
   __sync_lock_release_##WIDTH (TYPE *ptr)                              \
   {                                                                    \
-    *ptr = 0;                                                          \
+    int failure;                                                       \
+    unsigned int oldval, newval, shift, mask;                          \
+    int *wordptr = (int *) ((unsigned long) ptr & ~3);                 \
+                                                                       \
+    shift = (((unsigned long) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH;    \
+    mask = MASK_##WIDTH << shift;                                      \
+                                                                       \
+    do {                                                               \
+      oldval = *wordptr;                                               \
+      newval = oldval & ~mask;                                         \
+      failure = __kernel_cmpxchg (oldval, newval, wordptr);            \
+    } while (failure != 0);                                            \
   }
 
-SYNC_LOCK_RELEASE (int,   4)
 SYNC_LOCK_RELEASE (short, 2)
 SYNC_LOCK_RELEASE (char,  1)