我想修改一个全局变量,该变量由 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/