diff options
Diffstat (limited to 'cpukit/include/rtems/score/atomic.h')
-rw-r--r-- | cpukit/include/rtems/score/atomic.h | 962 |
1 files changed, 888 insertions, 74 deletions
diff --git a/cpukit/include/rtems/score/atomic.h b/cpukit/include/rtems/score/atomic.h index 161b0ec03e..9ef1779e60 100644 --- a/cpukit/include/rtems/score/atomic.h +++ b/cpukit/include/rtems/score/atomic.h @@ -10,6 +10,7 @@ */ /* + * Copyright (C) 2015 embedded brains GmbH & Co. KG * COPYRIGHT (c) 2012-2013 Deng Hengyi. * * Redistribution and use in source and binary forms, with or without @@ -37,7 +38,7 @@ #ifndef _RTEMS_SCORE_ATOMIC_H #define _RTEMS_SCORE_ATOMIC_H -#include <rtems/score/cpuatomic.h> +#include <rtems/score/basedefs.h> /** * @defgroup RTEMSScoreAtomic Atomic Operations @@ -54,122 +55,935 @@ * @{ */ -typedef CPU_atomic_Uint Atomic_Uint; +#ifdef RTEMS_SMP + #if defined(__cplusplus) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) + /* + * The GCC 4.9 ships its own <stdatomic.h> which is not C++ compatible. The + * suggested solution was to include <atomic> in case C++ is used. This works + * at least with GCC 4.9. See also: + * + * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60932 + * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60940 + */ + #include <atomic> + #define _RTEMS_SCORE_ATOMIC_USE_ATOMIC + #else + #include <stdatomic.h> + #define _RTEMS_SCORE_ATOMIC_USE_STDATOMIC + #endif +#else + #include <rtems/score/isrlevel.h> +#endif -typedef CPU_atomic_Ulong Atomic_Ulong; +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) -typedef CPU_atomic_Uintptr Atomic_Uintptr; +typedef std::atomic_uint Atomic_Uint; -typedef CPU_atomic_Flag Atomic_Flag; +typedef std::atomic_ulong Atomic_Ulong; -typedef CPU_atomic_Order Atomic_Order; +typedef std::atomic_uintptr_t Atomic_Uintptr; -#define ATOMIC_ORDER_RELAXED CPU_ATOMIC_ORDER_RELAXED +typedef std::atomic_flag Atomic_Flag; -#define ATOMIC_ORDER_ACQUIRE CPU_ATOMIC_ORDER_ACQUIRE +typedef std::memory_order Atomic_Order; -#define ATOMIC_ORDER_RELEASE CPU_ATOMIC_ORDER_RELEASE +#define ATOMIC_ORDER_RELAXED std::memory_order_relaxed -#define ATOMIC_ORDER_ACQ_REL CPU_ATOMIC_ORDER_ACQ_REL +#define ATOMIC_ORDER_ACQUIRE std::memory_order_acquire -#define ATOMIC_ORDER_SEQ_CST CPU_ATOMIC_ORDER_SEQ_CST +#define ATOMIC_ORDER_RELEASE std::memory_order_release -#define ATOMIC_INITIALIZER_UINT( value ) CPU_ATOMIC_INITIALIZER_UINT( value ) +#define ATOMIC_ORDER_ACQ_REL std::memory_order_acq_rel -#define ATOMIC_INITIALIZER_ULONG( value ) CPU_ATOMIC_INITIALIZER_ULONG( value ) +#define ATOMIC_ORDER_SEQ_CST std::memory_order_seq_cst -#define ATOMIC_INITIALIZER_UINTPTR( value ) CPU_ATOMIC_INITIALIZER_UINTPTR( value ) +#define ATOMIC_INITIALIZER_UINT( value ) ATOMIC_VAR_INIT( value ) -#define ATOMIC_INITIALIZER_FLAG CPU_ATOMIC_INITIALIZER_FLAG +#define ATOMIC_INITIALIZER_ULONG( value ) ATOMIC_VAR_INIT( value ) -#define _Atomic_Fence( order ) _CPU_atomic_Fence( order ) +#define ATOMIC_INITIALIZER_UINTPTR( value ) ATOMIC_VAR_INIT( value ) -#define _Atomic_Init_uint( obj, desired ) \ - _CPU_atomic_Init_uint( obj, desired ) +#define ATOMIC_INITIALIZER_FLAG ATOMIC_FLAG_INIT -#define _Atomic_Init_ulong( obj, desired ) \ - _CPU_atomic_Init_ulong( obj, desired ) +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) -#define _Atomic_Init_uintptr( obj, desired ) \ - _CPU_atomic_Init_uintptr( obj, desired ) +typedef atomic_uint Atomic_Uint; -#define _Atomic_Load_uint( obj, order ) \ - _CPU_atomic_Load_uint( obj, order ) +typedef atomic_ulong Atomic_Ulong; -#define _Atomic_Load_ulong( obj, order ) \ - _CPU_atomic_Load_ulong( obj, order ) +typedef atomic_uintptr_t Atomic_Uintptr; -#define _Atomic_Load_uintptr( obj, order ) \ - _CPU_atomic_Load_uintptr( obj, order ) +typedef atomic_flag Atomic_Flag; -#define _Atomic_Store_uint( obj, desr, order ) \ - _CPU_atomic_Store_uint( obj, desr, order ) +typedef memory_order Atomic_Order; -#define _Atomic_Store_ulong( obj, desr, order ) \ - _CPU_atomic_Store_ulong( obj, desr, order ) +#define ATOMIC_ORDER_RELAXED memory_order_relaxed -#define _Atomic_Store_uintptr( obj, desr, order ) \ - _CPU_atomic_Store_uintptr( obj, desr, order ) +#define ATOMIC_ORDER_ACQUIRE memory_order_acquire -#define _Atomic_Fetch_add_uint( obj, arg, order ) \ - _CPU_atomic_Fetch_add_uint( obj, arg, order ) +#define ATOMIC_ORDER_RELEASE memory_order_release -#define _Atomic_Fetch_add_ulong( obj, arg, order ) \ - _CPU_atomic_Fetch_add_ulong( obj, arg, order ) +#define ATOMIC_ORDER_ACQ_REL memory_order_acq_rel -#define _Atomic_Fetch_add_uintptr( obj, arg, order ) \ - _CPU_atomic_Fetch_add_uintptr( obj, arg, order ) +#define ATOMIC_ORDER_SEQ_CST memory_order_seq_cst -#define _Atomic_Fetch_sub_uint( obj, arg, order ) \ - _CPU_atomic_Fetch_sub_uint( obj, arg, order ) +#define ATOMIC_INITIALIZER_UINT( value ) ATOMIC_VAR_INIT( value ) -#define _Atomic_Fetch_sub_ulong( obj, arg, order ) \ - _CPU_atomic_Fetch_sub_ulong( obj, arg, order ) +#define ATOMIC_INITIALIZER_ULONG( value ) ATOMIC_VAR_INIT( value ) -#define _Atomic_Fetch_sub_uintptr( obj, arg, order ) \ - _CPU_atomic_Fetch_sub_uintptr( obj, arg, order ) +#define ATOMIC_INITIALIZER_UINTPTR( value ) ATOMIC_VAR_INIT( value ) -#define _Atomic_Fetch_or_uint( obj, arg, order ) \ - _CPU_atomic_Fetch_or_uint( obj, arg, order ) +#define ATOMIC_INITIALIZER_FLAG ATOMIC_FLAG_INIT -#define _Atomic_Fetch_or_ulong( obj, arg, order ) \ - _CPU_atomic_Fetch_or_ulong( obj, arg, order ) +#else -#define _Atomic_Fetch_or_uintptr( obj, arg, order ) \ - _CPU_atomic_Fetch_or_uintptr( obj, arg, order ) +typedef unsigned int Atomic_Uint; -#define _Atomic_Fetch_and_uint( obj, arg, order ) \ - _CPU_atomic_Fetch_and_uint( obj, arg, order ) +typedef unsigned long Atomic_Ulong; -#define _Atomic_Fetch_and_ulong( obj, arg, order ) \ - _CPU_atomic_Fetch_and_ulong( obj, arg, order ) +typedef uintptr_t Atomic_Uintptr; -#define _Atomic_Fetch_and_uintptr( obj, arg, order ) \ - _CPU_atomic_Fetch_and_uintptr( obj, arg, order ) +typedef bool Atomic_Flag; -#define _Atomic_Exchange_uint( obj, desr, order ) \ - _CPU_atomic_Exchange_uint( obj, desr, order ) +typedef int Atomic_Order; -#define _Atomic_Exchange_ulong( obj, desr, order ) \ - _CPU_atomic_Exchange_ulong( obj, desr, order ) +#define ATOMIC_ORDER_RELAXED 0 -#define _Atomic_Exchange_uintptr( obj, desr, order ) \ - _CPU_atomic_Exchange_uintptr( obj, desr, order ) +#define ATOMIC_ORDER_ACQUIRE 2 -#define _Atomic_Compare_exchange_uint( obj, expected, desired, succ, fail ) \ - _CPU_atomic_Compare_exchange_uint( obj, expected, desired, succ, fail ) +#define ATOMIC_ORDER_RELEASE 3 -#define _Atomic_Compare_exchange_ulong( obj, expected, desired, succ, fail ) \ - _CPU_atomic_Compare_exchange_ulong( obj, expected, desired, succ, fail ) +#define ATOMIC_ORDER_ACQ_REL 4 -#define _Atomic_Compare_exchange_uintptr( obj, expected, desired, succ, fail ) \ - _CPU_atomic_Compare_exchange_uintptr( obj, expected, desired, succ, fail ) +#define ATOMIC_ORDER_SEQ_CST 5 -#define _Atomic_Flag_clear( obj, order ) \ - _CPU_atomic_Flag_clear( obj, order ) +#define ATOMIC_INITIALIZER_UINT( value ) ( value ) -#define _Atomic_Flag_test_and_set( obj, order ) \ - _CPU_atomic_Flag_test_and_set( obj, order ) +#define ATOMIC_INITIALIZER_ULONG( value ) ( value ) + +#define ATOMIC_INITIALIZER_UINTPTR( value ) ( value ) + +#define ATOMIC_INITIALIZER_FLAG false + +#endif + +/** + * @brief Sets up a cpu fence. + * + * @param[out] order The order for the fence. + */ +static inline void _Atomic_Fence( Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + std::atomic_thread_fence( order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + atomic_thread_fence( order ); +#else + (void) order; + RTEMS_COMPILER_MEMORY_BARRIER(); +#endif +} + +/** + * @brief Initializes Uint. + * + * @param[out] obj The CPU atomic Uint to initialize. + * @param desired The desired value for @a obj. + */ +static inline void _Atomic_Init_uint( Atomic_Uint *obj, unsigned int desired ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + obj->store( desired ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + atomic_init( obj, desired ); +#else + *obj = desired; +#endif +} + +/** + * @brief Initializes Ulong. + * + * @param[out] obj The CPU atomic Ulong to initialize. + * @param desired The desired value for @a obj. + */ +static inline void _Atomic_Init_ulong( Atomic_Ulong *obj, unsigned long desired ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + obj->store( desired ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + atomic_init( obj, desired ); +#else + *obj = desired; +#endif +} + +/** + * @brief Initializes Uintptr. + * + * @param[out] obj The CPU atomic Uintptr to initialize. + * @param desired The desired value for @a obj. + */ +static inline void _Atomic_Init_uintptr( Atomic_Uintptr *obj, uintptr_t desired ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + obj->store( desired ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + atomic_init( obj, desired ); +#else + *obj = desired; +#endif +} + +/** + * @brief Loads value of Uint considering the order. + * + * @param obj The CPU atomic Uint to get the value from. + * @param order The atomic order for getting the value. + * + * @return The value of @a obj considering the @a order. + */ +static inline unsigned int _Atomic_Load_uint( const Atomic_Uint *obj, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->load( order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_load_explicit( obj, order ); +#else + unsigned int val; + + (void) order; + val = *obj; + RTEMS_COMPILER_MEMORY_BARRIER(); + + return val; +#endif +} + +/** + * @brief Loads value of Ulong considering the order. + * + * @param obj The CPU atomic Ulong to get the value from. + * @param order The atomic order for getting the value. + * + * @return The value of @a obj considering the @a order. + */ +static inline unsigned long _Atomic_Load_ulong( const Atomic_Ulong *obj, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->load( order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_load_explicit( obj, order ); +#else + unsigned long val; + + (void) order; + val = *obj; + RTEMS_COMPILER_MEMORY_BARRIER(); + + return val; +#endif +} + +/** + * @brief Loads value of Uintptr considering the order. + * + * @param obj The CPU atomic Uintptr to get the value from. + * @param order The atomic order for getting the value. + * + * @return The value of @a obj considering the @a order. + */ +static inline uintptr_t _Atomic_Load_uintptr( const Atomic_Uintptr *obj, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->load( order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_load_explicit( obj, order ); +#else + uintptr_t val; + + (void) order; + val = *obj; + RTEMS_COMPILER_MEMORY_BARRIER(); + + return val; +#endif +} + +/** + * @brief Stores a value to Uint considering the order. + * + * @param[out] obj The CPU atomic Uint to store a value in. + * @param desired The desired value for @a obj. + * @param order The atomic order for storing the value. + */ +static inline void _Atomic_Store_uint( Atomic_Uint *obj, unsigned int desired, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + obj->store( desired, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + atomic_store_explicit( obj, desired, order ); +#else + (void) order; + RTEMS_COMPILER_MEMORY_BARRIER(); + *obj = desired; +#endif +} + +/** + * @brief Stores a value to Ulong considering the order. + * + * @param[out] obj The CPU atomic Ulong to store a value in. + * @param desired The desired value for @a obj. + * @param order The atomic order for storing the value. + */ +static inline void _Atomic_Store_ulong( Atomic_Ulong *obj, unsigned long desired, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + obj->store( desired, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + atomic_store_explicit( obj, desired, order ); +#else + (void) order; + RTEMS_COMPILER_MEMORY_BARRIER(); + *obj = desired; +#endif +} + +/** + * @brief Stores a value to Uintptr considering the order. + * + * @param[out] obj The CPU atomic Uintptr to store a value in. + * @param desired The desired value for @a obj. + * @param order The atomic order for storing the value. + */ +static inline void _Atomic_Store_uintptr( Atomic_Uintptr *obj, uintptr_t desired, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + obj->store( desired, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + atomic_store_explicit( obj, desired, order ); +#else + (void) order; + RTEMS_COMPILER_MEMORY_BARRIER(); + *obj = desired; +#endif +} + +/** + * @brief Fetches current value of Uint and adds a value to the stored value. + * + * @param[in, out] obj The CPU atomic Uint to get the value from and add @a arg to. + * @param arg The value to add to @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the addition of @a arg. + */ +static inline unsigned int _Atomic_Fetch_add_uint( Atomic_Uint *obj, unsigned int arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_add( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_add_explicit( obj, arg, order ); +#else + unsigned int val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val + arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Ulong and adds a value to the stored value. + * + * @param[in, out] obj The CPU atomic Ulong to get the value from and add @a arg to. + * @param arg The value to add to @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the addition of @a arg. + */ +static inline unsigned long _Atomic_Fetch_add_ulong( Atomic_Ulong *obj, unsigned long arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_add( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_add_explicit( obj, arg, order ); +#else + unsigned long val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val + arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Uintptr and adds a value to the stored value. + * + * @param[in, out] obj The CPU atomic Uintptr to get the value from and add @a arg to. + * @param arg The value to add to @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the addition of @a arg. + */ +static inline uintptr_t _Atomic_Fetch_add_uintptr( Atomic_Uintptr *obj, uintptr_t arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_add( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_add_explicit( obj, arg, order ); +#else + uintptr_t val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val + arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Uint and subtracts a value from the stored value. + * + * @param[in, out] obj The CPU atomic Uint to get the value from and subtract @a arg from. + * @param arg The value to subtract from @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the subtraction of @a arg. + */ +static inline unsigned int _Atomic_Fetch_sub_uint( Atomic_Uint *obj, unsigned int arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_sub( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_sub_explicit( obj, arg, order ); +#else + unsigned int val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val - arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Ulong and subtracts a value from the stored value. + * + * @param[in, out] obj The CPU atomic Ulong to get the value from and subtract @a arg from. + * @param arg The value to subtract from @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the subtraction of @a arg. + */ +static inline unsigned long _Atomic_Fetch_sub_ulong( Atomic_Ulong *obj, unsigned long arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_sub( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_sub_explicit( obj, arg, order ); +#else + unsigned long val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val - arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Uintptr and subtracts a value from the stored value. + * + * @param[in, out] obj The CPU atomic Uintptr to get the value from and subtract @a arg from. + * @param arg The value to subtract from @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the subtraction of @a arg. + */ +static inline uintptr_t _Atomic_Fetch_sub_uintptr( Atomic_Uintptr *obj, uintptr_t arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_sub( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_sub_explicit( obj, arg, order ); +#else + uintptr_t val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val - arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Uint and ORs a value with the stored value. + * + * @param[in, out] obj The CPU atomic Uint to get the value from and OR @a arg to. + * @param arg The value to OR with @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the OR operation with @a arg. + */ +static inline unsigned int _Atomic_Fetch_or_uint( Atomic_Uint *obj, unsigned int arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_or( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_or_explicit( obj, arg, order ); +#else + unsigned int val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val | arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Ulong and ORs a value with the stored value. + * + * @param[in, out] obj The CPU atomic Ulong to get the value from and OR @a arg to. + * @param arg The value to OR with @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the OR operation with @a arg. + */ +static inline unsigned long _Atomic_Fetch_or_ulong( Atomic_Ulong *obj, unsigned long arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_or( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_or_explicit( obj, arg, order ); +#else + unsigned long val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val | arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Uintptr and ORs a value with the stored value. + * + * @param[in, out] obj The CPU atomic Uintptr to get the value from and OR @a arg to. + * @param arg The value to OR with @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the OR operation with @a arg. + */ +static inline uintptr_t _Atomic_Fetch_or_uintptr( Atomic_Uintptr *obj, uintptr_t arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_or( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_or_explicit( obj, arg, order ); +#else + uintptr_t val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val | arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Uint and ANDs a value with the stored value. + * + * @param[in, out] obj The CPU atomic Uint to get the value from and AND @a arg to. + * @param arg The value to AND with @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the AND operation with @a arg. + */ +static inline unsigned int _Atomic_Fetch_and_uint( Atomic_Uint *obj, unsigned int arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_and( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_and_explicit( obj, arg, order ); +#else + unsigned int val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val & arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Ulong and ANDs a value with the stored value. + * + * @param[in, out] obj The CPU atomic Ulong to get the value from and AND @a arg to. + * @param arg The value to AND with @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the AND operation with @a arg. + */ +static inline unsigned long _Atomic_Fetch_and_ulong( Atomic_Ulong *obj, unsigned long arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_and( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_and_explicit( obj, arg, order ); +#else + unsigned long val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val & arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Uintptr and ANDs a value with the stored value. + * + * @param[in, out] obj The CPU atomic Uintptr to get the value from and AND @a arg to. + * @param arg The value to AND with @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the AND operation with @a arg. + */ +static inline uintptr_t _Atomic_Fetch_and_uintptr( Atomic_Uintptr *obj, uintptr_t arg, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->fetch_and( arg, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_fetch_and_explicit( obj, arg, order ); +#else + uintptr_t val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = val & arg; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Uint and sets its value. + * + * @param[in, out] obj The CPU atomic Uint to get the value from and set the value to @a desired. + * @param arg The value to set for @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the exchange with @a desired. + */ +static inline unsigned int _Atomic_Exchange_uint( Atomic_Uint *obj, unsigned int desired, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->exchange( desired, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_exchange_explicit( obj, desired, order ); +#else + unsigned int val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = desired; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Ulong and sets its value. + * + * @param[in, out] obj The CPU atomic Ulong to get the value from and set the value to @a desired. + * @param arg The value to set for @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the exchange with @a desired. + */ +static inline unsigned long _Atomic_Exchange_ulong( Atomic_Ulong *obj, unsigned long desired, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->exchange( desired, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_exchange_explicit( obj, desired, order ); +#else + unsigned long val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = desired; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Fetches current value of Uintptr and sets its value. + * + * @param[in, out] obj The CPU atomic Uintptr to get the value from and set the value to @a desired. + * @param arg The value to set for @a obj. + * @param order The atomic order for the operation. + * + * @return The value of @a obj prior to the exchange with @a desired. + */ +static inline uintptr_t _Atomic_Exchange_uintptr( Atomic_Uintptr *obj, uintptr_t desired, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->exchange( desired, order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_exchange_explicit( obj, desired, order ); +#else + uintptr_t val; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + val = *obj; + *obj = desired; + _ISR_Local_enable( level ); + + return val; +#endif +} + +/** + * @brief Checks if value of Uint is as expected. + * + * This method checks if the value of @a obj is equal to the value of @a expected. If + * this is the case, the value of @a obj is changed to @a desired. Otherwise, the value + * of @a obj is changed to @a expected. + * + * @param[in, out] obj The CPU atomic Uint to operate upon. + * @param[in, out] expected The expected value of @a obj. If @a obj has a different + * value, @a expected is changed to the actual value of @a obj. + * @param desired The new value of @a obj if the old value of @a obj was as expected. + * @param succ The order if it is successful. + * @param fail The order if it fails. + * + * @retval true The old value of @a obj was as expected. + * @retval false The old value of @a obj was not as expected. + */ +static inline bool _Atomic_Compare_exchange_uint( Atomic_Uint *obj, unsigned int *expected, unsigned int desired, Atomic_Order succ, Atomic_Order fail ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->compare_exchange_strong( *expected, desired, succ, fail ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_compare_exchange_strong_explicit( obj, expected, desired, succ, fail ); +#else + bool success; + ISR_Level level; + unsigned int actual; + + (void) succ; + (void) fail; + _ISR_Local_disable( level ); + actual = *obj; + success = ( actual == *expected ); + if ( success ) { + *obj = desired; + } else { + *expected = actual; + } + _ISR_Local_enable( level ); + + return success; +#endif +} + +/** + * @brief Checks if value of Ulong is as expected. + * + * This method checks if the value of @a obj is equal to the value of @a expected. If + * this is the case, the value of @a obj is changed to @a desired. Otherwise, the value + * of @a obj is changed to @a expected. + * + * @param[in, out] obj The CPU atomic Ulong to operate upon. + * @param[in, out] expected The expected value of @a obj. If @a obj has a different + * value, @a expected is changed to the actual value of @a obj. + * @param desired The new value of @a obj if the old value of @a obj was as expected. + * @param succ The order if it is successful. + * @param fail The order if it fails. + * + * @retval true The old value of @a obj was as expected. + * @retval false The old value of @a obj was not as expected. + */ +static inline bool _Atomic_Compare_exchange_ulong( Atomic_Ulong *obj, unsigned long *expected, unsigned long desired, Atomic_Order succ, Atomic_Order fail ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->compare_exchange_strong( *expected, desired, succ, fail ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_compare_exchange_strong_explicit( obj, expected, desired, succ, fail ); +#else + bool success; + ISR_Level level; + unsigned long actual; + + (void) succ; + (void) fail; + _ISR_Local_disable( level ); + actual = *obj; + success = ( actual == *expected ); + if ( success ) { + *obj = desired; + } else { + *expected = actual; + } + _ISR_Local_enable( level ); + + return success; +#endif +} + +/** + * @brief Checks if value of Uintptr is as expected. + * + * This method checks if the value of @a obj is equal to the value of @a expected. If + * this is the case, the value of @a obj is changed to @a desired. Otherwise, the value + * of @a obj is changed to @a expected. + * + * @param[in, out] obj The CPU atomic Uintptr to operate upon. + * @param[in, out] expected The expected value of @a obj. If @a obj has a different + * value, @a expected is changed to the actual value of @a obj. + * @param desired The new value of @a obj if the old value of @a obj was as expected. + * @param succ The order if it is successful. + * @param fail The order if it fails. + * + * @retval true The old value of @a obj was as expected. + * @retval false The old value of @a obj was not as expected. + */ +static inline bool _Atomic_Compare_exchange_uintptr( Atomic_Uintptr *obj, uintptr_t *expected, uintptr_t desired, Atomic_Order succ, Atomic_Order fail ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->compare_exchange_strong( *expected, desired, succ, fail ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_compare_exchange_strong_explicit( obj, expected, desired, succ, fail ); +#else + bool success; + ISR_Level level; + uintptr_t actual; + + (void) succ; + (void) fail; + _ISR_Local_disable( level ); + actual = *obj; + success = ( actual == *expected ); + if ( success ) { + *obj = desired; + } else { + *expected = actual; + } + _ISR_Local_enable( level ); + + return success; +#endif +} + +/** + * @brief Clears the atomic flag. + * + * @param[out] obj The atomic flag to be cleared. + * @param order The atomic order for the operation. + */ +static inline void _Atomic_Flag_clear( Atomic_Flag *obj, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + obj->clear( order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + atomic_flag_clear_explicit( obj, order ); +#else + (void) order; + *obj = false; +#endif +} + +/** + * @brief Returns current flag state and sets it. + * + * @param[in, out] obj The atomic flag to be set. + * @param order The atomic order for the operation. + * + * @retval true @a obj was set prior to this operation. + * @retval false @a obj was not set prior to this operation. + */ +static inline bool _Atomic_Flag_test_and_set( Atomic_Flag *obj, Atomic_Order order ) +{ +#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC) + return obj->test_and_set( order ); +#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC) + return atomic_flag_test_and_set_explicit( obj, order ); +#else + bool flag; + ISR_Level level; + + (void) order; + _ISR_Local_disable( level ); + flag = *obj; + *obj = true; + _ISR_Local_enable( level ); + + return flag; +#endif +} /** @} */ |