root/opal/mca/pmix/pmix4x/pmix/src/atomics/sys/atomic_stdc.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. pmix_atomic_mb
  2. pmix_atomic_wmb
  3. pmix_atomic_rmb
  4. pmix_atomic_fetch_min_32
  5. pmix_atomic_fetch_max_32
  6. pmix_atomic_fetch_min_64
  7. pmix_atomic_fetch_max_64
  8. pmix_atomic_min_fetch_32
  9. pmix_atomic_max_fetch_32
  10. pmix_atomic_min_fetch_64
  11. pmix_atomic_max_fetch_64
  12. pmix_atomic_lock_init
  13. pmix_atomic_trylock
  14. pmix_atomic_lock
  15. pmix_atomic_unlock
  16. pmix_atomic_compare_exchange_strong_128

   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 (c) 2018      Intel, Inc.  All rights reserved.
   6  * $COPYRIGHT$
   7  *
   8  * Additional copyrights may follow
   9  *
  10  * $HEADER$
  11  */
  12 
  13 /* This file provides shims between the pmix atomics interface and the C11 atomics interface. It
  14  * is intended as the first step in moving to using C11 atomics across the entire codebase. Once
  15  * all officially supported compilers offer C11 atomic (GCC 4.9.0+, icc 2018+, pgi, xlc, etc) then
  16  * this shim will go away and the codebase will be updated to use C11's atomic support
  17  * directly.
  18  * This shim contains some functions already present in atomic_impl.h because we do not include
  19  * atomic_impl.h when using C11 atomics. It would require alot of #ifdefs to avoid duplicate
  20  * definitions to be worthwhile. */
  21 
  22 #if !defined(PMIX_ATOMIC_STDC_H)
  23 #define PMIX_ATOMIC_STDC_H
  24 
  25 #include <stdatomic.h>
  26 #include <stdint.h>
  27 #include "src/include/pmix_stdint.h"
  28 
  29 #define PMIX_HAVE_ATOMIC_MEM_BARRIER 1
  30 
  31 #define PMIX_HAVE_ATOMIC_COMPARE_EXCHANGE_32 1
  32 #define PMIX_HAVE_ATOMIC_SWAP_32 1
  33 
  34 #define PMIX_HAVE_ATOMIC_MATH_32 1
  35 #define PMIX_HAVE_ATOMIC_ADD_32 1
  36 #define PMIX_HAVE_ATOMIC_AND_32 1
  37 #define PMIX_HAVE_ATOMIC_OR_32 1
  38 #define PMIX_HAVE_ATOMIC_XOR_32 1
  39 #define PMIX_HAVE_ATOMIC_SUB_32 1
  40 
  41 #define PMIX_HAVE_ATOMIC_COMPARE_EXCHANGE_64 1
  42 #define PMIX_HAVE_ATOMIC_SWAP_64 1
  43 
  44 #define PMIX_HAVE_ATOMIC_MATH_64 1
  45 #define PMIX_HAVE_ATOMIC_ADD_64 1
  46 #define PMIX_HAVE_ATOMIC_AND_64 1
  47 #define PMIX_HAVE_ATOMIC_OR_64 1
  48 #define PMIX_HAVE_ATOMIC_XOR_64 1
  49 #define PMIX_HAVE_ATOMIC_SUB_64 1
  50 
  51 #define PMIX_HAVE_ATOMIC_LLSC_32 0
  52 #define PMIX_HAVE_ATOMIC_LLSC_64 0
  53 #define PMIX_HAVE_ATOMIC_LLSC_PTR 0
  54 
  55 #define PMIX_HAVE_ATOMIC_MIN_32 1
  56 #define PMIX_HAVE_ATOMIC_MAX_32 1
  57 
  58 #define PMIX_HAVE_ATOMIC_MIN_64 1
  59 #define PMIX_HAVE_ATOMIC_MAX_64 1
  60 
  61 #define PMIX_HAVE_ATOMIC_SPINLOCKS 1
  62 
  63 static inline void pmix_atomic_mb (void)
  64 {
  65     atomic_thread_fence (memory_order_seq_cst);
  66 }
  67 
  68 static inline void pmix_atomic_wmb (void)
  69 {
  70     atomic_thread_fence (memory_order_release);
  71 }
  72 
  73 static inline void pmix_atomic_rmb (void)
  74 {
  75     atomic_thread_fence (memory_order_acquire);
  76 }
  77 
  78 #define pmix_atomic_compare_exchange_strong_32(addr, compare, value) atomic_compare_exchange_strong_explicit (addr, compare, value, memory_order_relaxed, memory_order_relaxed)
  79 #define pmix_atomic_compare_exchange_strong_64(addr, compare, value) atomic_compare_exchange_strong_explicit (addr, compare, value, memory_order_relaxed, memory_order_relaxed)
  80 #define pmix_atomic_compare_exchange_strong_ptr(addr, compare, value) atomic_compare_exchange_strong_explicit (addr, compare, value, memory_order_relaxed, memory_order_relaxed)
  81 #define pmix_atomic_compare_exchange_strong_acq_32(addr, compare, value) atomic_compare_exchange_strong_explicit (addr, compare, value, memory_order_acquire, memory_order_relaxed)
  82 #define pmix_atomic_compare_exchange_strong_acq_64(addr, compare, value) atomic_compare_exchange_strong_explicit (addr, compare, value, memory_order_acquire, memory_order_relaxed)
  83 #define pmix_atomic_compare_exchange_strong_acq_ptr(addr, compare, value) atomic_compare_exchange_strong_explicit (addr, compare, value, memory_order_acquire, memory_order_relaxed)
  84 
  85 #define pmix_atomic_compare_exchange_strong_rel_32(addr, compare, value) atomic_compare_exchange_strong_explicit (addr, compare, value, memory_order_release, memory_order_relaxed)
  86 #define pmix_atomic_compare_exchange_strong_rel_64(addr, compare, value) atomic_compare_exchange_strong_explicit (addr, compare, value, memory_order_release, memory_order_relaxed)
  87 #define pmix_atomic_compare_exchange_strong_rel_ptr(addr, compare, value) atomic_compare_exchange_strong_explicit (addr, compare, value, memory_order_release, memory_order_relaxed)
  88 
  89 #define pmix_atomic_compare_exchange_strong(addr, oldval, newval) atomic_compare_exchange_strong_explicit (addr, oldval, newval, memory_order_relaxed, memory_order_relaxed)
  90 #define pmix_atomic_compare_exchange_strong_acq(addr, oldval, newval)  atomic_compare_exchange_strong_explicit (addr, oldval, newval, memory_order_acquire, memory_order_relaxed)
  91 #define pmix_atomic_compare_exchange_strong_rel(addr, oldval, newval)  atomic_compare_exchange_strong_explicit (addr, oldval, newval, memory_order_release, memory_order_relaxed)
  92 
  93 #define pmix_atomic_swap_32(addr, value) atomic_exchange_explicit (addr, value, memory_order_relaxed)
  94 #define pmix_atomic_swap_64(addr, value) atomic_exchange_explicit (addr, value, memory_order_relaxed)
  95 #define pmix_atomic_swap_ptr(addr, value) atomic_exchange_explicit (addr, value, memory_order_relaxed)
  96 
  97 #define PMIX_ATOMIC_STDC_DEFINE_FETCH_OP(op, bits, type, operator)      \
  98     static inline type pmix_atomic_fetch_ ## op ##_## bits (pmix_atomic_ ## type *addr, type value) \
  99     {                                                                   \
 100         return atomic_fetch_ ## op ## _explicit (addr, value, memory_order_relaxed); \
 101     }                                                                   \
 102                                                                         \
 103     static inline type pmix_atomic_## op ## _fetch_ ## bits (pmix_atomic_ ## type *addr, type value) \
 104     {                                                                   \
 105         return atomic_fetch_ ## op ## _explicit (addr, value, memory_order_relaxed) operator value; \
 106     }
 107 
 108 PMIX_ATOMIC_STDC_DEFINE_FETCH_OP(add, 32, int32_t, +)
 109 PMIX_ATOMIC_STDC_DEFINE_FETCH_OP(add, 64, int64_t, +)
 110 PMIX_ATOMIC_STDC_DEFINE_FETCH_OP(add, size_t, size_t, +)
 111 
 112 PMIX_ATOMIC_STDC_DEFINE_FETCH_OP(sub, 32, int32_t, -)
 113 PMIX_ATOMIC_STDC_DEFINE_FETCH_OP(sub, 64, int64_t, -)
 114 PMIX_ATOMIC_STDC_DEFINE_FETCH_OP(sub, size_t, size_t, -)
 115 
 116 PMIX_ATOMIC_STDC_DEFINE_FETCH_OP(or, 32, int32_t, |)
 117 PMIX_ATOMIC_STDC_DEFINE_FETCH_OP(or, 64, int64_t, |)
 118 
 119 PMIX_ATOMIC_STDC_DEFINE_FETCH_OP(xor, 32, int32_t, ^)
 120 PMIX_ATOMIC_STDC_DEFINE_FETCH_OP(xor, 64, int64_t, ^)
 121 
 122 PMIX_ATOMIC_STDC_DEFINE_FETCH_OP(and, 32, int32_t, &)
 123 PMIX_ATOMIC_STDC_DEFINE_FETCH_OP(and, 64, int64_t, &)
 124 
 125 #define pmix_atomic_add(addr, value) (void) atomic_fetch_add_explicit (addr, value, memory_order_relaxed)
 126 
 127 static inline int32_t pmix_atomic_fetch_min_32 (pmix_atomic_int32_t *addr, int32_t value)
 128 {
 129     int32_t old = *addr;
 130     do {
 131         if (old <= value) {
 132             break;
 133         }
 134     } while (!pmix_atomic_compare_exchange_strong_32 (addr, &old, value));
 135 
 136     return old;
 137 }
 138 
 139 static inline int32_t pmix_atomic_fetch_max_32 (pmix_atomic_int32_t *addr, int32_t value)
 140 {
 141     int32_t old = *addr;
 142     do {
 143         if (old >= value) {
 144             break;
 145         }
 146     } while (!pmix_atomic_compare_exchange_strong_32 (addr, &old, value));
 147 
 148     return old;
 149 }
 150 
 151 static inline int64_t pmix_atomic_fetch_min_64 (pmix_atomic_int64_t *addr, int64_t value)
 152 {
 153     int64_t old = *addr;
 154     do {
 155         if (old <= value) {
 156             break;
 157         }
 158     } while (!pmix_atomic_compare_exchange_strong_64 (addr, &old, value));
 159 
 160     return old;
 161 }
 162 
 163 static inline int64_t pmix_atomic_fetch_max_64 (pmix_atomic_int64_t *addr, int64_t value)
 164 {
 165     int64_t old = *addr;
 166     do {
 167         if (old >= value) {
 168             break;
 169         }
 170     } while (!pmix_atomic_compare_exchange_strong_64 (addr, &old, value));
 171 
 172     return old;
 173 }
 174 
 175 static inline int32_t pmix_atomic_min_fetch_32 (pmix_atomic_int32_t *addr, int32_t value)
 176 {
 177     int32_t old = pmix_atomic_fetch_min_32 (addr, value);
 178     return old <= value ? old : value;
 179 }
 180 
 181 static inline int32_t pmix_atomic_max_fetch_32 (pmix_atomic_int32_t *addr, int32_t value)
 182 {
 183     int32_t old = pmix_atomic_fetch_max_32 (addr, value);
 184     return old >= value ? old : value;
 185 }
 186 
 187 static inline int64_t pmix_atomic_min_fetch_64 (pmix_atomic_int64_t *addr, int64_t value)
 188 {
 189     int64_t old = pmix_atomic_fetch_min_64 (addr, value);
 190     return old <= value ? old : value;
 191 }
 192 
 193 static inline int64_t pmix_atomic_max_fetch_64 (pmix_atomic_int64_t *addr, int64_t value)
 194 {
 195     int64_t old = pmix_atomic_fetch_max_64 (addr, value);
 196     return old >= value ? old : value;
 197 }
 198 
 199 #define PMIX_ATOMIC_LOCK_UNLOCKED false
 200 #define PMIX_ATOMIC_LOCK_LOCKED true
 201 
 202 #define PMIX_ATOMIC_LOCK_INIT ATOMIC_FLAG_INIT
 203 
 204 typedef atomic_flag pmix_atomic_lock_t;
 205 
 206 /*
 207  * Lock initialization function. It set the lock to UNLOCKED.
 208  */
 209 static inline void pmix_atomic_lock_init (pmix_atomic_lock_t *lock, bool value)
 210 {
 211     atomic_flag_clear (lock);
 212 }
 213 
 214 
 215 static inline int pmix_atomic_trylock (pmix_atomic_lock_t *lock)
 216 {
 217     return (int) atomic_flag_test_and_set (lock);
 218 }
 219 
 220 
 221 static inline void pmix_atomic_lock(pmix_atomic_lock_t *lock)
 222 {
 223     while (pmix_atomic_trylock (lock)) {
 224     }
 225 }
 226 
 227 
 228 static inline void pmix_atomic_unlock (pmix_atomic_lock_t *lock)
 229 {
 230     atomic_flag_clear (lock);
 231 }
 232 
 233 
 234 #if PMIX_HAVE_C11_CSWAP_INT128
 235 
 236 /* the C11 atomic compare-exchange is lock free so use it */
 237 #define pmix_atomic_compare_exchange_strong_128 atomic_compare_exchange_strong
 238 
 239 #define PMIX_HAVE_ATOMIC_COMPARE_EXCHANGE_128 1
 240 
 241 #elif PMIX_HAVE_SYNC_BUILTIN_CSWAP_INT128
 242 
 243 /* fall back on the __sync builtin if available since it will emit the expected instruction on x86_64 (cmpxchng16b) */
 244 __pmix_attribute_always_inline__
 245 static inline bool pmix_atomic_compare_exchange_strong_128 (pmix_atomic_int128_t *addr,
 246                                                             pmix_int128_t *oldval, pmix_int128_t newval)
 247 {
 248     pmix_int128_t prev = __sync_val_compare_and_swap (addr, *oldval, newval);
 249     bool ret = prev == *oldval;
 250     *oldval = prev;
 251     return ret;
 252 }
 253 
 254 #define PMIX_HAVE_ATOMIC_COMPARE_EXCHANGE_128 1
 255 
 256 #else
 257 
 258 #define PMIX_HAVE_ATOMIC_COMPARE_EXCHANGE_128 0
 259 
 260 #endif
 261 
 262 #endif /* !defined(PMIX_ATOMIC_STDC_H) */

/* [<][>][^][v][top][bottom][index][help] */