【问题标题】:volatile vs memory barrier for interrupts中断的易失性与内存屏障
【发布时间】:2019-11-09 11:55:53
【问题描述】:

xy 成为主代码和中断代码之间共享的变量。

我对@9​​87654323@ 的想法是,它仅且始终需要用于也在主代码中使用的硬件变量和中断变量。

通过禁用中断,保证主代码中xy 的每次使用都是原子的。

xy 是否真的需要为volatile,或者在使用它们强制从 RAM 重新加载变量之前设置内存屏障是否足够?

一)

volatile bool x;
volatile int y[100];

int main(void)
{

        while (true) {
                disable_interrupts();
                if (x)
                        work(y);
                x = false;
                enable_interrupts();
        }
}

B)

bool x;
int y[100];

int main(void)
{

        while (true) {
                memory_barrier();
                disable_interrupts();
                if (x)
                        work(y);
                x = false;
                enable_interrupts();
        }
}

目标是:

  • 让编译器优化work()

  • 能够使用标准库函数,例如 memcpy()(这些函数不能与 volatile 变量一起使用)。

编辑:添加中断示例

interrupts.c:

extern volatile? int x;
extern volatile? int y;

void interrupt(void)
{

        x = true;
        REGY1 = y[7];
        y[23] = REGY2;
}

【问题讨论】:

  • 您如何看到这段代码被有害地重新组织,既没有易失性也没有内存障碍?即使work 被内联?谁来更新变量?
  • 据我所知,您只显示了一个可能访问变量的上下文。只有不止一个才会有趣。请展示另一个可能访问变量的上下文示例。
  • My idea of volatile nee,仅当编译器优化它们时。您不需要 volatile 所有变量,只需要那些您不想对其应用优化的变量。 those aren't made to be used with volatile variables - 通过非易失性句柄访问易失性对象无论如何都是 UB。无论如何,编译器不应该优化memcpy,因为它会看到它访问一个易失性对象。让我们标记它:应该is it enough to put a memory barrier - 不,不是。在您的第二个代码中,sn-p 编译器将完全删除 if (x) 语句,因为它是 if (false)
  • @Lundin 是的,但是如果中断被阻止,我们在这里试图避免的优化究竟是什么?
  • 请注意,与嵌入式系统编译器不同,桌面系统编译器往往从不假设不会调用中断/回调。因此,对于您的普通 PC 编译器,您不需要 volatile 限定与回调共享的变量,因为作为编译器扩展,编译器确保它意识到这些变量可以随时更新。但这绝不是任何标准的保证。

标签: c interrupt atomic volatile memory-barriers


【解决方案1】:

内存屏障而不是volatile 很好。 Linux内核开发者prefer it that way

有几点需要注意。

  • 在禁用中断后移动屏障。中断往往发生在最糟糕的时候。
  • 在启用中断之前,您需要第二个内存屏障,用于在主程序中写入并在中断处理程序中读取的变量。
  • 在多处理器/多核系统中禁用中断是不够的,它不会阻止另一个内核运行。
  • 不用说,不应长时间禁用中断,因为它会阻止某些硬件驱动程序运行。

【讨论】:

  • 我知道 Linux 的各种线程。我不知道它对中断也有效:)
  • 对任何可以改变变量内容的东西都有效。不管是中断、另一个处理器还是 DMA 访问。
猜你喜欢
  • 2018-02-28
  • 1970-01-01
  • 2010-12-19
  • 2017-01-17
  • 2020-02-08
  • 2015-11-03
  • 1970-01-01
  • 2017-07-31
  • 1970-01-01
相关资源
最近更新 更多