|
| 1 | +/**************************************************************************/ |
| 2 | +/* */ |
| 3 | +/* OCaml */ |
| 4 | +/* */ |
| 5 | +/* KC Sivaramakrishnan, Indian Institute of Technology, Madras */ |
| 6 | +/* Stephen Dolan, University of Cambridge */ |
| 7 | +/* */ |
| 8 | +/* Copyright 2018 Indian Institute of Technology, Madras */ |
| 9 | +/* Copyright 2018 University of Cambridge */ |
| 10 | +/* */ |
| 11 | +/* All rights reserved. This file is distributed under the terms of */ |
| 12 | +/* the GNU Lesser General Public License version 2.1, with the */ |
| 13 | +/* special exception on linking described in the file LICENSE. */ |
| 14 | +/* */ |
| 15 | +/**************************************************************************/ |
| 16 | +#ifndef CAML_ATOMIC_H |
| 17 | +#define CAML_ATOMIC_H |
| 18 | + |
| 19 | +#include "config.h" |
| 20 | + |
| 21 | +/* On platforms supporting C11 atomics, this file just includes <stdatomic.h>. |
| 22 | +
|
| 23 | + On other platforms, this file includes platform-specific stubs for |
| 24 | + the subset of C11 atomics needed by the OCaml runtime |
| 25 | + */ |
| 26 | + |
| 27 | +#ifdef __cplusplus |
| 28 | + |
| 29 | +extern "C++" { |
| 30 | +#include <atomic> |
| 31 | +#define ATOMIC_UINTNAT_INIT(x) (x) |
| 32 | +typedef std::atomic<uintnat> atomic_uintnat; |
| 33 | +typedef std::atomic<intnat> atomic_intnat; |
| 34 | +using std::memory_order_relaxed; |
| 35 | +using std::memory_order_acquire; |
| 36 | +using std::memory_order_release; |
| 37 | +using std::memory_order_acq_rel; |
| 38 | +using std::memory_order_seq_cst; |
| 39 | +} |
| 40 | + |
| 41 | +#elif defined(HAS_STDATOMIC_H) |
| 42 | + |
| 43 | +#include <stdatomic.h> |
| 44 | +#define ATOMIC_UINTNAT_INIT(x) (x) |
| 45 | +typedef _Atomic uintnat atomic_uintnat; |
| 46 | +typedef _Atomic intnat atomic_intnat; |
| 47 | + |
| 48 | +#elif defined(__GNUC__) |
| 49 | + |
| 50 | +/* Support for versions of gcc which have built-in atomics but do not |
| 51 | + expose stdatomic.h (e.g. gcc 4.8) */ |
| 52 | +typedef enum memory_order { |
| 53 | + memory_order_relaxed = __ATOMIC_RELAXED, |
| 54 | + memory_order_acquire = __ATOMIC_ACQUIRE, |
| 55 | + memory_order_release = __ATOMIC_RELEASE, |
| 56 | + memory_order_acq_rel = __ATOMIC_ACQ_REL, |
| 57 | + memory_order_seq_cst = __ATOMIC_SEQ_CST |
| 58 | +} memory_order; |
| 59 | + |
| 60 | +#define ATOMIC_UINTNAT_INIT(x) { (x) } |
| 61 | +typedef struct { uintnat repr; } atomic_uintnat; |
| 62 | +typedef struct { intnat repr; } atomic_intnat; |
| 63 | + |
| 64 | +#define atomic_load_explicit(x, m) __atomic_load_n(&(x)->repr, (m)) |
| 65 | +#define atomic_load(x) atomic_load_explicit((x), memory_order_seq_cst) |
| 66 | +#define atomic_store_explicit(x, v, m) __atomic_store_n(&(x)->repr, (v), (m)) |
| 67 | +#define atomic_store(x, v) atomic_store_explicit((x), (v), memory_order_seq_cst) |
| 68 | +#define atomic_compare_exchange_strong(x, oldv, newv) \ |
| 69 | + __atomic_compare_exchange_n( \ |
| 70 | + &(x)->repr, \ |
| 71 | + (oldv), (newv), 0, \ |
| 72 | + memory_order_seq_cst, memory_order_seq_cst) |
| 73 | +#define atomic_exchange(x, newv) \ |
| 74 | + __atomic_exchange_n(&(x)->repr, (newv), memory_order_seq_cst) |
| 75 | +#define atomic_fetch_add(x, n) \ |
| 76 | + __atomic_fetch_add(&(x)->repr, (n), memory_order_seq_cst) |
| 77 | +#define atomic_fetch_or(x, n) \ |
| 78 | + __atomic_fetch_or(&(x)->repr, (n), memory_order_seq_cst) |
| 79 | +#define atomic_thread_fence __atomic_thread_fence |
| 80 | + |
| 81 | +#else |
| 82 | +#error "C11 atomics are unavailable on this platform. See camlatomic.h" |
| 83 | +#endif |
| 84 | + |
| 85 | +#endif /* CAML_ATOMIC_H */ |
0 commit comments