From 18ded03a82b187128679c2b8d87892903201c3a5 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Fri, 21 Oct 2011 12:23:03 +0400 Subject: [PATCH] Add FIXMEs to add AO_fetch_compare_and_swap primitives --- ChangeLog | 1 + TODO | 2 -- doc/README.txt | 3 +++ src/atomic_ops.c | 3 +++ src/atomic_ops.h | 11 +++++++++-- src/atomic_ops/generalize.h | 2 ++ src/atomic_ops/sysdeps/ao_t_is_int.h | 2 ++ src/atomic_ops/sysdeps/armcc/arm_v6.h | 2 ++ src/atomic_ops/sysdeps/emul_cas.h | 2 ++ src/atomic_ops/sysdeps/gcc/alpha.h | 2 ++ src/atomic_ops/sysdeps/gcc/arm.h | 2 ++ src/atomic_ops/sysdeps/gcc/avr32.h | 2 ++ src/atomic_ops/sysdeps/gcc/hexagon.h | 2 ++ src/atomic_ops/sysdeps/gcc/ia64.h | 2 ++ src/atomic_ops/sysdeps/gcc/m68k.h | 2 ++ src/atomic_ops/sysdeps/gcc/mips.h | 2 ++ src/atomic_ops/sysdeps/gcc/powerpc.h | 2 ++ src/atomic_ops/sysdeps/gcc/s390.h | 2 ++ src/atomic_ops/sysdeps/gcc/sparc.h | 2 ++ src/atomic_ops/sysdeps/gcc/x86.h | 2 ++ src/atomic_ops/sysdeps/gcc/x86_64.h | 2 ++ src/atomic_ops/sysdeps/generic_pthread.h | 2 ++ src/atomic_ops/sysdeps/hpc/ia64.h | 2 ++ src/atomic_ops/sysdeps/ibmc/powerpc.h | 4 ++-- src/atomic_ops/sysdeps/icc/ia64.h | 2 ++ src/atomic_ops/sysdeps/msftc/common32_defs.h | 2 ++ src/atomic_ops/sysdeps/msftc/x86_64.h | 2 ++ src/atomic_ops/sysdeps/sunc/x86.h | 2 ++ src/atomic_ops/sysdeps/sunc/x86_64.h | 2 ++ tests/list_atomic.template | 1 + tests/test_atomic_include.template | 1 + 31 files changed, 66 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 60d6ab2..770ae4e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ * Add '-no-undefined' to LDFLAGS in src/Makefile.am. * Add AO_and, AO_xor atomic operations. +* Add AO_fetch_compare_and_swap primitives. * Add and fill in AUTHORS, TODO files. * Add atomic_ops.pc.in and atomic_ops-uninstalled.pc.in to pkgconfig folder. * Adjust AO_..._H macros in public headers. diff --git a/TODO b/TODO index 58114c5..d245225 100644 --- a/TODO +++ b/TODO @@ -1,8 +1,6 @@ TODO tasks ========== -Add equivalent of __sync_val_compare_and_swap. Add tests. - Add C++0x ATM (atomic memory operations) layer. diff --git a/doc/README.txt b/doc/README.txt index 26a4f7f..348247d 100644 --- a/doc/README.txt +++ b/doc/README.txt @@ -100,6 +100,9 @@ int compare_and_swap(volatile AO_t * addr, AO_t old_val, AO_t new_val) Atomically compare *addr to old_val, and replace *addr by new_val if the first comparison succeeds. Returns nonzero if the comparison succeeded and *addr was updated. +AO_t fetch_compare_and_swap(volatile AO_t * addr, AO_t old_val, AO_t new_val) + Atomically compare *addr to old_val, and replace *addr by new_val + if the first comparison succeeds; returns the original value of *addr. AO_TS_VAL_t test_and_set(volatile AO_TS_t * addr) Atomically read the binary value at *addr, and set it. AO_TS_VAL_t is an enumeration type which includes two values AO_TS_SET and diff --git a/src/atomic_ops.c b/src/atomic_ops.c index 3b86371..bd77bba 100644 --- a/src/atomic_ops.c +++ b/src/atomic_ops.c @@ -195,6 +195,7 @@ int AO_compare_and_swap_emulation(volatile AO_t *addr, AO_t old, sigset_t old_sigs; block_all_signals(&old_sigs); # endif + lock(my_lock); if (*addr == old) { @@ -210,6 +211,8 @@ int AO_compare_and_swap_emulation(volatile AO_t *addr, AO_t old, return result; } +/* FIXME: implement AO_fetch_compare_and_swap */ + int AO_compare_double_and_swap_double_emulation(volatile AO_double_t *addr, AO_t old_val1, AO_t old_val2, AO_t new_val1, AO_t new_val2) diff --git a/src/atomic_ops.h b/src/atomic_ops.h index 334dba0..ca3a21a 100644 --- a/src/atomic_ops.h +++ b/src/atomic_ops.h @@ -77,6 +77,7 @@ /* AO_or */ /* AO_xor */ /* AO_compare_and_swap */ +/* AO_fetch_compare_and_swap */ /* */ /* Note that atomicity guarantees are valid only if both */ /* readers and writers use AO_ operations to access the */ @@ -90,9 +91,14 @@ /* or can only be read concurrently, then x can be accessed */ /* via ordinary references and assignments. */ /* */ -/* Compare_and_exchange takes an address and an expected old */ -/* value and a new value, and returns an int. Nonzero */ +/* AO_compare_and_swap takes an address and an expected old */ +/* value and a new value, and returns an int. Non-zero result */ /* indicates that it succeeded. */ +/* AO_fetch_compare_and_swap takes an address and an expected */ +/* old value and a new value, and returns the real old value. */ +/* The operation succeeded if and only if the expected old */ +/* value matches the old value returned. */ +/* */ /* Test_and_set takes an address, atomically replaces it by */ /* AO_TS_SET, and returns the prior value. */ /* An AO_TS_t location can be reset with the */ @@ -350,6 +356,7 @@ # else # error Cannot implement AO_compare_and_swap_full on this architecture. # endif +/* FIXME: same for AO_fetch_compare_and_swap */ #endif /* AO_REQUIRE_CAS && !AO_HAVE_compare_and_swap ... */ /* The most common way to clear a test-and-set location */ diff --git a/src/atomic_ops/generalize.h b/src/atomic_ops/generalize.h index 91a96fe..2131685 100644 --- a/src/atomic_ops/generalize.h +++ b/src/atomic_ops/generalize.h @@ -1053,6 +1053,8 @@ # endif #endif /* AO_HAVE_compare_and_swap_full */ +/* FIXME: implement AO_fetch_compare_and_swap */ + #if !defined(AO_HAVE_compare_and_swap) \ && defined(AO_HAVE_compare_and_swap_release) # define AO_compare_and_swap(addr,old,new_val) \ diff --git a/src/atomic_ops/sysdeps/ao_t_is_int.h b/src/atomic_ops/sysdeps/ao_t_is_int.h index 3b6f165..33d3e4d 100644 --- a/src/atomic_ops/sysdeps/ao_t_is_int.h +++ b/src/atomic_ops/sysdeps/ao_t_is_int.h @@ -72,6 +72,8 @@ # define AO_HAVE_int_compare_and_swap #endif +/* FIXME: implement AO_fetch_compare_and_swap */ + /* AO_load */ #if defined(AO_HAVE_load_acquire) \ && !defined(AO_HAVE_int_load_acquire) diff --git a/src/atomic_ops/sysdeps/armcc/arm_v6.h b/src/atomic_ops/sysdeps/armcc/arm_v6.h index 7b43151..16e7f1a 100644 --- a/src/atomic_ops/sysdeps/armcc/arm_v6.h +++ b/src/atomic_ops/sysdeps/armcc/arm_v6.h @@ -198,6 +198,8 @@ __asm__ { } #define AO_HAVE_compare_and_swap +/* FIXME: implement AO_fetch_compare_and_swap */ + /* helper functions for the Realview compiler: LDREXD is not usable * with inline assembler, so use the "embedded" assembler as * suggested by ARM Dev. support (June 2008). */ diff --git a/src/atomic_ops/sysdeps/emul_cas.h b/src/atomic_ops/sysdeps/emul_cas.h index 1aa34d9..fa93141 100644 --- a/src/atomic_ops/sysdeps/emul_cas.h +++ b/src/atomic_ops/sysdeps/emul_cas.h @@ -64,6 +64,8 @@ void AO_store_full_emulation(volatile AO_t *addr, AO_t val); # define AO_HAVE_compare_double_and_swap_double_full #endif +/* FIXME: implement AO_fetch_compare_and_swap */ + #undef AO_store #undef AO_HAVE_store #undef AO_store_write diff --git a/src/atomic_ops/sysdeps/gcc/alpha.h b/src/atomic_ops/sysdeps/gcc/alpha.h index 61d0433..016e4d1 100644 --- a/src/atomic_ops/sysdeps/gcc/alpha.h +++ b/src/atomic_ops/sysdeps/gcc/alpha.h @@ -61,3 +61,5 @@ AO_compare_and_swap(volatile AO_t *addr, return (int)was_equal; } #define AO_HAVE_compare_and_swap + +/* FIXME: implement AO_fetch_compare_and_swap */ diff --git a/src/atomic_ops/sysdeps/gcc/arm.h b/src/atomic_ops/sysdeps/gcc/arm.h index 3e5fd02..5a53d4e 100644 --- a/src/atomic_ops/sysdeps/gcc/arm.h +++ b/src/atomic_ops/sysdeps/gcc/arm.h @@ -265,6 +265,8 @@ AO_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val) } #define AO_HAVE_compare_and_swap +/* FIXME: implement AO_fetch_compare_and_swap */ + #if !defined(__ARM_ARCH_6__) && !defined(__ARM_ARCH_6J__) \ && !defined(__ARM_ARCH_6T2__) && !defined(__ARM_ARCH_6Z__) \ && !defined(__ARM_ARCH_6ZT2__) && (!defined(__thumb__) \ diff --git a/src/atomic_ops/sysdeps/gcc/avr32.h b/src/atomic_ops/sysdeps/gcc/avr32.h index 7a2fbed..c1bf56c 100644 --- a/src/atomic_ops/sysdeps/gcc/avr32.h +++ b/src/atomic_ops/sysdeps/gcc/avr32.h @@ -63,3 +63,5 @@ AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) return (int)ret; } #define AO_HAVE_compare_and_swap_full + +/* FIXME: implement AO_fetch_compare_and_swap */ diff --git a/src/atomic_ops/sysdeps/gcc/hexagon.h b/src/atomic_ops/sysdeps/gcc/hexagon.h index fdc9e56..9dff708 100644 --- a/src/atomic_ops/sysdeps/gcc/hexagon.h +++ b/src/atomic_ops/sysdeps/gcc/hexagon.h @@ -92,4 +92,6 @@ AO_compare_and_swap(volatile AO_t *addr, AO_t old, AO_t new_val) } #define AO_HAVE_compare_and_swap +/* FIXME: implement AO_fetch_compare_and_swap */ + #include "../ao_t_is_int.h" diff --git a/src/atomic_ops/sysdeps/gcc/ia64.h b/src/atomic_ops/sysdeps/gcc/ia64.h index 60c7a7e..086f314 100644 --- a/src/atomic_ops/sysdeps/gcc/ia64.h +++ b/src/atomic_ops/sysdeps/gcc/ia64.h @@ -189,6 +189,8 @@ AO_compare_and_swap_release(volatile AO_t *addr, } #define AO_HAVE_compare_and_swap_release +/* FIXME: implement AO_fetch_compare_and_swap */ + AO_INLINE int AO_char_compare_and_swap_acquire(volatile unsigned char *addr, unsigned char old, unsigned char new_val) diff --git a/src/atomic_ops/sysdeps/gcc/m68k.h b/src/atomic_ops/sysdeps/gcc/m68k.h index c898082..a00afe7 100644 --- a/src/atomic_ops/sysdeps/gcc/m68k.h +++ b/src/atomic_ops/sysdeps/gcc/m68k.h @@ -63,4 +63,6 @@ AO_compare_and_swap_full(volatile AO_t *addr, } #define AO_HAVE_compare_and_swap_full +/* FIXME: implement AO_fetch_compare_and_swap */ + #include "../ao_t_is_int.h" diff --git a/src/atomic_ops/sysdeps/gcc/mips.h b/src/atomic_ops/sysdeps/gcc/mips.h index 527a347..a91426c 100644 --- a/src/atomic_ops/sysdeps/gcc/mips.h +++ b/src/atomic_ops/sysdeps/gcc/mips.h @@ -94,6 +94,8 @@ AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) { } #define AO_HAVE_compare_and_swap_full +/* FIXME: implement AO_fetch_compare_and_swap */ + /* * FIXME: We should also implement fetch_and_add and or primitives * directly. diff --git a/src/atomic_ops/sysdeps/gcc/powerpc.h b/src/atomic_ops/sysdeps/gcc/powerpc.h index 69ec05b..5312a8e 100644 --- a/src/atomic_ops/sysdeps/gcc/powerpc.h +++ b/src/atomic_ops/sysdeps/gcc/powerpc.h @@ -225,6 +225,8 @@ AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) { } #define AO_HAVE_compare_and_swap_full +/* FIXME: implement AO_fetch_compare_and_swap */ + AO_INLINE AO_t AO_fetch_and_add(volatile AO_t *addr, AO_t incr) { AO_t oldval; diff --git a/src/atomic_ops/sysdeps/gcc/s390.h b/src/atomic_ops/sysdeps/gcc/s390.h index c05dc85..fadf944 100644 --- a/src/atomic_ops/sysdeps/gcc/s390.h +++ b/src/atomic_ops/sysdeps/gcc/s390.h @@ -59,4 +59,6 @@ AO_INLINE int AO_compare_and_swap_full(volatile AO_t *addr, } #define AO_HAVE_compare_and_swap_full +/* FIXME: implement AO_fetch_compare_and_swap */ + /* FIXME: Add double-wide compare-and-swap for 32-bit executables. */ diff --git a/src/atomic_ops/sysdeps/gcc/sparc.h b/src/atomic_ops/sysdeps/gcc/sparc.h index 41bc2f5..7647893 100644 --- a/src/atomic_ops/sysdeps/gcc/sparc.h +++ b/src/atomic_ops/sysdeps/gcc/sparc.h @@ -63,6 +63,8 @@ AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) { #define AO_HAVE_compare_and_swap_full #endif /* !AO_NO_SPARC_V9 */ +/* FIXME: implement AO_fetch_compare_and_swap */ + /* FIXME: This needs to be extended for SPARC v8 and v9. */ /* SPARC V8 also has swap. V9 has CAS. */ /* There are barriers like membar #LoadStore. */ diff --git a/src/atomic_ops/sysdeps/gcc/x86.h b/src/atomic_ops/sysdeps/gcc/x86.h index b304dd0..c408dbc 100644 --- a/src/atomic_ops/sysdeps/gcc/x86.h +++ b/src/atomic_ops/sysdeps/gcc/x86.h @@ -149,6 +149,8 @@ AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) } #define AO_HAVE_compare_and_swap_full +/* FIXME: implement AO_fetch_compare_and_swap */ + /* Returns nonzero if the comparison succeeded. */ /* Really requires at least a Pentium. */ AO_INLINE int diff --git a/src/atomic_ops/sysdeps/gcc/x86_64.h b/src/atomic_ops/sysdeps/gcc/x86_64.h index 9225270..de68c0f 100644 --- a/src/atomic_ops/sysdeps/gcc/x86_64.h +++ b/src/atomic_ops/sysdeps/gcc/x86_64.h @@ -143,6 +143,8 @@ AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) } #define AO_HAVE_compare_and_swap_full +/* FIXME: implement AO_fetch_compare_and_swap */ + #ifdef AO_CMPXCHG16B_AVAILABLE /* NEC LE-IT: older AMD Opterons are missing this instruction. diff --git a/src/atomic_ops/sysdeps/generic_pthread.h b/src/atomic_ops/sysdeps/generic_pthread.h index 8c8a91a..f051fc9 100644 --- a/src/atomic_ops/sysdeps/generic_pthread.h +++ b/src/atomic_ops/sysdeps/generic_pthread.h @@ -233,6 +233,8 @@ AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) } #define AO_HAVE_compare_and_swap_full +/* FIXME: implement AO_fetch_compare_and_swap */ + /* Unlike real architectures, we define both double-width CAS variants. */ typedef struct { diff --git a/src/atomic_ops/sysdeps/hpc/ia64.h b/src/atomic_ops/sysdeps/hpc/ia64.h index b793fcb..68e78cd 100644 --- a/src/atomic_ops/sysdeps/hpc/ia64.h +++ b/src/atomic_ops/sysdeps/hpc/ia64.h @@ -107,6 +107,8 @@ AO_compare_and_swap_release(volatile AO_t *addr, } #define AO_HAVE_compare_and_swap_release +/* FIXME: implement AO_fetch_compare_and_swap */ + AO_INLINE int AO_char_compare_and_swap_acquire(volatile unsigned char *addr, unsigned char old, unsigned char new_val) diff --git a/src/atomic_ops/sysdeps/ibmc/powerpc.h b/src/atomic_ops/sysdeps/ibmc/powerpc.h index 4378dca..a51c3d5 100644 --- a/src/atomic_ops/sysdeps/ibmc/powerpc.h +++ b/src/atomic_ops/sysdeps/ibmc/powerpc.h @@ -120,5 +120,5 @@ AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) } #define AO_HAVE_compare_and_swap_full -/* FIXME: We should also implement fetch_and_add and or primitives */ -/* directly. */ +/* FIXME: We should also implement AO_fetch_compare_and_swap, */ +/* AO_fetch_and_add, AO_and/or/xor primitives directly. */ diff --git a/src/atomic_ops/sysdeps/icc/ia64.h b/src/atomic_ops/sysdeps/icc/ia64.h index cfa2073..9562265 100644 --- a/src/atomic_ops/sysdeps/icc/ia64.h +++ b/src/atomic_ops/sysdeps/icc/ia64.h @@ -152,6 +152,8 @@ AO_compare_and_swap_release(volatile AO_t *addr, } #define AO_HAVE_compare_and_swap_release +/* FIXME: implement AO_fetch_compare_and_swap */ + AO_INLINE int AO_char_compare_and_swap_acquire(volatile unsigned char *addr, unsigned char old, unsigned char new_val) diff --git a/src/atomic_ops/sysdeps/msftc/common32_defs.h b/src/atomic_ops/sysdeps/msftc/common32_defs.h index 5d519f0..3b5c782 100644 --- a/src/atomic_ops/sysdeps/msftc/common32_defs.h +++ b/src/atomic_ops/sysdeps/msftc/common32_defs.h @@ -115,4 +115,6 @@ AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) # endif } # define AO_HAVE_compare_and_swap_full + +/* FIXME: implement AO_fetch_compare_and_swap */ #endif /* AO_ASSUME_WINDOWS98 */ diff --git a/src/atomic_ops/sysdeps/msftc/x86_64.h b/src/atomic_ops/sysdeps/msftc/x86_64.h index 135a053..3b10543 100644 --- a/src/atomic_ops/sysdeps/msftc/x86_64.h +++ b/src/atomic_ops/sysdeps/msftc/x86_64.h @@ -85,6 +85,8 @@ AO_compare_and_swap_full(volatile AO_t *addr, } #define AO_HAVE_compare_and_swap_full +/* FIXME: implement AO_fetch_compare_and_swap */ + /* As far as we can tell, the lfence and sfence instructions are not */ /* currently needed or useful for cached memory accesses. */ diff --git a/src/atomic_ops/sysdeps/sunc/x86.h b/src/atomic_ops/sysdeps/sunc/x86.h index 9abd8a0..8db5851 100644 --- a/src/atomic_ops/sysdeps/sunc/x86.h +++ b/src/atomic_ops/sysdeps/sunc/x86.h @@ -142,6 +142,8 @@ AO_compare_and_swap_full (volatile AO_t *addr, AO_t old, AO_t new_val) } #define AO_HAVE_compare_and_swap_full +/* FIXME: implement AO_fetch_compare_and_swap */ + #if 0 /* FIXME: not tested (and probably wrong). Besides, */ /* it tickles a bug in Sun C 5.10 (when optimizing). */ diff --git a/src/atomic_ops/sysdeps/sunc/x86_64.h b/src/atomic_ops/sysdeps/sunc/x86_64.h index 5be6d9a..d888a5d 100644 --- a/src/atomic_ops/sysdeps/sunc/x86_64.h +++ b/src/atomic_ops/sysdeps/sunc/x86_64.h @@ -142,6 +142,8 @@ AO_compare_and_swap_full (volatile AO_t *addr, AO_t old, AO_t new_val) } #define AO_HAVE_compare_and_swap_full +/* FIXME: implement AO_fetch_compare_and_swap */ + #ifdef AO_CMPXCHG16B_AVAILABLE /* NEC LE-IT: older AMD Opterons are missing this instruction. * On these machines SIGILL will be thrown. diff --git a/tests/list_atomic.template b/tests/list_atomic.template index 7fdef11..1c1d632 100644 --- a/tests/list_atomic.template +++ b/tests/list_atomic.template @@ -65,4 +65,5 @@ void list_atomicXX(void) # else "No AO_compare_and_swapXX"; # endif +/* FIXME: test AO_fetch_compare_and_swap */ } diff --git a/tests/test_atomic_include.template b/tests/test_atomic_include.template index 9fec3f9..ea1f14c 100644 --- a/tests/test_atomic_include.template +++ b/tests/test_atomic_include.template @@ -170,6 +170,7 @@ void test_atomicXX(void) MISSING(AO_compare_and_swap); if (x == 13) x = 42; # endif +/* FIXME: test AO_fetch_compare_and_swap */ # if defined(AO_HAVE_orXX) AO_orXX(&x, 66); TA_assert(x == 106); -- 2.7.4