避免先检查后睡眠的竞争条件

Avoid race condition on check-then-sleep

以下面的示例代码为例:

static volatile bool pending = false;

void __attribute__((interrupt(TIMER0_A0_VECTOR))) TIMER0_A0_ISR (void)
{
    pending = true;        
}

int main(void)
{
    while(true) {
        if (!pending)
            sleep();
        pending = false;
        // do stuff
    }
}

假设睡眠函数使硬件进入睡眠状态,并且中断唤醒硬件,因此睡眠函数将在中断后立即return。

这里有一个竞争条件:如果中断发生在 if 语句之后但在睡眠之前,我们将睡眠直到下一个中​​断。这是我在现实世界中对应此代码的问题。我怎样才能避免这个问题?

我正在使用 msp430g2433。

为了确保自动执行检查和进入睡眠,您必须禁用它们周围的中断。这还需要您进入休眠状态并同时重新启用中断,但这在 MSP430 上很容易:

while (true) {
    _disable_interrupts();
    if (!pending)
        _bis_SR_register(GIE + LPM1_bits);
    else
        _enable_interrupts();

    pending = false;
    // do stuff
}

或者,显式写入中断位访问,这可能会使逻辑更清晰:

while (true) {
    int status_bits = GIE;
    _bic_SR_register(status_bits); // disable interrupts
    if (!pending)
        status_bits |= LPM1_bits;
    _bis_SR_register(status_bits); // enable interrupts, go to sleep if needed

    pending = false;
    // do stuff
}