2

RTOS のさまざまなタスクと IRQ コンテキストによって共有されるグローバル変数を変更したいと考えています。したがって、この変数をアトミックに変更する必要があります。私の現在の実装では、ステートメントをアトミックに変更するために enable_irq/disable_irq 関数を使用しています。

extern int g_var;

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

アトミック操作のヘルパーとして、__sync_bool_compare_and_swapGCCドキュメントの関数を見つけました。

私の現在のツールチェーンは 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));
}

__sync_bool_compare_and_swapARMv4 コマンド セットで (インライン アセンブリとして) 関数を記述するにはどうすればよいですか?

4

1 に答える 1

1

__kernel_cmpxchgLinux カーネル ソースで関数の同様の実装を見つけました。

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

詳細はこちらのリンクからご覧いただけます。

警告したい重要な問題が 2 つあります。

1 -__kernel_cmpxchg スワップが発生した場合は 0 を返し、__sync_bool_compare_and_swap関数は true を返します。

2-関数プロトタイプは異なります。

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));
}

警告: このコードは、カーネル サポートなしでは正しく動作しません。以下のコメントを参照してください。

于 2013-09-04T00:47:50.273 に答える