c - 如何在 ARM7 中进行原子比较和交换?

标签 c atomic keil arm7

我想修改一个全局变量,该变量由 RTOS 中的不同任务和 IRQ 上下文共享。因此我需要原子地修改这个变量。 在我当前的实现中,我一直在使用 enable_irq/disable_irq 函数以原子方式修改语句。

extern int g_var;

void set_bit_atomic(int mask)
{
    disable_irq();
    g_var |= mask;
    enable_irq();
}

我在 GCC 中找到了 __sync_bool_compare_and_swap 函数 documentation作为原子操作的助手。

我目前的工具链是KEIL MDK,我想换成下图的方式,

void set_bit_atomic(int mask)
{
    volatile int tmp;
    do {
        tmp = g_var;
    } while (!__sync_bool_compare_and_swap(&g_var, tmp, tmp | mask));
}

如何在 ARMv4 命令集中编写 __sync_bool_compare_and_swap 函数(作为内联汇编)?

最佳答案

我在 Linux 内核源代码中找到了 __kernel_cmpxchg 函数的类似实现。

它是为 ARMv5 和更早版本编写的,它似乎适用于 ARM7TDMI (ARMv4)。

1:      ldr     r3, [r2]        @ load current val
        subs    r3, r3, r0      @ compare with oldval
2:      streq   r1, [r2]        @ store newval if eq
        rsbs    r0, r3, #0      @ set return val and C flag
        bx      lr              @ or "mov pc, lr" if no thumb support

可以在 this 链接中找到详细信息。

我想警告两个重要的问题,

1- __kernel_cmpxchg 发生交换时返回 0,而 __sync_bool_compare_and_swap 函数返回 true。

2-函数原型(prototype)不同。

typedef int (*__kernel_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
#define __kernel_cmpxchg ((__kernel_cmpxchg_t)0xffff0fc0)

bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)

因此我不得不如下更改用法,

void set_bit_atomic(int mask)
{
    volatile int tmp;
    do {
        tmp = g_var;
    } while (my_compare_and_swap(tmp, tmp | mask, &g_var));
}

警告:如果没有内核支持,此代码将无法正常工作。请参阅下面的评论。

关于c - 如何在 ARM7 中进行原子比较和交换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18475347/

相关文章:

c++ - 来自 CreateWindow/CreateDialog 的 HWND 是否可以从另一个线程获取消息?

c++ - 奇怪的shared_ptr行为

c - 生成 RTE_Components.h

c - 防止 Keil uVision 中 bool 值的 "enumerated type mixed with another type"警告

C 忽略结构体前面的 const 限定符

c - 使用 MinGW 和 CMake 编译 HDF5 时出错

c - 逆向工程递归函数

c - 在 C 中的 getline 中识别 EOF 与换行符

python - python 中的 stdin.readline() 是原子的吗?

c++ std::atomic<bool>::fetch_or 未实现?