// SPDX-FileCopyrightText: 2023 Olivier Dion // // SPDX-License-Identifier: LGPL-2.1-or-later /* * urcu/uatomic/builtins-generic.h */ #ifndef _URCU_UATOMIC_BUILTINS_GENERIC_H #define _URCU_UATOMIC_BUILTINS_GENERIC_H #include #include /* * Whether the memory order `CMM_SEQ_CST_FENCE` should emit a fence after an * atomic load operation. Can be overriden by the architecture. * * Default: Emit the memory barrier. */ #ifndef cmm_seq_cst_fence_after_atomic_load # define cmm_seq_cst_fence_after_atomic_load cmm_seq_cst_fence_after_atomic #endif /* * Whether the memory order `CMM_SEQ_CST_FENCE` should emit a fence after an * atomic store operation. Can be overriden by the architecture. * * Default: Emit the memory barrier. */ #ifndef cmm_seq_cst_fence_after_atomic_store # define cmm_seq_cst_fence_after_atomic_store cmm_seq_cst_fence_after_atomic #endif /* * Whether the memory order `CMM_SEQ_CST_FENCE` should emit a fence after an * atomic read-modify-write operation. Can be overriden by the architecture. * * Default: Emit the memory barrier. */ #ifndef cmm_seq_cst_fence_after_atomic_rmw # define cmm_seq_cst_fence_after_atomic_rmw cmm_seq_cst_fence_after_atomic #endif #define uatomic_store_mo(addr, v, mo) \ do { \ _cmm_static_assert__atomic_lf(sizeof(*(addr))); \ __atomic_store_n(cmm_cast_volatile(addr), v, \ cmm_to_c11(mo)); \ cmm_seq_cst_fence_after_atomic_store(mo); \ } while (0) #define uatomic_load_mo(addr, mo) \ __extension__ \ ({ \ _cmm_static_assert__atomic_lf(sizeof(*(addr))); \ __typeof__(*(addr)) _value = \ __atomic_load_n(cmm_cast_volatile(addr), \ cmm_to_c11(mo)); \ cmm_seq_cst_fence_after_atomic_load(mo); \ \ _value; \ }) #define uatomic_cmpxchg_mo(addr, old, new, mos, mof) \ __extension__ \ ({ \ __typeof__(*(addr)) _old = (__typeof__(*(addr)))old; \ \ _cmm_static_assert__atomic_lf(sizeof(*(addr))); \ if (__atomic_compare_exchange_n(cmm_cast_volatile(addr), \ &_old, new, 0, \ cmm_to_c11(mos), \ cmm_to_c11(mof))) { \ cmm_seq_cst_fence_after_atomic_rmw(mos); \ } else { \ cmm_seq_cst_fence_after_atomic_rmw(mof); \ } \ _old; \ }) #define uatomic_xchg_mo(addr, v, mo) \ __extension__ \ ({ \ _cmm_static_assert__atomic_lf(sizeof(*(addr))); \ __typeof__((*addr)) _old = \ __atomic_exchange_n(cmm_cast_volatile(addr), v, \ cmm_to_c11(mo)); \ cmm_seq_cst_fence_after_atomic_rmw(mo); \ _old; \ }) #define uatomic_add_return_mo(addr, v, mo) \ __extension__ \ ({ \ _cmm_static_assert__atomic_lf(sizeof(*(addr))); \ __typeof__(*(addr)) _old = \ __atomic_add_fetch(cmm_cast_volatile(addr), v, \ cmm_to_c11(mo)); \ cmm_seq_cst_fence_after_atomic_rmw(mo); \ _old; \ }) #define uatomic_sub_return_mo(addr, v, mo) \ __extension__ \ ({ \ _cmm_static_assert__atomic_lf(sizeof(*(addr))); \ __typeof__(*(addr)) _old = \ __atomic_sub_fetch(cmm_cast_volatile(addr), v, \ cmm_to_c11(mo)); \ cmm_seq_cst_fence_after_atomic_rmw(mo); \ _old; \ }) #define uatomic_and_mo(addr, mask, mo) \ do { \ _cmm_static_assert__atomic_lf(sizeof(*(addr))); \ (void) __atomic_and_fetch(cmm_cast_volatile(addr), mask, \ cmm_to_c11(mo)); \ cmm_seq_cst_fence_after_atomic_rmw(mo); \ } while (0) #define uatomic_or_mo(addr, mask, mo) \ do { \ _cmm_static_assert__atomic_lf(sizeof(*(addr))); \ (void) __atomic_or_fetch(cmm_cast_volatile(addr), mask, \ cmm_to_c11(mo)); \ cmm_seq_cst_fence_after_atomic_rmw(mo); \ } while (0) #define uatomic_add_mo(addr, v, mo) \ (void) uatomic_add_return_mo(addr, v, mo) #define uatomic_sub_mo(addr, v, mo) \ (void) uatomic_sub_return_mo(addr, v, mo) #define uatomic_inc_mo(addr, mo) \ uatomic_add_mo(addr, 1, mo) #define uatomic_dec_mo(addr, mo) \ uatomic_sub_mo(addr, 1, mo) #define cmm_smp_mb__before_uatomic_and() cmm_smp_mb() #define cmm_smp_mb__after_uatomic_and() cmm_smp_mb() #define cmm_smp_mb__before_uatomic_or() cmm_smp_mb() #define cmm_smp_mb__after_uatomic_or() cmm_smp_mb() #define cmm_smp_mb__before_uatomic_add() cmm_smp_mb() #define cmm_smp_mb__after_uatomic_add() cmm_smp_mb() #define cmm_smp_mb__before_uatomic_sub() cmm_smp_mb() #define cmm_smp_mb__after_uatomic_sub() cmm_smp_mb() #define cmm_smp_mb__before_uatomic_inc() cmm_smp_mb() #define cmm_smp_mb__after_uatomic_inc() cmm_smp_mb() #define cmm_smp_mb__before_uatomic_dec() cmm_smp_mb() #define cmm_smp_mb__after_uatomic_dec() cmm_smp_mb() #endif /* _URCU_UATOMIC_BUILTINS_GENERIC_H */