|
| 1 | +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ |
| 2 | +/* |
| 3 | + * Copyright (c) 2018 Los Alamos National Security, LLC. All rights |
| 4 | + * reserved. |
| 5 | + * $COPYRIGHT$ |
| 6 | + * |
| 7 | + * Additional copyrights may follow |
| 8 | + * |
| 9 | + * $HEADER$ |
| 10 | + */ |
| 11 | + |
| 12 | +/* This file provides shims between the opal atomics interface and the C11 atomics interface. It |
| 13 | + * is intended as the first step in moving to using C11 atomics across the entire codebase. Once |
| 14 | + * all officially supported compilers offer C11 atomic (GCC 4.9.0+, icc 2018+, pgi, xlc, etc) then |
| 15 | + * this shim will go away and the codebase will be updated to use C11's atomic support |
| 16 | + * directly. |
| 17 | + * This shim contains some functions already present in atomic_impl.h because we do not include |
| 18 | + * atomic_impl.h when using C11 atomics. It would require alot of #ifdefs to avoid duplicate |
| 19 | + * definitions to be worthwhile. */ |
| 20 | + |
| 21 | +#if !defined(OPAL_ATOMIC_STDC_H) |
| 22 | +#define OPAL_ATOMIC_STDC_H |
| 23 | + |
| 24 | +#include <stdatomic.h> |
| 25 | +#include <stdint.h> |
| 26 | +#include "opal/include/opal_stdint.h" |
| 27 | + |
| 28 | +#define OPAL_HAVE_ATOMIC_MEM_BARRIER 1 |
| 29 | + |
| 30 | +#define OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_32 1 |
| 31 | +#define OPAL_HAVE_ATOMIC_SWAP_32 1 |
| 32 | + |
| 33 | +#define OPAL_HAVE_ATOMIC_MATH_32 1 |
| 34 | +#define OPAL_HAVE_ATOMIC_ADD_32 1 |
| 35 | +#define OPAL_HAVE_ATOMIC_AND_32 1 |
| 36 | +#define OPAL_HAVE_ATOMIC_OR_32 1 |
| 37 | +#define OPAL_HAVE_ATOMIC_XOR_32 1 |
| 38 | +#define OPAL_HAVE_ATOMIC_SUB_32 1 |
| 39 | + |
| 40 | +#define OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_64 1 |
| 41 | +#define OPAL_HAVE_ATOMIC_SWAP_64 1 |
| 42 | + |
| 43 | +#define OPAL_HAVE_ATOMIC_MATH_64 1 |
| 44 | +#define OPAL_HAVE_ATOMIC_ADD_64 1 |
| 45 | +#define OPAL_HAVE_ATOMIC_AND_64 1 |
| 46 | +#define OPAL_HAVE_ATOMIC_OR_64 1 |
| 47 | +#define OPAL_HAVE_ATOMIC_XOR_64 1 |
| 48 | +#define OPAL_HAVE_ATOMIC_SUB_64 1 |
| 49 | + |
| 50 | +#define OPAL_HAVE_ATOMIC_LLSC_32 0 |
| 51 | +#define OPAL_HAVE_ATOMIC_LLSC_64 0 |
| 52 | +#define OPAL_HAVE_ATOMIC_LLSC_PTR 0 |
| 53 | + |
| 54 | +#define OPAL_HAVE_ATOMIC_MIN_32 1 |
| 55 | +#define OPAL_HAVE_ATOMIC_MAX_32 1 |
| 56 | + |
| 57 | +#define OPAL_HAVE_ATOMIC_MIN_64 1 |
| 58 | +#define OPAL_HAVE_ATOMIC_MAX_64 1 |
| 59 | + |
| 60 | +#define OPAL_HAVE_ATOMIC_SPINLOCKS 1 |
| 61 | + |
| 62 | +static inline void opal_atomic_mb (void) |
| 63 | +{ |
| 64 | + atomic_thread_fence (memory_order_seq_cst); |
| 65 | +} |
| 66 | + |
| 67 | +static inline void opal_atomic_wmb (void) |
| 68 | +{ |
| 69 | + atomic_thread_fence (memory_order_release); |
| 70 | +} |
| 71 | + |
| 72 | +static inline void opal_atomic_rmb (void) |
| 73 | +{ |
| 74 | + atomic_thread_fence (memory_order_acquire); |
| 75 | +} |
| 76 | + |
| 77 | +#define opal_atomic_compare_exchange_strong_32 atomic_compare_exchange_strong |
| 78 | +#define opal_atomic_compare_exchange_strong_64 atomic_compare_exchange_strong |
| 79 | +#define opal_atomic_compare_exchange_strong_ptr atomic_compare_exchange_strong |
| 80 | +#define opal_atomic_compare_exchange_strong_acq_32(addr, compare, value) atomic_compare_exchange_strong_explicit (addr, compare, value, memory_order_acquire, memory_order_relaxed) |
| 81 | +#define opal_atomic_compare_exchange_strong_acq_64(addr, compare, value) atomic_compare_exchange_strong_explicit (addr, compare, value, memory_order_acquire, memory_order_relaxed) |
| 82 | +#define opal_atomic_compare_exchange_strong_acq_ptr(addr, compare, value) atomic_compare_exchange_strong_explicit (addr, compare, value, memory_order_acquire, memory_order_relaxed) |
| 83 | + |
| 84 | +#define opal_atomic_compare_exchange_strong_rel_32(addr, compare, value) atomic_compare_exchange_strong_explicit (addr, compare, value, memory_order_release, memory_order_relaxed) |
| 85 | +#define opal_atomic_compare_exchange_strong_rel_64(addr, compare, value) atomic_compare_exchange_strong_explicit (addr, compare, value, memory_order_release, memory_order_relaxed) |
| 86 | +#define opal_atomic_compare_exchange_strong_rel_ptr(addr, compare, value) atomic_compare_exchange_strong_explicit (addr, compare, value, memory_order_release, memory_order_relaxed) |
| 87 | + |
| 88 | +#define opal_atomic_compare_exchange_strong atomic_compare_exchange_strong |
| 89 | +#define opal_atomic_compare_exchange_strong_acq(addr, oldval, newval) atomic_compare_exchange_strong_explicit (addr, oldval, newval, memory_order_acquire, memory_order_relaxed) |
| 90 | +#define opal_atomic_compare_exchange_strong_rel(addr, oldval, newval) atomic_compare_exchange_strong_explicit (addr, oldval, newval, memory_order_release, memory_order_relaxed) |
| 91 | + |
| 92 | +#define opal_atomic_swap_32 atomic_exchange |
| 93 | +#define opal_atomic_swap_64 atomic_exchange |
| 94 | +#define opal_atomic_swap_ptr atomic_exchange |
| 95 | + |
| 96 | +#define OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(op, bits, type, operator) \ |
| 97 | + static inline type opal_atomic_fetch_ ## op ##_## bits (opal_atomic_ ## type *addr, type value) \ |
| 98 | + { \ |
| 99 | + return atomic_fetch_ ## op (addr, value); \ |
| 100 | + } \ |
| 101 | + \ |
| 102 | + static inline type opal_atomic_## op ## _fetch_ ## bits (opal_atomic_ ## type *addr, type value) \ |
| 103 | + { \ |
| 104 | + return atomic_fetch_ ## op (addr, value) operator value; \ |
| 105 | + } |
| 106 | + |
| 107 | +OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(add, 32, int32_t, +) |
| 108 | +OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(add, 64, int64_t, +) |
| 109 | +OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(add, size_t, size_t, +) |
| 110 | + |
| 111 | +OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(sub, 32, int32_t, -) |
| 112 | +OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(sub, 64, int64_t, -) |
| 113 | +OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(sub, size_t, size_t, -) |
| 114 | + |
| 115 | +OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(or, 32, int32_t, |) |
| 116 | +OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(or, 64, int64_t, |) |
| 117 | + |
| 118 | +OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(xor, 32, int32_t, ^) |
| 119 | +OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(xor, 64, int64_t, ^) |
| 120 | + |
| 121 | +OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(and, 32, int32_t, &) |
| 122 | +OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(and, 64, int64_t, &) |
| 123 | + |
| 124 | +#define opal_atomic_add (void) atomic_fetch_add |
| 125 | + |
| 126 | +static inline int32_t opal_atomic_fetch_min_32 (opal_atomic_int32_t *addr, int32_t value) |
| 127 | +{ |
| 128 | + int32_t old = *addr; |
| 129 | + do { |
| 130 | + if (old <= value) { |
| 131 | + break; |
| 132 | + } |
| 133 | + } while (!opal_atomic_compare_exchange_strong_32 (addr, &old, value)); |
| 134 | + |
| 135 | + return old; |
| 136 | +} |
| 137 | + |
| 138 | +static inline int32_t opal_atomic_fetch_max_32 (opal_atomic_int32_t *addr, int32_t value) |
| 139 | +{ |
| 140 | + int32_t old = *addr; |
| 141 | + do { |
| 142 | + if (old >= value) { |
| 143 | + break; |
| 144 | + } |
| 145 | + } while (!opal_atomic_compare_exchange_strong_32 (addr, &old, value)); |
| 146 | + |
| 147 | + return old; |
| 148 | +} |
| 149 | + |
| 150 | +static inline int64_t opal_atomic_fetch_min_64 (opal_atomic_int64_t *addr, int64_t value) |
| 151 | +{ |
| 152 | + int64_t old = *addr; |
| 153 | + do { |
| 154 | + if (old <= value) { |
| 155 | + break; |
| 156 | + } |
| 157 | + } while (!opal_atomic_compare_exchange_strong_64 (addr, &old, value)); |
| 158 | + |
| 159 | + return old; |
| 160 | +} |
| 161 | + |
| 162 | +static inline int64_t opal_atomic_fetch_max_64 (opal_atomic_int64_t *addr, int64_t value) |
| 163 | +{ |
| 164 | + int64_t old = *addr; |
| 165 | + do { |
| 166 | + if (old >= value) { |
| 167 | + break; |
| 168 | + } |
| 169 | + } while (!opal_atomic_compare_exchange_strong_64 (addr, &old, value)); |
| 170 | + |
| 171 | + return old; |
| 172 | +} |
| 173 | + |
| 174 | +static inline int32_t opal_atomic_min_fetch_32 (opal_atomic_int32_t *addr, int32_t value) |
| 175 | +{ |
| 176 | + int32_t old = opal_atomic_fetch_min_32 (addr, value); |
| 177 | + return old <= value ? old : value; |
| 178 | +} |
| 179 | + |
| 180 | +static inline int32_t opal_atomic_max_fetch_32 (opal_atomic_int32_t *addr, int32_t value) |
| 181 | +{ |
| 182 | + int32_t old = opal_atomic_fetch_max_32 (addr, value); |
| 183 | + return old >= value ? old : value; |
| 184 | +} |
| 185 | + |
| 186 | +static inline int64_t opal_atomic_min_fetch_64 (opal_atomic_int64_t *addr, int64_t value) |
| 187 | +{ |
| 188 | + int64_t old = opal_atomic_fetch_min_64 (addr, value); |
| 189 | + return old <= value ? old : value; |
| 190 | +} |
| 191 | + |
| 192 | +static inline int64_t opal_atomic_max_fetch_64 (opal_atomic_int64_t *addr, int64_t value) |
| 193 | +{ |
| 194 | + int64_t old = opal_atomic_fetch_max_64 (addr, value); |
| 195 | + return old >= value ? old : value; |
| 196 | +} |
| 197 | + |
| 198 | +#define OPAL_ATOMIC_LOCK_UNLOCKED false |
| 199 | +#define OPAL_ATOMIC_LOCK_LOCKED true |
| 200 | + |
| 201 | +#define OPAL_ATOMIC_LOCK_INIT ATOMIC_FLAG_INIT |
| 202 | + |
| 203 | +typedef atomic_flag opal_atomic_lock_t; |
| 204 | + |
| 205 | +/* |
| 206 | + * Lock initialization function. It set the lock to UNLOCKED. |
| 207 | + */ |
| 208 | +static inline void opal_atomic_lock_init (opal_atomic_lock_t *lock, bool value) |
| 209 | +{ |
| 210 | + atomic_flag_clear (lock); |
| 211 | +} |
| 212 | + |
| 213 | + |
| 214 | +static inline int opal_atomic_trylock (opal_atomic_lock_t *lock) |
| 215 | +{ |
| 216 | + return (int) atomic_flag_test_and_set (lock); |
| 217 | +} |
| 218 | + |
| 219 | + |
| 220 | +static inline void opal_atomic_lock(opal_atomic_lock_t *lock) |
| 221 | +{ |
| 222 | + while (opal_atomic_trylock (lock)) { |
| 223 | + } |
| 224 | +} |
| 225 | + |
| 226 | + |
| 227 | +static inline void opal_atomic_unlock (opal_atomic_lock_t *lock) |
| 228 | +{ |
| 229 | + atomic_flag_clear (lock); |
| 230 | +} |
| 231 | + |
| 232 | +/* NTH: will probably have to make this stronger to avoid using a lock-based cmpxchng 128 */ |
| 233 | +#if HAVE_OPAL_INT128_T |
| 234 | + |
| 235 | +#define opal_atomic_compare_exchange_strong_128 atomic_compare_exchange_strong |
| 236 | +#define OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_128 1 |
| 237 | + |
| 238 | +#endif |
| 239 | + |
| 240 | +#endif /* !defined(OPAL_ATOMIC_STDC_H) */ |
0 commit comments