From 900e713cd0eda2a2b16a413080757975a0d7bb2a Mon Sep 17 00:00:00 2001 From: chenrun1 Date: Thu, 8 Aug 2024 16:04:32 +0800 Subject: [PATCH] atomic:Add more interfaces Summary: 1. add atomic_flag_test_and_set and atomic_flag_clear 2. add typedef memory_order 3. add atomic_flag Signed-off-by: chenrun1 --- include/nuttx/atomic.h | 9 ++++++- include/nuttx/lib/stdatomic.h | 45 ++++++++++++++++++++++++++++----- libs/libc/machine/arch_atomic.c | 39 ++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 8 deletions(-) diff --git a/include/nuttx/atomic.h b/include/nuttx/atomic.h index 487366264a..2d2d2eee68 100644 --- a/include/nuttx/atomic.h +++ b/include/nuttx/atomic.h @@ -33,6 +33,7 @@ extern "C++" # define ATOMIC_VAR_INIT(value) (value) + using std::memory_order; using std::atomic_bool; using std::atomic_char; using std::atomic_schar; @@ -56,6 +57,10 @@ extern "C++" using std::atomic_compare_exchange_strong_explicit; using std::atomic_compare_exchange_weak; using std::atomic_compare_exchange_weak_explicit; + using std::atomic_flag_test_and_set; + using std::atomic_flag_test_and_set_explicit; + using std::atomic_flag_clear; + using std::atomic_flag_clear_explicit; using std::atomic_fetch_add; using std::atomic_fetch_add_explicit; using std::atomic_fetch_sub; @@ -67,7 +72,9 @@ extern "C++" using std::atomic_fetch_xor; using std::atomic_fetch_xor_explicit; } -# elif __has_include() +# elif __has_include() && \ + ((defined(__cplusplus) && __cplusplus >= 201103L) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L)) # if !(__clang__) && defined(__cplusplus) # define _Atomic # endif diff --git a/include/nuttx/lib/stdatomic.h b/include/nuttx/lib/stdatomic.h index 65278027a6..fae2b32f1c 100644 --- a/include/nuttx/lib/stdatomic.h +++ b/include/nuttx/lib/stdatomic.h @@ -56,6 +56,7 @@ # define __ATOMIC_SEQ_CST 5 #endif +#define ATOMIC_FLAG_INIT 0 #define ATOMIC_VAR_INIT(value) (value) #define atomic_store_n(obj, val, type) \ @@ -101,14 +102,16 @@ #define atomic_compare_exchange_weak_explicit(obj, expected, desired, success, failure) \ atomic_compare_exchange_n(obj, expected, desired, true, success, failure) -#define atomic_fetch_or_n(obj, val, type) \ - (sizeof(*(obj)) == 1 ? __atomic_fetch_or_1(obj, val, type) : \ - sizeof(*(obj)) == 2 ? __atomic_fetch_or_2(obj, val, type) : \ - sizeof(*(obj)) == 4 ? __atomic_fetch_or_4(obj, val, type) : \ - __atomic_fetch_or_8(obj, val, type)) +#define atomic_flag_test_and_set_n(obj, type) \ + (sizeof(*(obj)) == 1 ? __atomic_flag_test_and_set_1(obj, type) : \ + sizeof(*(obj)) == 2 ? __atomic_flag_test_and_set_2(obj, type) : \ + sizeof(*(obj)) == 4 ? __atomic_flag_test_and_set_4(obj, type) : \ + __atomic_flag_test_and_set_8(obj, type)) -#define atomic_fetch_or(obj, val) atomic_fetch_or_n(obj, val, __ATOMIC_RELAXED) -#define atomic_fetch_or_explicit(obj, val, type) atomic_fetch_or_n(obj, val, type) +#define atomic_flag_test_and_set(obj) atomic_flag_test_and_set_n(obj, __ATOMIC_RELAXED) +#define atomic_flag_test_and_set_explicit(obj, type) atomic_flag_test_and_set_n(obj, 1, type) +#define atomic_flag_clear(obj) atomic_store(obj, 0) +#define atomic_flag_clear_explicit(obj, type) atomic_store_explicit(obj, 0, type) #define atomic_fetch_and_n(obj, val, type) \ (sizeof(*(obj)) == 1 ? __atomic_fetch_and_1(obj, val, type) : \ @@ -119,6 +122,15 @@ #define atomic_fetch_and(obj, val) atomic_fetch_and_n(obj, val, __ATOMIC_RELAXED) #define atomic_fetch_and_explicit(obj, val, type) atomic_fetch_and_n(obj, val, type) +#define atomic_fetch_or_n(obj, val, type) \ + (sizeof(*(obj)) == 1 ? __atomic_fetch_or_1(obj, val, type) : \ + sizeof(*(obj)) == 2 ? __atomic_fetch_or_2(obj, val, type) : \ + sizeof(*(obj)) == 4 ? __atomic_fetch_or_4(obj, val, type) : \ + __atomic_fetch_or_8(obj, val, type)) + +#define atomic_fetch_or(obj, val) atomic_fetch_or_n(obj, val, __ATOMIC_RELAXED) +#define atomic_fetch_or_explicit(obj, val, type) atomic_fetch_or_n(obj, val, type) + #define atomic_fetch_xor_n(obj, val, type) \ (sizeof(*(obj)) == 1 ? __atomic_fetch_xor_1(obj, val, type) : \ sizeof(*(obj)) == 2 ? __atomic_fetch_xor_2(obj, val, type) : \ @@ -150,6 +162,17 @@ * Public Types ****************************************************************************/ +typedef enum +{ + memory_order_relaxed = __ATOMIC_RELAXED, + memory_order_consume = __ATOMIC_CONSUME, + memory_order_acquire = __ATOMIC_ACQUIRE, + memory_order_release = __ATOMIC_RELEASE, + memory_order_acq_rel = __ATOMIC_ACQ_REL, + memory_order_seq_cst = __ATOMIC_SEQ_CST +} memory_order; + +typedef volatile int atomic_flag; typedef volatile bool atomic_bool; typedef volatile char atomic_char; typedef volatile signed char atomic_schar; @@ -196,6 +219,14 @@ bool __atomic_compare_exchange_4(FAR volatile void *mem, FAR void *expect, bool __atomic_compare_exchange_8(FAR volatile void *mem, FAR void *expect, uint64_t desired, bool weak, int success, int failure); +uint8_t __atomic_flag_test_and_set_1(FAR const volatile void *ptr, + int memorder); +uint16_t __atomic_flag_test_and_set_2(FAR const volatile void *ptr, + int memorder); +uint32_t __atomic_flag_test_and_set_4(FAR const volatile void *ptr, + int memorder); +uint64_t __atomic_flag_test_and_set_8(FAR const volatile void *ptr, + int memorder); uint8_t __atomic_fetch_add_1(FAR volatile void *ptr, uint8_t value, int memorder); uint16_t __atomic_fetch_add_2(FAR volatile void *ptr, uint16_t value, diff --git a/libs/libc/machine/arch_atomic.c b/libs/libc/machine/arch_atomic.c index a04e9ecacf..efb7238888 100644 --- a/libs/libc/machine/arch_atomic.c +++ b/libs/libc/machine/arch_atomic.c @@ -98,6 +98,21 @@ return ret; \ } +#define FLAG_TEST_AND_SET(n, type) \ + \ + type weak_function __atomic_flags_test_and_set##n (FAR volatile void *ptr, \ + int memorder) \ + { \ + irqstate_t irqstate = spin_lock_irqsave(NULL); \ + FAR type *tmp = (FAR type *)ptr; \ + type ret = *tmp; \ + \ + *(FAR type *)ptr = 1; \ + \ + spin_unlock_irqrestore(NULL, irqstate); \ + return ret; \ + } + #define FETCH_ADD(n, type) \ \ type weak_function __atomic_fetch_add_##n (FAR volatile void *ptr, \ @@ -396,6 +411,30 @@ CMP_EXCHANGE(4, uint32_t) CMP_EXCHANGE(8, uint64_t) +/**************************************************************************** + * Name: __atomic_flag_test_and_set_1 + ****************************************************************************/ + +FLAG_TEST_AND_SET(1, uint8_t) + +/**************************************************************************** + * Name: __atomic_flag_test_and_set_2 + ****************************************************************************/ + +FLAG_TEST_AND_SET(2, uint16_t) + +/**************************************************************************** + * Name: __atomic_flag_test_and_set_4 + ****************************************************************************/ + +FLAG_TEST_AND_SET(4, uint32_t) + +/**************************************************************************** + * Name: __atomic_flag_test_and_set_8 + ****************************************************************************/ + +FLAG_TEST_AND_SET(8, uint64_t) + /**************************************************************************** * Name: __atomic_fetch_add_1 ****************************************************************************/