]> granicus.if.org Git - libatomic_ops/commitdiff
Add non-generalized double-CAS-full implementation for AArch64
authorIvan Maidanski <ivmai@mail.ru>
Sun, 26 May 2013 13:08:27 +0000 (17:08 +0400)
committerIvan Maidanski <ivmai@mail.ru>
Sun, 26 May 2013 13:08:27 +0000 (17:08 +0400)
* src/atomic_ops/sysdeps/gcc/aarch64.h
(AO_double_compare_and_swap_full): New function.

src/atomic_ops/sysdeps/gcc/aarch64.h

index 6ae26f367a60a121f10eb4515fb671db19fe4a17..54e6d7f6d50ed64a5ae69c6128b3f4e02209723a 100644 (file)
     return !result;
   }
 # define AO_HAVE_double_compare_and_swap_release
-#endif
+
+  AO_INLINE int
+  AO_double_compare_and_swap_full(volatile AO_double_t *addr,
+                                  AO_double_t old_val, AO_double_t new_val)
+  {
+    AO_double_t tmp;
+    int result = 1;
+
+    do {
+      __asm__ __volatile__("//AO_double_compare_and_swap_full\n"
+        "       ldaxp  %0, %1, %2\n"
+        : "=&r" (tmp.AO_val1), "=&r" (tmp.AO_val2)
+        : "Q" (*addr));
+      if (tmp.AO_val1 != old_val.AO_val1 || tmp.AO_val2 != old_val.AO_val2)
+        break;
+      __asm__ __volatile__(
+        "       stlxp %w0, %2, %3, %1\n"
+        : "=&r" (result), "=Q" (*addr)
+        : "r" (new_val.AO_val1), "r" (new_val.AO_val2));
+    } while (AO_EXPECT_FALSE(result));
+    return !result;
+  }
+# define AO_HAVE_double_compare_and_swap_full
+#endif /* __GNUC__ == 4 */
 
 #include "generic.h"