diff options
| author | Ivan Maidanski <ivmai@mail.ru> | 2011-12-14 11:13:46 +0400 |
|---|---|---|
| committer | Ivan Maidanski <ivmai@mail.ru> | 2011-12-14 11:13:46 +0400 |
| commit | 40d54b7fb87595e89269cec9643f8fa54094bf7a (patch) | |
| tree | 0fe5a0ebe33c0dbfffc1890280c0a1b96e8f85e9 | |
| parent | dc5861613cef2cc1f23bc115864b5cf98d2241a4 (diff) | |
| parent | d8cd00a386ceeac4c726a153833605fd6db08c26 (diff) | |
| download | libatomic_ops-40d54b7fb87595e89269cec9643f8fa54094bf7a.tar.gz | |
Merge branch 'ao_val_cas'
| -rw-r--r-- | ChangeLog | 1 | ||||
| -rw-r--r-- | src/atomic_ops/sysdeps/gcc/mips.h | 138 |
2 files changed, 115 insertions, 24 deletions
@@ -13,6 +13,7 @@ * Eliminate compiler warnings in various functions and macros. * Generalize AO_compare_and_swap primitives via AO_fetch_compare_and_swap. * Generalize acquire/release/full CAS primitives for MIPS +* Implement fetch_and_add, test_and_set primitives for MIPS. * Improve Makefile for MS VC++; pass '-W3' option to MS compiler. * Include ao_t_is_int.h from atomic_ops.h after first generalization pass * Merge all Makefile.am files in src tree. diff --git a/src/atomic_ops/sysdeps/gcc/mips.h b/src/atomic_ops/sysdeps/gcc/mips.h index 1e1ad97..525a54a 100644 --- a/src/atomic_ops/sysdeps/gcc/mips.h +++ b/src/atomic_ops/sysdeps/gcc/mips.h @@ -26,6 +26,16 @@ /* Data dependence does not imply read ordering. */ #define AO_NO_DD_ORDERING +#ifdef AO_ICE9A1_LLSC_WAR + /* ICE9 rev A1 chip (used in very few systems) is reported to */ + /* have a low-frequency bug that causes LL to fail. */ + /* To workaround, just issue the second 'LL'. */ +# define AO_MIPS_LL_FIX(args_str) \ + " ll " args_str "\n" +#else +# define AO_MIPS_LL_FIX(args_str) "" +#endif + AO_INLINE void AO_nop_full(void) { @@ -40,39 +50,119 @@ AO_nop_full(void) } #define AO_HAVE_nop_full -AO_INLINE int -AO_compare_and_swap(volatile AO_t *addr, AO_t old, AO_t new_val) +#ifndef AO_PREFER_GENERALIZED +AO_INLINE AO_t +AO_fetch_and_add(volatile AO_t *addr, AO_t incr) { - register int was_equal = 0; + register int result; register int temp; __asm__ __volatile__( - " .set push \n" - " .set mips2 \n" - " .set noreorder \n" - " .set nomacro \n" - "1: ll %0, %1 \n" - " bne %0, %4, 2f \n" - " move %0, %3 \n" - " sc %0, %1 \n" - " .set pop \n" - " beqz %0, 1b \n" - " li %2, 1 \n" - "2: " - : "=&r" (temp), "+R" (*addr), "+r" (was_equal) - : "r" (new_val), "r" (old) + + " .set push\n" + " .set mips2\n" + " .set noreorder\n" + " .set nomacro\n" + "1: ll %0, %2\n" + AO_MIPS_LL_FIX("%0, %2") + " addu %1, %0, %3\n" + " sc %1, %2\n" + " beqz %1, 1b\n" + " nop\n" + " .set pop " + : "=&r" (result), "=&r" (temp), "=m" (*addr) + : "Ir" (incr) + : "memory"); + return (AO_t)result; +} +#define AO_HAVE_fetch_and_add + +AO_INLINE AO_TS_VAL_t +AO_test_and_set(volatile AO_TS_t *addr) +{ + register int oldval; + register int temp; + + __asm__ __volatile__( + " .set push\n" + " .set mips2\n" + " .set noreorder\n" + " .set nomacro\n" + "1: ll %0, %2\n" + AO_MIPS_LL_FIX("%0, %2") + " move %1, %3\n" + " sc %1, %2\n" + " beqz %1, 1b\n" + " nop\n" + " .set pop " + : "=&r" (oldval), "=&r" (temp), "=m" (*addr) + : "r" (1) : "memory"); - return was_equal; + return (AO_TS_VAL_t)oldval; } -#define AO_HAVE_compare_and_swap +#define AO_HAVE_test_and_set + + /* FIXME: Implement AO_and/or/xor primitives directly. */ +#endif /* !AO_PREFER_GENERALIZED */ + +#ifndef AO_GENERALIZE_ASM_BOOL_CAS + AO_INLINE int + AO_compare_and_swap(volatile AO_t *addr, AO_t old, AO_t new_val) + { + register int was_equal = 0; + register int temp; + + __asm__ __volatile__( + " .set push \n" + " .set mips2 \n" + " .set noreorder \n" + " .set nomacro \n" + "1: ll %0, %1 \n" + AO_MIPS_LL_FIX("%0, %1") + " bne %0, %4, 2f \n" + " move %0, %3 \n" + " sc %0, %1 \n" + " .set pop \n" + " beqz %0, 1b \n" + " li %2, 1 \n" + "2: " + : "=&r" (temp), "+R" (*addr), "+r" (was_equal) + : "r" (new_val), "r" (old) + : "memory"); + return was_equal; + } +# 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, AO_t new_val) +{ + register int fetched_val; + register int temp; + + __asm__ __volatile__( + " .set push\n" + " .set mips2\n" + " .set noreorder\n" + " .set nomacro\n" + "1: ll %0, %2\n" + AO_MIPS_LL_FIX("%0, %2") + " bne %0, %4, 2f\n" + " move %1, %3\n" + " sc %1, %2\n" + " beqz %1, 1b\n" + " nop\n" + " .set pop\n" + "2:" + : "=&r" (fetched_val), "=&r" (temp), "=m" (*addr) + : "r" (new_val), "Jr" (old) + : "memory"); + return (AO_t)fetched_val; +} +#define AO_HAVE_fetch_compare_and_swap /* CAS primitives with acquire, release and full semantics are */ /* generated automatically (and AO_int_... primitives are */ /* defined properly after the first generalization pass). */ -/* FIXME: implement AO_fetch_compare_and_swap */ - -/* FIXME: We should also implement AO_fetch_and_add, AO_and, AO_or, */ -/* AO_xor primitives directly. */ - #define AO_T_IS_INT |
