| 1 | // SPDX-FileCopyrightText: 2020 Michael Jeanson <mjeanson@efficios.com> |
| 2 | // |
| 3 | // SPDX-License-Identifier: LGPL-2.1-or-later |
| 4 | |
| 5 | #ifndef _URCU_UATOMIC_H |
| 6 | #define _URCU_UATOMIC_H |
| 7 | |
| 8 | #include <assert.h> |
| 9 | |
| 10 | #include <urcu/arch.h> |
| 11 | #include <urcu/config.h> |
| 12 | |
| 13 | enum cmm_memorder { |
| 14 | CMM_RELAXED = 0, |
| 15 | CMM_CONSUME = 1, |
| 16 | CMM_ACQUIRE = 2, |
| 17 | CMM_RELEASE = 3, |
| 18 | CMM_ACQ_REL = 4, |
| 19 | CMM_SEQ_CST = 5, |
| 20 | CMM_SEQ_CST_FENCE = 6, |
| 21 | }; |
| 22 | |
| 23 | #ifdef CONFIG_RCU_USE_ATOMIC_BUILTINS |
| 24 | |
| 25 | /* |
| 26 | * Make sure that CMM_SEQ_CST_FENCE is not equivalent to other memory orders. |
| 27 | */ |
| 28 | # ifdef static_assert |
| 29 | static_assert(CMM_RELAXED == __ATOMIC_RELAXED, ""); |
| 30 | static_assert(CMM_CONSUME == __ATOMIC_CONSUME, ""); |
| 31 | static_assert(CMM_ACQUIRE == __ATOMIC_ACQUIRE, ""); |
| 32 | static_assert(CMM_RELEASE == __ATOMIC_RELEASE, ""); |
| 33 | static_assert(CMM_ACQ_REL == __ATOMIC_ACQ_REL, ""); |
| 34 | static_assert(CMM_SEQ_CST == __ATOMIC_SEQ_CST, ""); |
| 35 | # endif |
| 36 | |
| 37 | /* |
| 38 | * This is not part of the public API. It it used internally to implement the |
| 39 | * CMM_SEQ_CST_FENCE memory order. |
| 40 | * |
| 41 | * NOTE: Using switch here instead of if statement to avoid -Wduplicated-cond |
| 42 | * warning when memory order is conditionally determined. |
| 43 | */ |
| 44 | static inline void cmm_seq_cst_fence_after_atomic(enum cmm_memorder mo) |
| 45 | { |
| 46 | switch (mo) { |
| 47 | case CMM_SEQ_CST_FENCE: |
| 48 | cmm_smp_mb(); |
| 49 | break; |
| 50 | default: |
| 51 | break; |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | #endif |
| 56 | |
| 57 | /* |
| 58 | * This is not part of the public API. It is used internally to convert from the |
| 59 | * CMM memory model to the C11 memory model. |
| 60 | */ |
| 61 | static inline int cmm_to_c11(int mo) |
| 62 | { |
| 63 | if (mo == CMM_SEQ_CST_FENCE) { |
| 64 | return CMM_SEQ_CST; |
| 65 | } |
| 66 | return mo; |
| 67 | } |
| 68 | |
| 69 | #if defined(CONFIG_RCU_USE_ATOMIC_BUILTINS) |
| 70 | #include <urcu/uatomic/builtins.h> |
| 71 | #elif defined(URCU_ARCH_X86) |
| 72 | #include <urcu/uatomic/x86.h> |
| 73 | #elif defined(URCU_ARCH_PPC) |
| 74 | #include <urcu/uatomic/ppc.h> |
| 75 | #elif defined(URCU_ARCH_S390) |
| 76 | #include <urcu/uatomic/s390.h> |
| 77 | #elif defined(URCU_ARCH_SPARC64) |
| 78 | #include <urcu/uatomic/sparc64.h> |
| 79 | #elif defined(URCU_ARCH_ALPHA) |
| 80 | #include <urcu/uatomic/alpha.h> |
| 81 | #elif defined(URCU_ARCH_IA64) |
| 82 | #include <urcu/uatomic/ia64.h> |
| 83 | #elif defined(URCU_ARCH_ARM) |
| 84 | #include <urcu/uatomic/arm.h> |
| 85 | #elif defined(URCU_ARCH_AARCH64) |
| 86 | #include <urcu/uatomic/aarch64.h> |
| 87 | #elif defined(URCU_ARCH_MIPS) |
| 88 | #include <urcu/uatomic/mips.h> |
| 89 | #elif defined(URCU_ARCH_NIOS2) |
| 90 | #include <urcu/uatomic/nios2.h> |
| 91 | #elif defined(URCU_ARCH_TILE) |
| 92 | #include <urcu/uatomic/tile.h> |
| 93 | #elif defined(URCU_ARCH_HPPA) |
| 94 | #include <urcu/uatomic/hppa.h> |
| 95 | #elif defined(URCU_ARCH_M68K) |
| 96 | #include <urcu/uatomic/m68k.h> |
| 97 | #elif defined(URCU_ARCH_RISCV) |
| 98 | #include <urcu/uatomic/riscv.h> |
| 99 | #else |
| 100 | #error "Cannot build: unrecognized architecture, see <urcu/arch.h>." |
| 101 | #endif |
| 102 | |
| 103 | #endif /* _URCU_UATOMIC_H */ |