From: Ivan Maidanski Date: Thu, 3 Jan 2013 15:18:11 +0000 (+0400) Subject: Enable generalization of all variants of CAS via fetch_compare_and_swap X-Git-Tag: libatomic_ops-7_4_0~48^2~44 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=45f058c48ad1a8889a5d4fc2c2c50cfb70c5c5ed;p=libatomic_ops Enable generalization of all variants of CAS via fetch_compare_and_swap * src/atomic_ops/generalize.h (AO_compare_and_swap_full, AO_compare_and_swap_acquire, AO_compare_and_swap_release, AO_compare_and_swap, AO_TS_COMPARE_AND_SWAP_FULL, AO_TS_COMPARE_AND_SWAP_ACQUIRE, AO_TS_COMPARE_AND_SWAP_RELEASE, AO_TS_COMPARE_AND_SWAP): Define (in this file) only if required for AO_test_and_set_X generalization. * src/atomic_ops/generalize-arithm.template (AO_XSIZE_compare_and_swap_write, AO_XSIZE_compare_and_swap_read, AO_XSIZE_compare_and_swap_release_write, AO_XSIZE_compare_and_swap_acquire_read, AO_XSIZE_compare_and_swap_dd_acquire_read): Add missing variant of generalized template CAS primitives based fetch_compare_and_swap; add the corresponding AO_HAVE_XSIZE_compare_and_swap_X macros. * src/atomic_ops/generalize-arithm.h: Regenerate. --- diff --git a/src/atomic_ops/generalize-arithm.h b/src/atomic_ops/generalize-arithm.h index 00d35a8..a50c697 100644 --- a/src/atomic_ops/generalize-arithm.h +++ b/src/atomic_ops/generalize-arithm.h @@ -57,6 +57,30 @@ # define AO_HAVE_char_compare_and_swap_release #endif +#if defined(AO_HAVE_char_fetch_compare_and_swap_write) \ + && !defined(AO_HAVE_char_compare_and_swap_write) + AO_INLINE int + AO_char_compare_and_swap_write(volatile unsigned/**/char *addr, unsigned/**/char old_val, + unsigned/**/char new_val) + { + return AO_char_fetch_compare_and_swap_write(addr, old_val, new_val) + == old_val; + } +# define AO_HAVE_char_compare_and_swap_write +#endif + +#if defined(AO_HAVE_char_fetch_compare_and_swap_read) \ + && !defined(AO_HAVE_char_compare_and_swap_read) + AO_INLINE int + AO_char_compare_and_swap_read(volatile unsigned/**/char *addr, unsigned/**/char old_val, + unsigned/**/char new_val) + { + return AO_char_fetch_compare_and_swap_read(addr, old_val, new_val) + == old_val; + } +# define AO_HAVE_char_compare_and_swap_read +#endif + #if defined(AO_HAVE_char_fetch_compare_and_swap) \ && !defined(AO_HAVE_char_compare_and_swap) AO_INLINE int @@ -68,6 +92,42 @@ # define AO_HAVE_char_compare_and_swap #endif +#if defined(AO_HAVE_char_fetch_compare_and_swap_release_write) \ + && !defined(AO_HAVE_char_compare_and_swap_release_write) + AO_INLINE int + AO_char_compare_and_swap_release_write(volatile unsigned/**/char *addr, + unsigned/**/char old_val, unsigned/**/char new_val) + { + return AO_char_fetch_compare_and_swap_release_write(addr, old_val, + new_val) == old_val; + } +# define AO_HAVE_char_compare_and_swap_release_write +#endif + +#if defined(AO_HAVE_char_fetch_compare_and_swap_acquire_read) \ + && !defined(AO_HAVE_char_compare_and_swap_acquire_read) + AO_INLINE int + AO_char_compare_and_swap_acquire_read(volatile unsigned/**/char *addr, + unsigned/**/char old_val, unsigned/**/char new_val) + { + return AO_char_fetch_compare_and_swap_acquire_read(addr, old_val, + new_val) == old_val; + } +# define AO_HAVE_char_compare_and_swap_acquire_read +#endif + +#if defined(AO_HAVE_char_fetch_compare_and_swap_dd_acquire_read) \ + && !defined(AO_HAVE_char_compare_and_swap_dd_acquire_read) + AO_INLINE int + AO_char_compare_and_swap_dd_acquire_read(volatile unsigned/**/char *addr, + unsigned/**/char old_val, unsigned/**/char new_val) + { + return AO_char_fetch_compare_and_swap_dd_acquire_read(addr, old_val, + new_val) == old_val; + } +# define AO_HAVE_char_compare_and_swap_dd_acquire_read +#endif + /* char_fetch_and_add */ /* We first try to implement fetch_and_add variants in terms of the */ /* corresponding compare_and_swap variants to minimize adding barriers. */ @@ -824,6 +884,30 @@ # define AO_HAVE_short_compare_and_swap_release #endif +#if defined(AO_HAVE_short_fetch_compare_and_swap_write) \ + && !defined(AO_HAVE_short_compare_and_swap_write) + AO_INLINE int + AO_short_compare_and_swap_write(volatile unsigned/**/short *addr, unsigned/**/short old_val, + unsigned/**/short new_val) + { + return AO_short_fetch_compare_and_swap_write(addr, old_val, new_val) + == old_val; + } +# define AO_HAVE_short_compare_and_swap_write +#endif + +#if defined(AO_HAVE_short_fetch_compare_and_swap_read) \ + && !defined(AO_HAVE_short_compare_and_swap_read) + AO_INLINE int + AO_short_compare_and_swap_read(volatile unsigned/**/short *addr, unsigned/**/short old_val, + unsigned/**/short new_val) + { + return AO_short_fetch_compare_and_swap_read(addr, old_val, new_val) + == old_val; + } +# define AO_HAVE_short_compare_and_swap_read +#endif + #if defined(AO_HAVE_short_fetch_compare_and_swap) \ && !defined(AO_HAVE_short_compare_and_swap) AO_INLINE int @@ -835,6 +919,42 @@ # define AO_HAVE_short_compare_and_swap #endif +#if defined(AO_HAVE_short_fetch_compare_and_swap_release_write) \ + && !defined(AO_HAVE_short_compare_and_swap_release_write) + AO_INLINE int + AO_short_compare_and_swap_release_write(volatile unsigned/**/short *addr, + unsigned/**/short old_val, unsigned/**/short new_val) + { + return AO_short_fetch_compare_and_swap_release_write(addr, old_val, + new_val) == old_val; + } +# define AO_HAVE_short_compare_and_swap_release_write +#endif + +#if defined(AO_HAVE_short_fetch_compare_and_swap_acquire_read) \ + && !defined(AO_HAVE_short_compare_and_swap_acquire_read) + AO_INLINE int + AO_short_compare_and_swap_acquire_read(volatile unsigned/**/short *addr, + unsigned/**/short old_val, unsigned/**/short new_val) + { + return AO_short_fetch_compare_and_swap_acquire_read(addr, old_val, + new_val) == old_val; + } +# define AO_HAVE_short_compare_and_swap_acquire_read +#endif + +#if defined(AO_HAVE_short_fetch_compare_and_swap_dd_acquire_read) \ + && !defined(AO_HAVE_short_compare_and_swap_dd_acquire_read) + AO_INLINE int + AO_short_compare_and_swap_dd_acquire_read(volatile unsigned/**/short *addr, + unsigned/**/short old_val, unsigned/**/short new_val) + { + return AO_short_fetch_compare_and_swap_dd_acquire_read(addr, old_val, + new_val) == old_val; + } +# define AO_HAVE_short_compare_and_swap_dd_acquire_read +#endif + /* short_fetch_and_add */ /* We first try to implement fetch_and_add variants in terms of the */ /* corresponding compare_and_swap variants to minimize adding barriers. */ @@ -1591,6 +1711,30 @@ # define AO_HAVE_int_compare_and_swap_release #endif +#if defined(AO_HAVE_int_fetch_compare_and_swap_write) \ + && !defined(AO_HAVE_int_compare_and_swap_write) + AO_INLINE int + AO_int_compare_and_swap_write(volatile unsigned *addr, unsigned old_val, + unsigned new_val) + { + return AO_int_fetch_compare_and_swap_write(addr, old_val, new_val) + == old_val; + } +# define AO_HAVE_int_compare_and_swap_write +#endif + +#if defined(AO_HAVE_int_fetch_compare_and_swap_read) \ + && !defined(AO_HAVE_int_compare_and_swap_read) + AO_INLINE int + AO_int_compare_and_swap_read(volatile unsigned *addr, unsigned old_val, + unsigned new_val) + { + return AO_int_fetch_compare_and_swap_read(addr, old_val, new_val) + == old_val; + } +# define AO_HAVE_int_compare_and_swap_read +#endif + #if defined(AO_HAVE_int_fetch_compare_and_swap) \ && !defined(AO_HAVE_int_compare_and_swap) AO_INLINE int @@ -1602,6 +1746,42 @@ # define AO_HAVE_int_compare_and_swap #endif +#if defined(AO_HAVE_int_fetch_compare_and_swap_release_write) \ + && !defined(AO_HAVE_int_compare_and_swap_release_write) + AO_INLINE int + AO_int_compare_and_swap_release_write(volatile unsigned *addr, + unsigned old_val, unsigned new_val) + { + return AO_int_fetch_compare_and_swap_release_write(addr, old_val, + new_val) == old_val; + } +# define AO_HAVE_int_compare_and_swap_release_write +#endif + +#if defined(AO_HAVE_int_fetch_compare_and_swap_acquire_read) \ + && !defined(AO_HAVE_int_compare_and_swap_acquire_read) + AO_INLINE int + AO_int_compare_and_swap_acquire_read(volatile unsigned *addr, + unsigned old_val, unsigned new_val) + { + return AO_int_fetch_compare_and_swap_acquire_read(addr, old_val, + new_val) == old_val; + } +# define AO_HAVE_int_compare_and_swap_acquire_read +#endif + +#if defined(AO_HAVE_int_fetch_compare_and_swap_dd_acquire_read) \ + && !defined(AO_HAVE_int_compare_and_swap_dd_acquire_read) + AO_INLINE int + AO_int_compare_and_swap_dd_acquire_read(volatile unsigned *addr, + unsigned old_val, unsigned new_val) + { + return AO_int_fetch_compare_and_swap_dd_acquire_read(addr, old_val, + new_val) == old_val; + } +# define AO_HAVE_int_compare_and_swap_dd_acquire_read +#endif + /* int_fetch_and_add */ /* We first try to implement fetch_and_add variants in terms of the */ /* corresponding compare_and_swap variants to minimize adding barriers. */ @@ -2358,6 +2538,30 @@ # define AO_HAVE_compare_and_swap_release #endif +#if defined(AO_HAVE_fetch_compare_and_swap_write) \ + && !defined(AO_HAVE_compare_and_swap_write) + AO_INLINE int + AO_compare_and_swap_write(volatile AO_t *addr, AO_t old_val, + AO_t new_val) + { + return AO_fetch_compare_and_swap_write(addr, old_val, new_val) + == old_val; + } +# define AO_HAVE_compare_and_swap_write +#endif + +#if defined(AO_HAVE_fetch_compare_and_swap_read) \ + && !defined(AO_HAVE_compare_and_swap_read) + AO_INLINE int + AO_compare_and_swap_read(volatile AO_t *addr, AO_t old_val, + AO_t new_val) + { + return AO_fetch_compare_and_swap_read(addr, old_val, new_val) + == old_val; + } +# define AO_HAVE_compare_and_swap_read +#endif + #if defined(AO_HAVE_fetch_compare_and_swap) \ && !defined(AO_HAVE_compare_and_swap) AO_INLINE int @@ -2369,6 +2573,42 @@ # define AO_HAVE_compare_and_swap #endif +#if defined(AO_HAVE_fetch_compare_and_swap_release_write) \ + && !defined(AO_HAVE_compare_and_swap_release_write) + AO_INLINE int + AO_compare_and_swap_release_write(volatile AO_t *addr, + AO_t old_val, AO_t new_val) + { + return AO_fetch_compare_and_swap_release_write(addr, old_val, + new_val) == old_val; + } +# define AO_HAVE_compare_and_swap_release_write +#endif + +#if defined(AO_HAVE_fetch_compare_and_swap_acquire_read) \ + && !defined(AO_HAVE_compare_and_swap_acquire_read) + AO_INLINE int + AO_compare_and_swap_acquire_read(volatile AO_t *addr, + AO_t old_val, AO_t new_val) + { + return AO_fetch_compare_and_swap_acquire_read(addr, old_val, + new_val) == old_val; + } +# define AO_HAVE_compare_and_swap_acquire_read +#endif + +#if defined(AO_HAVE_fetch_compare_and_swap_dd_acquire_read) \ + && !defined(AO_HAVE_compare_and_swap_dd_acquire_read) + AO_INLINE int + AO_compare_and_swap_dd_acquire_read(volatile AO_t *addr, + AO_t old_val, AO_t new_val) + { + return AO_fetch_compare_and_swap_dd_acquire_read(addr, old_val, + new_val) == old_val; + } +# define AO_HAVE_compare_and_swap_dd_acquire_read +#endif + /* fetch_and_add */ /* We first try to implement fetch_and_add variants in terms of the */ /* corresponding compare_and_swap variants to minimize adding barriers. */ diff --git a/src/atomic_ops/generalize-arithm.template b/src/atomic_ops/generalize-arithm.template index b7c5c7d..93750c8 100644 --- a/src/atomic_ops/generalize-arithm.template +++ b/src/atomic_ops/generalize-arithm.template @@ -57,6 +57,30 @@ # define AO_HAVE_XSIZE_compare_and_swap_release #endif +#if defined(AO_HAVE_XSIZE_fetch_compare_and_swap_write) \ + && !defined(AO_HAVE_XSIZE_compare_and_swap_write) + AO_INLINE int + AO_XSIZE_compare_and_swap_write(volatile XCTYPE *addr, XCTYPE old_val, + XCTYPE new_val) + { + return AO_XSIZE_fetch_compare_and_swap_write(addr, old_val, new_val) + == old_val; + } +# define AO_HAVE_XSIZE_compare_and_swap_write +#endif + +#if defined(AO_HAVE_XSIZE_fetch_compare_and_swap_read) \ + && !defined(AO_HAVE_XSIZE_compare_and_swap_read) + AO_INLINE int + AO_XSIZE_compare_and_swap_read(volatile XCTYPE *addr, XCTYPE old_val, + XCTYPE new_val) + { + return AO_XSIZE_fetch_compare_and_swap_read(addr, old_val, new_val) + == old_val; + } +# define AO_HAVE_XSIZE_compare_and_swap_read +#endif + #if defined(AO_HAVE_XSIZE_fetch_compare_and_swap) \ && !defined(AO_HAVE_XSIZE_compare_and_swap) AO_INLINE int @@ -68,6 +92,42 @@ # define AO_HAVE_XSIZE_compare_and_swap #endif +#if defined(AO_HAVE_XSIZE_fetch_compare_and_swap_release_write) \ + && !defined(AO_HAVE_XSIZE_compare_and_swap_release_write) + AO_INLINE int + AO_XSIZE_compare_and_swap_release_write(volatile XCTYPE *addr, + XCTYPE old_val, XCTYPE new_val) + { + return AO_XSIZE_fetch_compare_and_swap_release_write(addr, old_val, + new_val) == old_val; + } +# define AO_HAVE_XSIZE_compare_and_swap_release_write +#endif + +#if defined(AO_HAVE_XSIZE_fetch_compare_and_swap_acquire_read) \ + && !defined(AO_HAVE_XSIZE_compare_and_swap_acquire_read) + AO_INLINE int + AO_XSIZE_compare_and_swap_acquire_read(volatile XCTYPE *addr, + XCTYPE old_val, XCTYPE new_val) + { + return AO_XSIZE_fetch_compare_and_swap_acquire_read(addr, old_val, + new_val) == old_val; + } +# define AO_HAVE_XSIZE_compare_and_swap_acquire_read +#endif + +#if defined(AO_HAVE_XSIZE_fetch_compare_and_swap_dd_acquire_read) \ + && !defined(AO_HAVE_XSIZE_compare_and_swap_dd_acquire_read) + AO_INLINE int + AO_XSIZE_compare_and_swap_dd_acquire_read(volatile XCTYPE *addr, + XCTYPE old_val, XCTYPE new_val) + { + return AO_XSIZE_fetch_compare_and_swap_dd_acquire_read(addr, old_val, + new_val) == old_val; + } +# define AO_HAVE_XSIZE_compare_and_swap_dd_acquire_read +#endif + /* XSIZE_fetch_and_add */ /* We first try to implement fetch_and_add variants in terms of the */ /* corresponding compare_and_swap variants to minimize adding barriers. */ diff --git a/src/atomic_ops/generalize.h b/src/atomic_ops/generalize.h index 7755575..3e66341 100644 --- a/src/atomic_ops/generalize.h +++ b/src/atomic_ops/generalize.h @@ -47,73 +47,77 @@ # error This file should not be included directly. #endif -/* Emulate AO_compare_and_swap() via AO_fetch_compare_and_swap(). */ -#if defined(AO_HAVE_fetch_compare_and_swap) \ - && !defined(AO_HAVE_compare_and_swap) - AO_INLINE int - AO_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val) - { - return AO_fetch_compare_and_swap(addr, old_val, new_val) == old_val; - } -# define AO_HAVE_compare_and_swap -#endif +/* Generate test_and_set_full, if necessary and possible. */ +#if !defined(AO_HAVE_test_and_set) && !defined(AO_HAVE_test_and_set_release) \ + && !defined(AO_HAVE_test_and_set_acquire) \ + && !defined(AO_HAVE_test_and_set_read) \ + && !defined(AO_HAVE_test_and_set_full) -#if defined(AO_HAVE_fetch_compare_and_swap_full) \ - && !defined(AO_HAVE_compare_and_swap_full) - AO_INLINE int - AO_compare_and_swap_full(volatile AO_t *addr, AO_t old_val, AO_t new_val) - { - return AO_fetch_compare_and_swap_full(addr, old_val, new_val) == old_val; - } -# define AO_HAVE_compare_and_swap_full -#endif + /* Emulate AO_compare_and_swap() via AO_fetch_compare_and_swap(). */ +# if defined(AO_HAVE_fetch_compare_and_swap) \ + && !defined(AO_HAVE_compare_and_swap) + AO_INLINE int + AO_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val) + { + return AO_fetch_compare_and_swap(addr, old_val, new_val) == old_val; + } +# define AO_HAVE_compare_and_swap +# endif -#if defined(AO_HAVE_fetch_compare_and_swap_acquire) \ - && !defined(AO_HAVE_compare_and_swap_acquire) - AO_INLINE int - AO_compare_and_swap_acquire(volatile AO_t *addr, AO_t old_val, AO_t new_val) - { - return AO_fetch_compare_and_swap_acquire(addr, old_val, new_val) - == old_val; - } -# define AO_HAVE_compare_and_swap_acquire -#endif +# if defined(AO_HAVE_fetch_compare_and_swap_full) \ + && !defined(AO_HAVE_compare_and_swap_full) + AO_INLINE int + AO_compare_and_swap_full(volatile AO_t *addr, AO_t old_val, AO_t new_val) + { + return AO_fetch_compare_and_swap_full(addr, old_val, new_val) + == old_val; + } +# define AO_HAVE_compare_and_swap_full +# endif -#if defined(AO_HAVE_fetch_compare_and_swap_release) \ - && !defined(AO_HAVE_compare_and_swap_release) - AO_INLINE int - AO_compare_and_swap_release(volatile AO_t *addr, AO_t old_val, AO_t new_val) - { - return AO_fetch_compare_and_swap_release(addr, old_val, new_val) - == old_val; - } -# define AO_HAVE_compare_and_swap_release -#endif +# if defined(AO_HAVE_fetch_compare_and_swap_acquire) \ + && !defined(AO_HAVE_compare_and_swap_acquire) + AO_INLINE int + AO_compare_and_swap_acquire(volatile AO_t *addr, AO_t old_val, + AO_t new_val) + { + return AO_fetch_compare_and_swap_acquire(addr, old_val, new_val) + == old_val; + } +# define AO_HAVE_compare_and_swap_acquire +# endif -#if AO_CHAR_TS_T -# define AO_TS_COMPARE_AND_SWAP_FULL(a,o,n) \ +# if defined(AO_HAVE_fetch_compare_and_swap_release) \ + && !defined(AO_HAVE_compare_and_swap_release) + AO_INLINE int + AO_compare_and_swap_release(volatile AO_t *addr, AO_t old_val, + AO_t new_val) + { + return AO_fetch_compare_and_swap_release(addr, old_val, new_val) + == old_val; + } +# define AO_HAVE_compare_and_swap_release +# endif + +# if AO_CHAR_TS_T +# define AO_TS_COMPARE_AND_SWAP_FULL(a,o,n) \ AO_char_compare_and_swap_full(a,o,n) -# define AO_TS_COMPARE_AND_SWAP_ACQUIRE(a,o,n) \ +# define AO_TS_COMPARE_AND_SWAP_ACQUIRE(a,o,n) \ AO_char_compare_and_swap_acquire(a,o,n) -# define AO_TS_COMPARE_AND_SWAP_RELEASE(a,o,n) \ +# define AO_TS_COMPARE_AND_SWAP_RELEASE(a,o,n) \ AO_char_compare_and_swap_release(a,o,n) -# define AO_TS_COMPARE_AND_SWAP(a,o,n) AO_char_compare_and_swap(a,o,n) -#endif +# define AO_TS_COMPARE_AND_SWAP(a,o,n) AO_char_compare_and_swap(a,o,n) +# endif -#if AO_AO_TS_T -# define AO_TS_COMPARE_AND_SWAP_FULL(a,o,n) AO_compare_and_swap_full(a,o,n) -# define AO_TS_COMPARE_AND_SWAP_ACQUIRE(a,o,n) \ - AO_compare_and_swap_acquire(a,o,n) -# define AO_TS_COMPARE_AND_SWAP_RELEASE(a,o,n) \ - AO_compare_and_swap_release(a,o,n) -# define AO_TS_COMPARE_AND_SWAP(a,o,n) AO_compare_and_swap(a,o,n) -#endif +# if AO_AO_TS_T +# define AO_TS_COMPARE_AND_SWAP_FULL(a,o,n) AO_compare_and_swap_full(a,o,n) +# define AO_TS_COMPARE_AND_SWAP_ACQUIRE(a,o,n) \ + AO_compare_and_swap_acquire(a,o,n) +# define AO_TS_COMPARE_AND_SWAP_RELEASE(a,o,n) \ + AO_compare_and_swap_release(a,o,n) +# define AO_TS_COMPARE_AND_SWAP(a,o,n) AO_compare_and_swap(a,o,n) +# endif -/* Generate test_and_set_full, if necessary and possible. */ -#if !defined(AO_HAVE_test_and_set) && !defined(AO_HAVE_test_and_set_release) \ - && !defined(AO_HAVE_test_and_set_acquire) \ - && !defined(AO_HAVE_test_and_set_read) \ - && !defined(AO_HAVE_test_and_set_full) # if (AO_AO_TS_T && defined(AO_HAVE_compare_and_swap_full)) \ || (AO_CHAR_TS_T && defined(AO_HAVE_char_compare_and_swap_full)) AO_INLINE AO_TS_VAL_t