3

我有一个禁用中断的功能,但问题是如果我禁用它们并调用一个也禁用/启用它们的函数,它们会过早重新启用。以下逻辑是否足以防止这种情况发生?

static volatile int IrqCounter = 0;

void EnableIRQ()
{
    if(IrqCounter > 0)
    {
        IrqCounter--;
    }

    if(IrqCounter == 0)
    {
        __enable_irq();
    }
}

void DisableIRQ()
{
    if(IrqCounter == 0)
    {
        __disable_irq();
    }

    IrqCounter++;
}
4

4 回答 4

5

我所知道的每个操作系统的做法是将 IRQ 状态保存到局部变量中,然后恢复它。

显然,您的代码存在TOCTOU问题 - 如果两个线程同时运行,检查 IrqCounter > 0,如果 IrqCounter == 1,则第一个线程将其视为 1,第二个线程将其视为 1,并且两者都递减柜台。

我肯定会尝试安排这样的事情:

int irq_state = irq_save();

irq_disable();

... do stuff with IRQ's turned off ... 

irq_restore(irq_state);

现在,您不必担心计数器会不同步等问题。

于 2013-01-29T12:45:47.603 回答
2

假设您有一个在禁用中断时无法更改上下文的系统,那么您所拥有的一切都很好,假设您仔细跟踪何时调用 enable()。

在您在下面的评论中描述的用法中,您计划在中断服务例程中使用这些部分。您的主要用途是阻止更高优先级的中断在 ISR 的某个部分运行。

请注意,您必须考虑这些嵌套 ISR 的堆栈深度,因为当您在从中断返回之前启用中断时,您将在 ISR 中启用中断。

关于其他答案: enable() 缺乏线程安全性(由于if(IrqCounter > 0))并不重要,因为任何时候你在 enable() 上下文切换已经被禁用,因为中断被关闭。(除非由于某种原因您有无与伦比的禁用/启用对,并且在这种情况下您还有其他问题。)

我唯一的建议是将 ASSERT 添加到启用而不是运行时检查,因为您永远不应该启用未禁用的中断。

void EnableIRQ()
{
  ASSERT(IrqCounter != 0)  //should never be 0, or we'd have an unmatched enable/disable pair

  IrqCounter--;  //doesn't matter that this isn't thread safe, as the enable is always called with interrupts disabled.

  if(IrqCounter == 0)
  {
      __enable_irq();
  }
}

我更喜欢您列出的save(); disable(); restore();技术而不是技术,因为我不喜欢每次处理中断时都必须跟踪操作系统的一段数据。但是,您必须注意何时(直接或间接)从 ISR 调用 enable()。

于 2013-01-29T14:40:32.907 回答
0

看起来不错,只是它不是线程安全的。

另一个常见的选项是查询中断启用/禁用状态并将其保存到局部变量中,然后禁用中断,然后在禁用中断时执行任何您想做的事情,然后从局部变量中恢复状态。

于 2013-01-29T12:21:09.263 回答
0
static volatile int IrqCounter = 0;

void EnableIRQ(void)
{
    ASSERT(IrqCounter != 0)  //should never be 0, or we'd have an unmatched enable/disable pair

    if (IrqCounter > 0)
    {
        IrqCounter--;
    }

    if (IrqCounter == 0)
    {
        __enable_irq();
    }
}

void DisableIRQ(void)
{
    __disable_irq(); // Fix TOCTOU issues. In CMSIS there is no harm in extra disables, so always disable.
    IrqCounter++;
}
于 2020-11-15T17:58:41.720 回答