}
#define AO_HAVE_test_and_set
-AO_INLINE int
-AO_compare_and_swap(volatile AO_t *addr, AO_t old, AO_t new_val)
+#ifndef AO_GENERALIZE_ASM_BOOL_CAS
+ AO_INLINE int
+ AO_compare_and_swap(volatile AO_t *addr, AO_t old, AO_t new_val)
+ {
+ AO_t __oldval;
+ int result = 0;
+ __asm__ __volatile__(
+ "1:\n"
+ " %0 = memw_locked(%3);\n" /* load and reserve */
+ " {\n"
+ " p2 = cmp.eq(%0,%4);\n" /* if load is not equal to */
+ " if (!p2.new) jump:nt 2f; \n" /* old, fail */
+ " }\n"
+ " memw_locked(%3,p1) = %5;\n" /* else store conditional */
+ " if (!p1) jump 1b;\n" /* retry if lost reservation */
+ " %1 = #1\n" /* success, result = 1 */
+ "2:\n"
+ : "=&r" (__oldval), "+r" (result), "+m"(*addr)
+ : "r" (addr), "r" (old), "r" (new_val)
+ : "p1", "p2", "memory"
+ );
+ return result;
+ }
+# define AO_HAVE_compare_and_swap
+#endif /* !AO_GENERALIZE_ASM_BOOL_CAS */
+
+AO_INLINE AO_t
+AO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val)
{
AO_t __oldval;
- int result = 0;
+
__asm__ __volatile__(
"1:\n"
- " %0 = memw_locked(%3);\n" /* load and reserve */
+ " %0 = memw_locked(%2);\n" /* load and reserve */
" {\n"
- " p2 = cmp.eq(%0,%4);\n" /* if load is not equal to */
- " if (!p2.new) jump:nt 2f; \n" /* old, fail */
+ " p2 = cmp.eq(%0,%3);\n" /* if load is not equal to */
+ " if (!p2.new) jump:nt 2f; \n" /* old_val, fail */
" }\n"
- " memw_locked(%3,p1) = %5;\n" /* else store conditional */
+ " memw_locked(%2,p1) = %4;\n" /* else store conditional */
" if (!p1) jump 1b;\n" /* retry if lost reservation */
- " %1 = #1\n" /* success, result = 1 */
"2:\n"
- : "=&r" (__oldval), "+r" (result), "+m"(*addr)
- : "r" (addr), "r" (old), "r" (new_val)
+ : "=&r" (__oldval), "+m"(*addr)
+ : "r" (addr), "r" (old_val), "r" (new_val)
: "p1", "p2", "memory"
);
- return result;
+ return __oldval;
}
-#define AO_HAVE_compare_and_swap
+#define AO_HAVE_fetch_compare_and_swap
- #include "../ao_t_is_int.h"
+ #define AO_T_IS_INT
}
#define AO_HAVE_compare_and_swap
- /* FIXME: I think the implementations below should be automatically */
- /* generated if we omit them. - HB */
-
- AO_INLINE int
- AO_compare_and_swap_acquire(volatile AO_t *addr, AO_t old, AO_t new_val) {
- int result = AO_compare_and_swap(addr, old, new_val);
- AO_nop_full();
- return result;
- }
- #define AO_HAVE_compare_and_swap_acquire
-
- AO_INLINE int
- AO_compare_and_swap_release(volatile AO_t *addr, AO_t old, AO_t new_val) {
- AO_nop_full();
- return AO_compare_and_swap(addr, old, new_val);
- }
- #define AO_HAVE_compare_and_swap_release
-
- AO_INLINE int
- AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) {
- int result;
- AO_nop_full();
- result = AO_compare_and_swap(addr, old, new_val);
- AO_nop_full();
- return result;
- }
- #define AO_HAVE_compare_and_swap_full
+ /* CAS primitives with acquire, release and full semantics are */
+ /* generated automatically (and AO_int_... primitives are */
+ /* defined properly after the first generalization pass). */
-/*
- * FIXME: We should also implement fetch_and_add and or primitives
- * directly.
- */
+/* FIXME: implement AO_fetch_compare_and_swap */
+
+/* FIXME: We should also implement AO_fetch_and_add, AO_and, AO_or, */
+/* AO_xor primitives directly. */
- #include "../ao_t_is_int.h"
+ #define AO_T_IS_INT
}
#define AO_HAVE_fetch_and_sub1_release
-AO_INLINE int
-AO_compare_and_swap_acquire(volatile AO_t *addr,
- AO_t old, AO_t new_val)
+AO_INLINE AO_t
+AO_fetch_compare_and_swap_acquire(volatile AO_t *addr, AO_t old_val,
+ AO_t new_val)
{
- AO_t oldval;
-
- _Asm_mov_to_ar(_AREG_CCV, old, _DOWN_MEM_FENCE);
- oldval = _Asm_cmpxchg(AO_T_SIZE, _SEM_ACQ, addr,
- new_val, _LDHINT_NONE, _DOWN_MEM_FENCE);
- return (oldval == old);
+ _Asm_mov_to_ar(_AREG_CCV, old_val, _DOWN_MEM_FENCE);
+ return _Asm_cmpxchg(AO_T_SIZE, _SEM_ACQ, addr,
+ new_val, _LDHINT_NONE, _DOWN_MEM_FENCE);
}
-#define AO_HAVE_compare_and_swap_acquire
+#define AO_HAVE_fetch_compare_and_swap_acquire
-AO_INLINE int
-AO_compare_and_swap_release(volatile AO_t *addr,
- AO_t old, AO_t new_val)
+AO_INLINE AO_t
+AO_fetch_compare_and_swap_release(volatile AO_t *addr, AO_t old_val,
+ AO_t new_val)
{
- AO_t oldval;
- _Asm_mov_to_ar(_AREG_CCV, old, _UP_MEM_FENCE);
- oldval = _Asm_cmpxchg(AO_T_SIZE, _SEM_REL, addr,
- new_val, _LDHINT_NONE, _UP_MEM_FENCE);
- /* Hopefully the compiler knows not to reorder the above two? */
- return (oldval == old);
+ _Asm_mov_to_ar(_AREG_CCV, old_val, _UP_MEM_FENCE);
+ return _Asm_cmpxchg(AO_T_SIZE, _SEM_REL, addr,
+ new_val, _LDHINT_NONE, _UP_MEM_FENCE);
+
}
-#define AO_HAVE_compare_and_swap_release
+#define AO_HAVE_fetch_compare_and_swap_release
-AO_INLINE int
-AO_char_compare_and_swap_acquire(volatile unsigned char *addr,
- unsigned char old, unsigned char new_val)
+AO_INLINE unsigned char
+AO_char_fetch_compare_and_swap_acquire(volatile unsigned char *addr,
+ unsigned char old_val, unsigned char new_val)
{
- unsigned char oldval;
+ _Asm_mov_to_ar(_AREG_CCV, old_val, _DOWN_MEM_FENCE);
+ return _Asm_cmpxchg(_SZ_B, _SEM_ACQ, addr,
+ new_val, _LDHINT_NONE, _DOWN_MEM_FENCE);
- _Asm_mov_to_ar(_AREG_CCV, old, _DOWN_MEM_FENCE);
- oldval = _Asm_cmpxchg(_SZ_B, _SEM_ACQ, addr,
- new_val, _LDHINT_NONE, _DOWN_MEM_FENCE);
- return (oldval == old);
}
-#define AO_HAVE_char_compare_and_swap_acquire
+#define AO_HAVE_char_fetch_compare_and_swap_acquire
-AO_INLINE int
-AO_char_compare_and_swap_release(volatile unsigned char *addr,
- unsigned char old, unsigned char new_val)
+AO_INLINE unsigned char
+AO_char_fetch_compare_and_swap_release(volatile unsigned char *addr,
+ unsigned char old_val, unsigned char new_val)
{
- unsigned char oldval;
- _Asm_mov_to_ar(_AREG_CCV, old, _UP_MEM_FENCE);
- oldval = _Asm_cmpxchg(_SZ_B, _SEM_REL, addr,
- new_val, _LDHINT_NONE, _UP_MEM_FENCE);
- /* Hopefully the compiler knows not to reorder the above two? */
- return (oldval == old);
+ _Asm_mov_to_ar(_AREG_CCV, old_val, _UP_MEM_FENCE);
+ return _Asm_cmpxchg(_SZ_B, _SEM_REL, addr,
+ new_val, _LDHINT_NONE, _UP_MEM_FENCE);
+
}
-#define AO_HAVE_char_compare_and_swap_release
+#define AO_HAVE_char_fetch_compare_and_swap_release
-AO_INLINE int
-AO_short_compare_and_swap_acquire(volatile unsigned short *addr,
- unsigned short old, unsigned short new_val)
+AO_INLINE unsigned short
+AO_short_fetch_compare_and_swap_acquire(volatile unsigned short *addr,
+ unsigned short old_val,
+ unsigned short new_val)
{
- unsigned short oldval;
+ _Asm_mov_to_ar(_AREG_CCV, old_val, _DOWN_MEM_FENCE);
+ return _Asm_cmpxchg(_SZ_B, _SEM_ACQ, addr,
+ new_val, _LDHINT_NONE, _DOWN_MEM_FENCE);
- _Asm_mov_to_ar(_AREG_CCV, old, _DOWN_MEM_FENCE);
- oldval = _Asm_cmpxchg(_SZ_B, _SEM_ACQ, addr,
- new_val, _LDHINT_NONE, _DOWN_MEM_FENCE);
- return (oldval == old);
}
-#define AO_HAVE_short_compare_and_swap_acquire
+#define AO_HAVE_short_fetch_compare_and_swap_acquire
-AO_INLINE int
-AO_short_compare_and_swap_release(volatile unsigned short *addr,
- unsigned short old, unsigned short new_val)
+AO_INLINE unsigned short
+AO_short_fetch_compare_and_swap_release(volatile unsigned short *addr,
+ unsigned short old_val,
+ unsigned short new_val)
{
- unsigned short oldval;
- _Asm_mov_to_ar(_AREG_CCV, old, _UP_MEM_FENCE);
- oldval = _Asm_cmpxchg(_SZ_B, _SEM_REL, addr,
- new_val, _LDHINT_NONE, _UP_MEM_FENCE);
- /* Hopefully the compiler knows not to reorder the above two? */
- return (oldval == old);
+ _Asm_mov_to_ar(_AREG_CCV, old_val, _UP_MEM_FENCE);
+ return _Asm_cmpxchg(_SZ_B, _SEM_REL, addr,
+ new_val, _LDHINT_NONE, _UP_MEM_FENCE);
+
}
-#define AO_HAVE_short_compare_and_swap_release
+#define AO_HAVE_short_fetch_compare_and_swap_release
#ifndef __LP64__
- # include "../ao_t_is_int.h"
+ # define AO_T_IS_INT
#endif