]> granicus.if.org Git - libatomic_ops/commitdiff
Eliminate arithmetic shifts in double-CAS (gcc/arm, msftc/x86)
authorIvan Maidanski <ivmai@mail.ru>
Fri, 5 Oct 2012 11:10:40 +0000 (15:10 +0400)
committerIvan Maidanski <ivmai@mail.ru>
Fri, 5 Oct 2012 14:00:23 +0000 (18:00 +0400)
* src/atomic_ops/sysdeps/gcc/arm.h
(AO_compare_double_and_swap_double): Make double values by setting
their AO_val1/2 parts instead of using arithmetic shifts; replace
old/new_val with old/new_w.AO_whole.
* src/atomic_ops/sysdeps/msftc/x86.h
(AO_compare_double_and_swap_double_full): Likewise.
* src/atomic_ops/sysdeps/msftc/x86.h
(AO_double_compare_and_swap_full): Add comment.
* src/atomic_ops/sysdeps/msftc/x86.h (AO_double_compare_and_swap_full,
AO_compare_double_and_swap_double_full): Cast result of
_InterlockedCompareExchange64 to double_ptr_storage (to eliminate
signed/unsigned values comparison mismatch compiler warning).

src/atomic_ops/sysdeps/gcc/arm.h
src/atomic_ops/sysdeps/msftc/x86.h

index a7a947c99cbe8b21a51e570d256e802308185c46..29b6e44277d6009897a0420ccb5b6c7e6b32c427 100644 (file)
@@ -320,25 +320,27 @@ AO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val)
                                     AO_t old_val1, AO_t old_val2,
                                     AO_t new_val1, AO_t new_val2)
   {
-    double_ptr_storage old_val =
-                        ((double_ptr_storage)old_val2 << 32) | old_val1;
-    double_ptr_storage new_val =
-                        ((double_ptr_storage)new_val2 << 32) | new_val1;
+    AO_double_t old_w;
+    AO_double_t new_w;
     double_ptr_storage tmp;
     int result = 1;
 
+    old_w.AO_val1 = old_val1;
+    old_w.AO_val2 = old_val2;
+    new_w.AO_val1 = new_val1;
+    new_w.AO_val2 = new_val2;
     do {
       __asm__ __volatile__("@AO_compare_double_and_swap_double\n"
         "       ldrexd  %0, [%1]\n"     /* get original to r1 & r2 */
         : "=&r"(tmp)
         : "r"(addr)
         : "cc");
-      if (tmp != old_val)
+      if (tmp != old_w.AO_whole)
         break;
       __asm__ __volatile__(
         "       strexd  %0, %2, [%3]\n" /* store new one if matched */
         : "=&r"(result), "+m"(*addr)
-        : "r"(new_val), "r"(addr)
+        : "r"(new_w.AO_whole), "r"(addr)
         : "cc");
     } while (AO_EXPECT_FALSE(result));
     return !result;   /* if succeded, return 1 else 0 */
index 6919c68f1de39de637a6d6bd6777d0ca383a447d..2ee54c47485dd9b344810187e49ff340e8e71e97 100644 (file)
@@ -96,22 +96,31 @@ AO_test_and_set_full(volatile AO_TS_t *addr)
   AO_double_compare_and_swap_full(volatile AO_double_t *addr,
                                   AO_double_t old_val, AO_double_t new_val)
   {
-    return _InterlockedCompareExchange64((__int64 volatile *)addr,
-                new_val.AO_whole, old_val.AO_whole) == old_val.AO_whole;
+    return (double_ptr_storage)_InterlockedCompareExchange64(
+                                        (__int64 volatile *)addr,
+                                        new_val.AO_whole /* exchange */,
+                                        old_val.AO_whole) == old_val.AO_whole;
   }
 # define AO_HAVE_double_compare_and_swap_full
 
-AO_INLINE int
-AO_compare_double_and_swap_double_full(volatile AO_double_t *addr,
-                                       AO_t old_val1, AO_t old_val2,
-                                       AO_t new_val1, AO_t new_val2)
-{
-    __int64 oldv = (__int64)old_val1 | ((__int64)old_val2 << 32);
-    __int64 newv = (__int64)new_val1 | ((__int64)new_val2 << 32);
-    return _InterlockedCompareExchange64((__int64 volatile *)addr,
-                                       newv, oldv) == oldv;
-}
-#define AO_HAVE_compare_double_and_swap_double_full
+  AO_INLINE int
+  AO_compare_double_and_swap_double_full(volatile AO_double_t *addr,
+                                         AO_t old_val1, AO_t old_val2,
+                                         AO_t new_val1, AO_t new_val2)
+  {
+    AO_double_t old_w;
+    AO_double_t new_w;
+
+    old_w.AO_val1 = old_val1;
+    old_w.AO_val2 = old_val2;
+    new_w.AO_val1 = new_val1;
+    new_w.AO_val2 = new_val2;
+    return (double_ptr_storage)_InterlockedCompareExchange64(
+                                        (__int64 volatile *)addr,
+                                        new_w.AO_whole,
+                                        old_w.AO_whole) == old_w.AO_whole;
+  }
+# define AO_HAVE_compare_double_and_swap_double_full
 
 #endif /* AO_ASSUME_VISTA */