125 lines
3.7 KiB
C
125 lines
3.7 KiB
C
/*
|
|
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
/*
|
|
* @file gcc/atomic.h
|
|
* @brief GCC specific atomic primitives for libmetal.
|
|
*/
|
|
|
|
#ifndef __METAL_GCC_ATOMIC__H__
|
|
#define __METAL_GCC_ATOMIC__H__
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
typedef int atomic_flag;
|
|
typedef char atomic_char;
|
|
typedef unsigned char atomic_uchar;
|
|
typedef short atomic_short;
|
|
typedef unsigned short atomic_ushort;
|
|
typedef int atomic_int;
|
|
typedef unsigned int atomic_uint;
|
|
typedef atomic_uint atomic_uintptr_t;
|
|
typedef long atomic_long;
|
|
typedef unsigned long atomic_ulong;
|
|
typedef long long atomic_llong;
|
|
typedef unsigned long long atomic_ullong;
|
|
|
|
#define ATOMIC_FLAG_INIT 0
|
|
#define ATOMIC_VAR_INIT(VAL) (VAL)
|
|
|
|
typedef enum {
|
|
memory_order_relaxed,
|
|
memory_order_consume,
|
|
memory_order_acquire,
|
|
memory_order_release,
|
|
memory_order_acq_rel,
|
|
memory_order_seq_cst,
|
|
} memory_order;
|
|
|
|
#define atomic_flag_test_and_set(FLAG) \
|
|
__sync_lock_test_and_set((FLAG), 1)
|
|
#define atomic_flag_test_and_set_explicit(FLAG, MO) \
|
|
atomic_flag_test_and_set(FLAG)
|
|
#define atomic_flag_clear(FLAG) \
|
|
__sync_lock_release((FLAG))
|
|
#define atomic_flag_clear_explicit(FLAG, MO) \
|
|
atomic_flag_clear(FLAG)
|
|
#define atomic_init(OBJ, VAL) \
|
|
do { *(OBJ) = (VAL); } while (0)
|
|
#define atomic_is_lock_free(OBJ) \
|
|
(sizeof(*(OBJ)) <= sizeof(long))
|
|
#define atomic_store(OBJ, VAL) \
|
|
do { *(OBJ) = (VAL); __sync_synchronize(); } while (0)
|
|
#define atomic_store_explicit(OBJ, VAL, MO) \
|
|
atomic_store((OBJ), (VAL))
|
|
#define atomic_load(OBJ) \
|
|
({ __sync_synchronize(); *(OBJ); })
|
|
#define atomic_load_explicit(OBJ, MO) \
|
|
atomic_load(OBJ)
|
|
#define atomic_exchange(OBJ, DES) \
|
|
({ \
|
|
__typeof__(OBJ) obj = (OBJ); \
|
|
__typeof__(*obj) des = (DES); \
|
|
__typeof__(*obj) expval; \
|
|
__typeof__(*obj) oldval = atomic_load(obj); \
|
|
do { \
|
|
expval = oldval; \
|
|
oldval = __sync_val_compare_and_swap( \
|
|
obj, expval, des); \
|
|
} while (oldval != expval); \
|
|
oldval; \
|
|
})
|
|
#define atomic_exchange_explicit(OBJ, DES, MO) \
|
|
atomic_exchange((OBJ), (DES))
|
|
#define atomic_compare_exchange_strong(OBJ, EXP, DES) \
|
|
({ \
|
|
__typeof__(OBJ) obj = (OBJ); \
|
|
__typeof__(EXP) exp = (EXP); \
|
|
__typeof__(*obj) expval = *exp; \
|
|
__typeof__(*obj) oldval = __sync_val_compare_and_swap( \
|
|
obj, expval, (DES)); \
|
|
*exp = oldval; \
|
|
oldval == expval; \
|
|
})
|
|
#define atomic_compare_exchange_strong_explicit(OBJ, EXP, DES, MO) \
|
|
atomic_compare_exchange_strong((OBJ), (EXP), (DES))
|
|
#define atomic_compare_exchange_weak(OBJ, EXP, DES) \
|
|
atomic_compare_exchange_strong((OBJ), (EXP), (DES))
|
|
#define atomic_compare_exchange_weak_explicit(OBJ, EXP, DES, MO) \
|
|
atomic_compare_exchange_weak((OBJ), (EXP), (DES))
|
|
#define atomic_fetch_add(OBJ, VAL) \
|
|
__sync_fetch_and_add((OBJ), (VAL))
|
|
#define atomic_fetch_add_explicit(OBJ, VAL, MO) \
|
|
atomic_fetch_add((OBJ), (VAL))
|
|
#define atomic_fetch_sub(OBJ, VAL) \
|
|
__sync_fetch_and_sub((OBJ), (VAL))
|
|
#define atomic_fetch_sub_explicit(OBJ, VAL, MO) \
|
|
atomic_fetch_sub((OBJ), (VAL))
|
|
#define atomic_fetch_or(OBJ, VAL) \
|
|
__sync_fetch_and_or((OBJ), (VAL))
|
|
#define atomic_fetch_or_explicit(OBJ, VAL, MO) \
|
|
atomic_fetch_or((OBJ), (VAL))
|
|
#define atomic_fetch_xor(OBJ, VAL) \
|
|
__sync_fetch_and_xor((OBJ), (VAL))
|
|
#define atomic_fetch_xor_explicit(OBJ, VAL, MO) \
|
|
atomic_fetch_xor((OBJ), (VAL))
|
|
#define atomic_fetch_and(OBJ, VAL) \
|
|
__sync_fetch_and_and((OBJ), (VAL))
|
|
#define atomic_fetch_and_explicit(OBJ, VAL, MO) \
|
|
atomic_fetch_and((OBJ), (VAL))
|
|
#define atomic_thread_fence(MO) \
|
|
__sync_synchronize()
|
|
#define atomic_signal_fence(MO) \
|
|
__sync_synchronize()
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* __METAL_GCC_ATOMIC__H__ */
|