C ++ 11 atomics:将它们与内存映射I / O一起使用是否有意义,甚至可能?

时间:2016-02-24 05:32:10

标签: c++ c++11 atomic device-driver memory-mapping

据我了解,C volatile和内存asm的内联asm已用于在内存映射I / O之上实现设备驱动程序。在Linux内核中可以找到几个例子。

如果我们忘记了未捕获异常的风险(如果有的话),用C ++ 11原子替换它们是否有意义?或者,它有可能吗?

2 个答案:

答案 0 :(得分:2)

据我所知,读取引用std::atomic旨在管理对内存的多线程访问(并发等)。但据我所知,正如你所说,volatile是为内存映射I / O和信号处理等内容而设计的。因此,volatile对原子访问没有影响,如果单独使用,则不能解决像原子一样的多线程访问问题。反之亦然 - 原子不提供volatile的特征。

因此,对你的问题的简短回答是否定的。

答案 1 :(得分:2)

通常,您可以使用原子替换内存栅栏,但不能替换volatile,除非它与栅栏一起用于线程间通信。

关于内存映射I / O,原子不够的原因是:

  • volatile保证您对程序中该变量的所有内存访问都会确实发生,并且它们恰好按照您指定的顺序发生(在单个线程中)。
  • std::atomic只保证您的程序就好像所有这些内存访问一样(根据C ++的内存模型,它不知道关于内存映射I / O)和 - 取决于指定的内存排序 - ,好像它们按指定的顺序发生。

实际上,这意味着编译器可以例如用一次写入替换对相同(非易失性)原子的连续写入(如果之间没有其他同步),对于读取也是如此。如果不使用读取的结果,它甚至可以完全消除读取(编译器可能仍然必须发出内存屏障)。

在更理论的层面上,如果您的编译器可以证明您的所有程序都返回42,则允许将其转换为单个指令,而与程序在此过程中使用的线程数和原子数无关。如果你的程序使用不是这种情况的volatile变量。

编辑:例如This paper显示了允许编译器应用于原子循环变量的一些可能的(可能是意外的)优化。