【问题标题】:How to understand atomics in a freestanding C or C++ implementation? [closed]如何理解独立 C 或 C++ 实现中的原子? [关闭]
【发布时间】:2016-12-16 18:17:44
【问题描述】:

C11 和 C++11 根据执行线程定义原子。在托管环境中,线程是什么很清楚,但在独立语言实现中,它是一个相当模糊的术语。

  1. 如何在必须在程序内部实现所有线程的独立实现中正式理解 C11 和 C++11 中指定的原子?例如:ISR 是一个单独的执行线程吗?
  2. 为什么标准委员会根据线程而不是简单地在代码排序领域定义原子?
  3. 除了 gcc 之外,是否有任何嵌入式编译器已经支持 C11/C++11 原子?

【问题讨论】:

  • 请注意 C++11 在 [intro.multithread]/1 中定义了 thread
  • 如果您只有 ISR,而不是多个处理器/内核,我会说标准的相关部分是信号,而不是线程。
  • @NathanOliver 谢谢,从问题中删除了这句话。
  • @EOF 我也会这么说,但从标准的角度来看,ISR 是信号处理程序吗?
  • 我不清楚“有序原子”中的“有序”是什么意思。原子防止数据竞争;他们没有也不能保证订购。

标签: c++ c c++11 c11


【解决方案1】:

对于这类问题,我有点机械化(有点手摇)的方法是原子保证三件事:读取和写入不会被上下文切换撕裂(所以你只能看到实际存储在变量中的值) ;缓存被刷新(所以你看不到陈旧的值);并且编译器不能在原子操作中移动指令(因此逻辑上发生在原子访问之前的操作实际上发生在该访问之前)。请注意,我在这里尽量避免使用任何“线程”的概念,尽管它有点费力。

如果您正在编写自己的线程机制,那么这些属性显然很重要。它们与您正在使用的线程机制的细节正交。

对于信号处理程序,当您需要检查信号处理程序中执行的代码中的值以及信号处理程序需要修改程序其余部分关心的值时,它们为您提供了一个立足点。

我不确定该标准是否正式解决了 ISR(很确定它没有),但从这个机制的角度来看,ISR 与不是来自对 raise 的调用的信号没有什么不同。它只是一个异步函数调用,它占用了从被中断的线程中获取的堆栈空间。这绝对是不是一个线程;它是现有线程上的寄生虫。所以对于 ISR,我会选择对信号的保证而不是对线程的保证。

【讨论】:

  • 我仍然想知道的一件事是,为什么标准没有根据您编写的三个保证来定义原子,没有“线程”的概念。如果确实如此,那么毫无疑问,原子对于裸机语言实现意味着什么。
  • @mrn - 我认为这正是因为我写的东西是机械的和挥手的。 该标准试图用抽象机器来定义 C++ 的语义,目前它没有“撕裂”或“缓存”的概念。事实上,抽象机器中几乎没有关于内存的内容,这是故意的,以避免过度包含系统。如果你仔细看,你会发现当你调用operator newoperator delete 时,你得到的唯一保证是第一个“分配存储”,第二个“回收......存储”....
  • ... 所以对于原子,主要用途是在线程之间传递值,并且定义是根据线程之间共享值时发生的情况。
  • @Peter Becker 好的,感谢您的解释。如果我尝试自己编写标准,可能会看到问题。
【解决方案2】:

原子用于处理竞争条件,因此如果没有线程,它们几乎没有意义。唯一可能发生争用的其他上下文是信号处理程序,C 标准提供了无锁概念。

这样看来,独立环境和托管环境之间没有区别。线程和原子是可选特性,如果独立环境支持两者,它必须符合两者的规范。如果它只支持 atomics,它可以为信号处理程序提供无锁的 atomic 类型,但其他 atomic 类型就没有用了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-22
    • 1970-01-01
    相关资源
    最近更新 更多