I would like to modify a global variable which is shared by different tasks and IRQ contexts in a RTOS. Therefore I need to modify this variable atomically. In my current implementation, I have been using enable_irq/disable_irq functions to modify the statement atomically.
extern int g_var;
void set_bit_atomic(int mask)
{
disable_irq();
g_var |= mask;
enable_irq();
}
I've found the __sync_bool_compare_and_swap
function in GCC documentation as a helper for atomic operations.
My current toolchain is KEIL MDK, and I would like to switch to the approach shown below,
void set_bit_atomic(int mask)
{
volatile int tmp;
do {
tmp = g_var;
} while (!__sync_bool_compare_and_swap(&g_var, tmp, tmp | mask));
}
How can I write __sync_bool_compare_and_swap
function in ARMv4 command set(as inline assembly)?
I have found a similar implementation for
__kernel_cmpxchg
function in Linux kernel source.It has been written for ARMv5 and earlier, and It seems to work for ARM7TDMI (ARMv4).
Details can be found at this link.
There are two important issues that I would like to warn,
1-
__kernel_cmpxchg
returns 0 when swap occurred, while__sync_bool_compare_and_swap
function returns true.2- function prototypes are different.
Therefore I had to change the usage as below,
Caveat: This code does not work properly without kernel support. See the comments below.