1 /* 2 * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 /* 8 * @file gcc/atomic.h 9 * @brief GCC specific atomic primitives for libmetal. 10 */ 11 12 #ifndef __METAL_GCC_ATOMIC__H__ 13 #define __METAL_GCC_ATOMIC__H__ 14 15 #ifdef __cplusplus 16 extern "C" { 17 #endif 18 19 typedef int atomic_flag; 20 typedef char atomic_char; 21 typedef unsigned char atomic_uchar; 22 typedef short atomic_short; 23 typedef unsigned short atomic_ushort; 24 typedef int atomic_int; 25 typedef unsigned int atomic_uint; 26 typedef atomic_uint atomic_uintptr_t; 27 typedef long atomic_long; 28 typedef unsigned long atomic_ulong; 29 typedef long long atomic_llong; 30 typedef unsigned long long atomic_ullong; 31 32 #define ATOMIC_FLAG_INIT 0 33 #define ATOMIC_VAR_INIT(VAL) (VAL) 34 35 typedef enum { 36 memory_order_relaxed, 37 memory_order_consume, 38 memory_order_acquire, 39 memory_order_release, 40 memory_order_acq_rel, 41 memory_order_seq_cst, 42 } memory_order; 43 44 #define atomic_flag_test_and_set(FLAG) \ 45 __sync_lock_test_and_set((FLAG), 1) 46 #define atomic_flag_test_and_set_explicit(FLAG, MO) \ 47 atomic_flag_test_and_set(FLAG) 48 #define atomic_flag_clear(FLAG) \ 49 __sync_lock_release((FLAG)) 50 #define atomic_flag_clear_explicit(FLAG, MO) \ 51 atomic_flag_clear(FLAG) 52 #define atomic_init(OBJ, VAL) \ 53 do { *(OBJ) = (VAL); } while (0) 54 #define atomic_is_lock_free(OBJ) \ 55 (sizeof(*(OBJ)) <= sizeof(long)) 56 #define atomic_store(OBJ, VAL) \ 57 do { *(OBJ) = (VAL); __sync_synchronize(); } while (0) 58 #define atomic_store_explicit(OBJ, VAL, MO) \ 59 atomic_store((OBJ), (VAL)) 60 #define atomic_load(OBJ) \ 61 ({ __sync_synchronize(); *(OBJ); }) 62 #define atomic_load_explicit(OBJ, MO) \ 63 atomic_load(OBJ) 64 #define atomic_exchange(OBJ, DES) \ 65 ({ \ 66 __typeof__(OBJ) obj = (OBJ); \ 67 __typeof__(*obj) des = (DES); \ 68 __typeof__(*obj) expval; \ 69 __typeof__(*obj) oldval = atomic_load(obj); \ 70 do { \ 71 expval = oldval; \ 72 oldval = __sync_val_compare_and_swap( \ 73 obj, expval, des); \ 74 } while (oldval != expval); \ 75 oldval; \ 76 }) 77 #define atomic_exchange_explicit(OBJ, DES, MO) \ 78 atomic_exchange((OBJ), (DES)) 79 #define atomic_compare_exchange_strong(OBJ, EXP, DES) \ 80 ({ \ 81 __typeof__(OBJ) obj = (OBJ); \ 82 __typeof__(EXP) exp = (EXP); \ 83 __typeof__(*obj) expval = *exp; \ 84 __typeof__(*obj) oldval = __sync_val_compare_and_swap( \ 85 obj, expval, (DES)); \ 86 *exp = oldval; \ 87 oldval == expval; \ 88 }) 89 #define atomic_compare_exchange_strong_explicit(OBJ, EXP, DES, MO) \ 90 atomic_compare_exchange_strong((OBJ), (EXP), (DES)) 91 #define atomic_compare_exchange_weak(OBJ, EXP, DES) \ 92 atomic_compare_exchange_strong((OBJ), (EXP), (DES)) 93 #define atomic_compare_exchange_weak_explicit(OBJ, EXP, DES, MO) \ 94 atomic_compare_exchange_weak((OBJ), (EXP), (DES)) 95 #define atomic_fetch_add(OBJ, VAL) \ 96 __sync_fetch_and_add((OBJ), (VAL)) 97 #define atomic_fetch_add_explicit(OBJ, VAL, MO) \ 98 atomic_fetch_add((OBJ), (VAL)) 99 #define atomic_fetch_sub(OBJ, VAL) \ 100 __sync_fetch_and_sub((OBJ), (VAL)) 101 #define atomic_fetch_sub_explicit(OBJ, VAL, MO) \ 102 atomic_fetch_sub((OBJ), (VAL)) 103 #define atomic_fetch_or(OBJ, VAL) \ 104 __sync_fetch_and_or((OBJ), (VAL)) 105 #define atomic_fetch_or_explicit(OBJ, VAL, MO) \ 106 atomic_fetch_or((OBJ), (VAL)) 107 #define atomic_fetch_xor(OBJ, VAL) \ 108 __sync_fetch_and_xor((OBJ), (VAL)) 109 #define atomic_fetch_xor_explicit(OBJ, VAL, MO) \ 110 atomic_fetch_xor((OBJ), (VAL)) 111 #define atomic_fetch_and(OBJ, VAL) \ 112 __sync_fetch_and_and((OBJ), (VAL)) 113 #define atomic_fetch_and_explicit(OBJ, VAL, MO) \ 114 atomic_fetch_and((OBJ), (VAL)) 115 #define atomic_thread_fence(MO) \ 116 __sync_synchronize() 117 #define atomic_signal_fence(MO) \ 118 __sync_synchronize() 119 120 #ifdef __cplusplus 121 } 122 #endif 123 124 #endif /* __METAL_GCC_ATOMIC__H__ */ 125