From de4f23748212dbba7d0250fdac3ae583e74fcbed Mon Sep 17 00:00:00 2001 From: Yaochenger <75192526+Yaochenger@users.noreply.github.com> Date: Thu, 23 Mar 2023 20:06:50 +0800 Subject: [atomic]添加arm与risc-v下的常用原子操作函数 (#7053) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update Kconfig * Update trap_gcc.S * Update bsp/hifive1/drivers/SConscript Co-authored-by: Man, Jianting (Meco) <920369182@qq.com> * Update SConscript * [atomic]提交一份arm与risc-v架构下的常用原子操作函数 * 修改变量类型 * 更新rtatomic.h与atomic_port.c * 更新rt-thread\libcpu\arm\common\atomic_port.c * 更新include/rtatomic.h与libcpu/arm/common/SConscript * 更新include/rtatomic.h * 修正格式与Kconfig * 修正格式与文件结构 * 规范文件格式与文件重命名 * 添加测试用例与CI * 添加函数声明 * 修改virt64/SConscript 添加atomic_riscv.c * 1.规范代码风格 * 2.添加RISC-V64原子指令支持 解决在RV64下编译器将32-bit运算结果扩展为64-bit 导致判断错误 * 添加C11标准库原子操作测试 --------- Co-authored-by: Man, Jianting (Meco) <920369182@qq.com> --- include/rtatomic.h | 195 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 include/rtatomic.h (limited to 'include/rtatomic.h') diff --git a/include/rtatomic.h b/include/rtatomic.h new file mode 100644 index 0000000000..dc7c79e208 --- /dev/null +++ b/include/rtatomic.h @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-03-14 WangShun first version + */ +#ifndef __RT_ATOMIC_H__ +#define __RT_ATOMIC_H__ + +rt_atomic_t rt_hw_atomic_load(volatile rt_atomic_t *ptr); +void rt_hw_atomic_store(volatile rt_atomic_t *ptr, rt_atomic_t val); +rt_atomic_t rt_hw_atomic_add(volatile rt_atomic_t *ptr, rt_atomic_t val); +rt_atomic_t rt_hw_atomic_sub(volatile rt_atomic_t *ptr, rt_atomic_t val); +rt_atomic_t rt_hw_atomic_and(volatile rt_atomic_t *ptr, rt_atomic_t val); +rt_atomic_t rt_hw_atomic_or(volatile rt_atomic_t *ptr, rt_atomic_t val); +rt_atomic_t rt_hw_atomic_xor(volatile rt_atomic_t *ptr, rt_atomic_t val); +rt_atomic_t rt_hw_atomic_exchange(volatile rt_atomic_t *ptr, rt_atomic_t val); +void rt_hw_atomic_flag_clear(volatile rt_atomic_t *ptr); +rt_atomic_t rt_hw_atomic_flag_test_and_set(volatile rt_atomic_t *ptr); +rt_atomic_t rt_hw_atomic_compare_exchange_strong(volatile rt_atomic_t *ptr, rt_atomic_t *old, rt_atomic_t new); + +#if defined(RT_USING_STDC_ATOMIC) +#ifndef __STDC_NO_ATOMICS__ +#define rt_atomic_load(ptr) atomic_load(ptr) +#define rt_atomic_store(ptr, v) atomic_store(ptr, v) +#define rt_atomic_add(ptr, v) atomic_fetch_add(ptr, v) +#define rt_atomic_sub(ptr, v) atomic_fetch_sub(ptr, v) +#define rt_atomic_and(ptr, v) atomic_fetch_and(ptr, v) +#define rt_atomic_or(ptr, v) atomic_fetch_or(ptr, v) +#define rt_atomic_xor(ptr, v) atomic_fetch_xor(ptr, v) +#define rt_atomic_exchange(ptr, v) atomic_exchange(ptr, v) +#define rt_atomic_flag_clear(ptr) atomic_flag_clear(ptr) +#define rt_atomic_flag_test_and_set(ptr) atomic_flag_test_and_set(ptr) +#define rt_atomic_compare_exchange_strong(ptr, v,des) atomic_compare_exchange_strong(ptr, v ,des) +#else +#error "The standard library C doesn't support the atomic operation" +#endif /* __STDC_NO_ATOMICS__ */ +#elif defined(RT_USING_HW_ATOMIC) +#define rt_atomic_load(ptr) rt_hw_atomic_load(ptr) +#define rt_atomic_store(ptr, v) rt_hw_atomic_store(ptr, v) +#define rt_atomic_add(ptr, v) rt_hw_atomic_add(ptr, v) +#define rt_atomic_sub(ptr, v) rt_hw_atomic_sub(ptr, v) +#define rt_atomic_and(ptr, v) rt_hw_atomic_and(ptr, v) +#define rt_atomic_or(ptr, v) rt_hw_atomic_or(ptr, v) +#define rt_atomic_xor(ptr, v) rt_hw_atomic_xor(ptr, v) +#define rt_atomic_exchange(ptr, v) rt_hw_atomic_exchange(ptr, v) +#define rt_atomic_flag_clear(ptr) rt_hw_atomic_flag_clear(ptr) +#define rt_atomic_flag_test_and_set(ptr) rt_hw_atomic_flag_test_and_set(ptr) +#define rt_atomic_compare_exchange_strong(ptr, v,des) rt_hw_atomic_compare_exchange_strong(ptr, v ,des) +#else +#include +#define rt_atomic_load(ptr) rt_soft_atomic_load(ptr) +#define rt_atomic_store(ptr, v) rt_soft_atomic_store(ptr, v) +#define rt_atomic_add(ptr, v) rt_soft_atomic_add(ptr, v) +#define rt_atomic_sub(ptr, v) rt_soft_atomic_sub(ptr, v) +#define rt_atomic_and(ptr, v) rt_soft_atomic_and(ptr, v) +#define rt_atomic_or(ptr, v) rt_soft_atomic_or(ptr, v) +#define rt_atomic_xor(ptr, v) rt_soft_atomic_xor(ptr, v) +#define rt_atomic_exchange(ptr, v) rt_soft_atomic_exchange(ptr, v) +#define rt_atomic_flag_clear(ptr) rt_soft_atomic_flag_clear(ptr) +#define rt_atomic_flag_test_and_set(ptr) rt_soft_atomic_flag_test_and_set(ptr) +#define rt_atomic_compare_exchange_strong(ptr, v,des) rt_soft_atomic_compare_exchange_strong(ptr, v ,des) + +rt_inline rt_atomic_t rt_soft_atomic_exchange(volatile rt_atomic_t *ptr, rt_atomic_t val) +{ + rt_base_t level; + rt_atomic_t temp; + level = rt_hw_interrupt_disable(); + temp = *ptr; + *ptr = val; + rt_hw_interrupt_enable(level); + return temp; +} + +rt_inline rt_atomic_t rt_soft_atomic_add(volatile rt_atomic_t *ptr, rt_atomic_t val) +{ + rt_base_t level; + rt_atomic_t temp; + level = rt_hw_interrupt_disable(); + temp = *ptr; + *ptr += val; + rt_hw_interrupt_enable(level); + return temp; +} + +rt_inline rt_atomic_t rt_soft_atomic_sub(volatile rt_atomic_t *ptr, rt_atomic_t val) +{ + rt_base_t level; + rt_atomic_t temp; + level = rt_hw_interrupt_disable(); + temp = *ptr; + *ptr -= val; + rt_hw_interrupt_enable(level); + return temp; +} + +rt_inline rt_atomic_t rt_soft_atomic_xor(volatile rt_atomic_t *ptr, rt_atomic_t val) +{ + rt_base_t level; + rt_atomic_t temp; + level = rt_hw_interrupt_disable(); + temp = *ptr; + *ptr = (*ptr) ^ val; + rt_hw_interrupt_enable(level); + return temp; +} + +rt_inline rt_atomic_t rt_soft_atomic_and(volatile rt_atomic_t *ptr, rt_atomic_t val) +{ + rt_base_t level; + rt_atomic_t temp; + level = rt_hw_interrupt_disable(); + temp = *ptr; + *ptr = (*ptr) & val; + rt_hw_interrupt_enable(level); + return temp; +} + +rt_inline rt_atomic_t rt_soft_atomic_or(volatile rt_atomic_t *ptr, rt_atomic_t val) +{ + rt_base_t level; + rt_atomic_t temp; + level = rt_hw_interrupt_disable(); + temp = *ptr; + *ptr = (*ptr) | val; + rt_hw_interrupt_enable(level); + return temp; +} + +rt_inline rt_atomic_t rt_soft_atomic_load(volatile rt_atomic_t *ptr) +{ + rt_base_t level; + rt_atomic_t temp; + level = rt_hw_interrupt_disable(); + temp = *ptr; + rt_hw_interrupt_enable(level); + return temp; +} + +rt_inline void rt_soft_atomic_store(volatile rt_atomic_t *ptr, rt_atomic_t val) +{ + rt_base_t level; + level = rt_hw_interrupt_disable(); + *ptr = val; + rt_hw_interrupt_enable(level); +} + +rt_inline rt_atomic_t rt_soft_atomic_flag_test_and_set(volatile rt_atomic_t *ptr) +{ + rt_base_t level; + rt_atomic_t temp; + level = rt_hw_interrupt_disable(); + if (*ptr == 0) + { + temp = 0; + *ptr = 1; + } + else + temp = 1; + rt_hw_interrupt_enable(level); + return temp; +} + +rt_inline void rt_soft_atomic_flag_clear(volatile rt_atomic_t *ptr) +{ + rt_base_t level; + level = rt_hw_interrupt_disable(); + *ptr = 0; + rt_hw_interrupt_enable(level); +} + +rt_inline rt_atomic_t rt_soft_atomic_compare_exchange_strong(volatile rt_atomic_t *ptr1, rt_atomic_t *ptr2, + rt_atomic_t desired) +{ + rt_base_t level; + rt_atomic_t temp; + level = rt_hw_interrupt_disable(); + if ((*ptr1) != (*ptr2)) + { + *ptr2 = *ptr1; + temp = 0; + } + else + { + *ptr1 = desired; + temp = 1; + } + rt_hw_interrupt_enable(level); + return temp; +} +#endif /* RT_USING_STDC_ATOMIC */ +#endif /* __RT_ATOMIC_H__ */ -- cgit v1.3.1