diff --git a/docs/ispc.rst b/docs/ispc.rst index 7668e5e9..9edd7325 100644 --- a/docs/ispc.rst +++ b/docs/ispc.rst @@ -3797,6 +3797,13 @@ For global atomics, only atomic swap is available for these types: float atomic_swap_global(uniform float * uniform ptr, float value) double atomic_swap_global(uniform double * uniform ptr, double value) +Finally, "swap" (but none of these other atomics) is available for pointer +types: + +:: + + void *atomic_swap_{local,global}(void * * uniform ptr, void * value) + There are also variants of the atomic that take ``uniform`` values for the operand and return a ``uniform`` result. These correspond to a single atomic operation being performed for the entire gang of program instances, @@ -3821,6 +3828,13 @@ rather than one per program instance. uniform int32 atomic_swap_{local,global}(uniform int32 * uniform ptr, uniform int32 newval) +And similarly for pointers: + +:: + + uniform void *atomic_swap_{local,global}(void * * uniform ptr, + void *newval) + Be careful that you use the atomic function that you mean to; consider the following code: @@ -3862,12 +3876,18 @@ the same location in memory!) int32 atomic_xor_{local,global}(uniform int32 * varying ptr, int32 value) int32 atomic_swap_{local,global}(uniform int32 * varying ptr, int32 value) +And: + +:: + + void *atomic_swap_{local,global}(void * * ptr, void *value) + There are also atomic "compare and exchange" functions. Compare and exchange atomically compares the value in "val" to "compare"--if they match, it assigns "newval" to "val". In either case, the old value of "val" is returned. (As with the other atomic operations, there are also ``unsigned`` and 64-bit variants of this function. Furthermore, there are -``float`` and ``double`` variants as well.) +``float``, ``double``, and ``void *`` variants as well.) :: diff --git a/stdlib.ispc b/stdlib.ispc index cebed66f..fd0df7ce 100644 --- a/stdlib.ispc +++ b/stdlib.ispc @@ -1772,6 +1772,49 @@ ATOMIC_DECL_CMPXCHG(double, double, IntMaskType) #undef ATOMIC_DECL_CMPXCHG +// void * variants of swap and compare exchange + +static inline void *atomic_swap_global(void ** uniform ptr, + void * value) { + return (void *)atomic_swap_global((intptr_t * uniform)ptr, + (intptr_t)value); +} + +static inline void * uniform atomic_swap_global(void ** uniform ptr, + void * uniform value) { + return (void * uniform)atomic_swap_global((intptr_t * uniform)ptr, + (uniform intptr_t)value); +} + +static inline void *atomic_swap_global(void ** ptr, void * value) { + return (void *)atomic_swap_global((intptr_t *)ptr, + (intptr_t)value); +} + +static inline void * +atomic_compare_exchange_global(void ** uniform ptr, + void * oldval, void * newval) { + return (void *)atomic_compare_exchange_global((intptr_t * uniform)ptr, + (intptr_t)oldval, + (intptr_t)newval); +} + +static inline void * uniform +atomic_compare_exchange_global(void ** uniform ptr, void * uniform oldval, + void * uniform newval) { + return (void * uniform)atomic_compare_exchange_global((intptr_t * uniform)ptr, + (uniform intptr_t)oldval, + (uniform intptr_t)newval); +} + +static inline void * +atomic_compare_exchange_global(void ** ptr, void * oldval, + void * newval) { + return (void *)atomic_compare_exchange_global((intptr_t *)ptr, + (intptr_t)oldval, + (intptr_t)newval); +} + /////////////////////////////////////////////////////////////////////////// // local atomics @@ -1943,6 +1986,49 @@ LOCAL_CMPXCHG(double) #undef LOCAL_ATOMIC #undef LOCAL_CMPXCHG +// void * variants of swap and compare exchange + +static inline void *atomic_swap_local(void ** uniform ptr, + void * value) { + return (void *)atomic_swap_local((intptr_t * uniform)ptr, + (intptr_t)value); +} + +static inline void * uniform atomic_swap_local(void ** uniform ptr, + void * uniform value) { + return (void * uniform)atomic_swap_local((intptr_t * uniform)ptr, + (uniform intptr_t)value); +} + +static inline void *atomic_swap_local(void ** ptr, void * value) { + return (void *)atomic_swap_local((intptr_t *)ptr, + (intptr_t)value); +} + +static inline void * +atomic_compare_exchange_local(void ** uniform ptr, + void * oldval, void * newval) { + return (void *)atomic_compare_exchange_local((intptr_t * uniform)ptr, + (intptr_t)oldval, + (intptr_t)newval); +} + +static inline void * uniform +atomic_compare_exchange_local(void ** uniform ptr, void * uniform oldval, + void * uniform newval) { + return (void * uniform)atomic_compare_exchange_local((intptr_t * uniform)ptr, + (uniform intptr_t)oldval, + (uniform intptr_t)newval); +} + +static inline void * +atomic_compare_exchange_local(void ** ptr, void * oldval, + void * newval) { + return (void *)atomic_compare_exchange_local((intptr_t *)ptr, + (intptr_t)oldval, + (intptr_t)newval); +} + /////////////////////////////////////////////////////////////////////////// // Transcendentals (float precision)