可能访问挥发物重新排序? [英] May accesses to volatiles be reordered?
问题描述
请考虑以下对 volatile
内存的写入顺序,我已从 David Chisnall在InformIT 的文章了解C11和C ++ 11原子:
volatile int a = 1;
volatile int b = 2;
a = 3;
我从C ++ 98的理解是这些操作无法重新排序,每个C ++ 98 1.9:
符合
实现需要模拟抽象机器的可观察行为,因为
...
抽象机器的可观察行为是对易失性数据的读写操作序列和
对库I / O函数的调用
Chisnall说,订单保存的约束仅适用于单个变量,写出一个符合的实现可以生成执行此操作的代码:
a = 1;
a = 3;
b = 2;
或:
b = 2;
a = 1;
a = 3;
C ++ 11重复C ++ 98的措辞
符合
的实现需要模拟(仅)抽象机器的可观察行为,如下面的
所述。
但是关于 volatile
s(1.9 / 8):
对volatile对象的访问严格按照抽象机器的规则进行计算。
1.9 / 12表示访问 volatile
glvalue(其中包括变量 a
, / code>和上面的
c
)是一个副作用,1.9 / 14表示一个完整表达式(例如语句)中的副作用必须在以后的完整表达式在同一个线程中的副作用。这使我得出结论,Chisnall显示的两个重新排序是无效的,因为它们不对应于抽象机器指定的排序。
我可以俯瞰某物,或是Chisnall错误吗?
(注意这不是一个线程问题。问题是编译器是否允许在单个线程中重新访问不同的 volatile
变量。)
IMO Chisnalls解释(由您提供)显然是错误的。更简单的情况是C ++ 98。需要保留对易失性数据的读取和写入的 这很明显,如果你考虑volatile:memory-mapped I / O的原始动机。在mmio中,通常在不同的存储器位置具有几个相关寄存器,并且I / O设备的协议需要对其寄存器集合进行特定的读取和写入序列 - 寄存器之间的顺序很重要。 C ++ 11的措辞避免谈论一个绝对的 这是一个完全独立的问题,这是一个实现。如何(甚至如果)从程序外部可观察到易失性数据访问,以及程序的访问顺序如何映射到外部可见事件未指定。一个实现应该给你一个合理的解释和合理的保证,但什么是合理的取决于上下文。 C ++ 11标准为不同步之间的数据竞争留下了空间易失性访问,所以没有什么需要围绕这些由全内存栅栏或类似的结构。如果存在真正用作存储器映射I / O或DMA的外部接口的存储器部分,那么实现可能是合理的,以保证对这些部分的易失性存取如何暴露给消费设备。 / p> 一个保证可能是从标准推断的(参见[into.execution]):类型 Consider the following sequence of writes to My understanding from C++98 was that these operations could not be reordered, per C++98 1.9: conforming
implementations are required to emulate (only) the observable behavior of the abstract machine as
explained below
...
The observable behavior of the abstract machine is its sequence of reads and writes to volatile data and
calls to library I/O functions Chisnall says that the constraint on order preservation applies only to individual variables, writing that a conforming implementation could generate code that does this: Or this: C++11 repeats the C++98 wording that conforming
implementations are required to emulate (only) the observable behavior of the abstract machine as explained
below. but says this about Access to volatile objects are evaluated strictly according to the rules of the abstract machine. 1.9/12 says that accessing a Am I overlooking something, or is Chisnall mistaken? (Note that this is not a threading question. The question is whether a compiler is permitted to reorder accesses to different IMO Chisnalls interpretation (as presented by you) is clearly wrong. The simpler case is C++98. The This becomes obvious, if you consider the original motivation for volatile: memory-mapped I/O. In mmio you typically have several related registers at different memory location and the protocol of an I/O device requires a specific sequence of reads and writes to its set of registers - order between registers is important. The C++11 wording avoids talking about an absolute It is an entirely separate issue what that entails for an implementation. How (and even if) a volatile data access is observable from outside the program and how the access order of the program maps to externally observable events is unspecified. An implementation should probably give you a reasonable interpretation and reasonable guarantees, but what is reasonable depends on the context. The C++11 standard leaves room for data races between unsynchronized volatile accesses, so there is nothing that requires surrounding these by full memory fences or similar constructs. If there are parts of memory that are truly used as external interface - for memory-mapped I/O or DMA - then it may be reasonable for the implementation to give you guarantees for how volatile accesses to these parts are exposed to consuming devices. One guarantee can probably be inferred from the standard (see [into.execution]): values of type 这篇关于可能访问挥发物重新排序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!序列,并且适用于任何易失性数据的读取和写入的有序序列,而不是单个变量。 p>
读写序列
,因为在多线程环境中没有一个明确定义这样的事件跨线程的序列 - 并且这不是一个问题,如果这些访问去独立的存储器位置。但我相信的意图是,对于任何序列的易失性数据访问与一个明确定义的顺序规则保持与C ++ 98相同 - 顺序必须保留,无论在该序列访问多少个不同的位置。
的值std :: sigatomic_t
必须具有与它们的写入顺序兼容的值,即使在信号处理程序中 - 至少在单线程程序中。volatile
memory, which I've taken from David Chisnall's article at InformIT, "Understanding C11 and C++11 Atomics":volatile int a = 1;
volatile int b = 2;
a = 3;
a = 1;
a = 3;
b = 2;
b = 2;
a = 1;
a = 3;
volatile
s (1.9/8):
volatile
glvalue (which includes the variables a
, b
, and c
above) is a side effect, and 1.9/14 says that the side effects in one full expression (e.g., a statement) must precede the side effects of a later full expression in the same thread. This leads me to conclude that the two reorderings Chisnall shows are invalid, because they do not correspond to the ordering dictated by the abstract machine. volatile
variables in a single thread.)sequence of reads and writes to volatile data
needs to be preserved and that applies to the ordered sequence of reads and writes of any volatile data, not to a single variable.sequence of reads and writes
, because in multi-threaded environments there is not one single well-defined sequence of such events across threads - and that is not a problem, if these accesses go to independent memory locations. But I believe the intent is that for any sequence of volatile data accesses with a well-defined order the rules remain the same as for C++98 - the order must be preserved, no matter how many different locations are accessed in that sequence.volatile std::sigatomic_t
must have values compatible with the order of writes to them even in a signal handler - at least in a single-threaded program.