避免先检查后睡眠的竞争条件
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
}
以下面的示例代码为例:
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
}