问题描述
通常,高速缓存行为64B,但非易失性存储器的原子性为8B.
Commonly, cacheline is 64B but atomicity of non-volatile memory is 8B.
例如:
x[1]=100;
x[2]=100;
clflush(x);
x
是高速缓存行对齐的,最初设置为 0
.
x
is cacheline aligned, and is initially set to 0
.
clflush();
重启后是否可能 x [1] = 0
, x [2] = 100
?
推荐答案
在以下假设下:
- 我假设您显示的代码代表x86汇编指令序列,而不是尚未编译的实际C代码.
- 我还假设代码是在Cascade Lake处理器上执行的,而不是在下一代Intel处理器上执行的(我认为具有Barlow Pass的CPL或ICX支持eADR,这意味着持久性不需要显式刷新,因为缓存在持久性域中).此答案也适用于现有的AMD + NVDIMM平台.
存储的全局可观察性顺序可能与Intel x86处理器上的持久性顺序有所不同.这称为宽松持久性.唯一可以保证顺序相同的情况是针对同一高速缓存行的WB类型存储序列(但是达到GO的存储并不一定意味着它变得持久).这是因为 CLFLUSH
是原子的,并且WB存储不能在全局可观察性中重新排序.请参阅:在x86-64上,是"movnti"或"movntdq",系统崩溃时是指令原子吗?.
The global observablility order of stores may differ from the persist order on Intel x86 processors. This is referred to as relaxed persistency. The only case in which the order is guaranteed to be the same is for a sequence of stores of type WB to the same cache line (but a store reaching GO doesn't necessarily meant it's become durable). This is because CLFLUSH
is atomic and WB stores cannot be reordered in global observability. See: On x86-64, is the "movnti" or "movntdq" instruction atomic when system crash?.
x86-TSO内存模型不允许对存储进行重新排序,因此另一个代理不可能观察到 x [2] == 100
和 x [1]!= 100
在正常操作期间(即处于易失性状态而不会崩溃).但是,如果系统崩溃并重新启动,则持久状态可能为 x [2] == 100
和 x [1]!= 100
.即使在退出 clflush
后系统崩溃了,因为 clflush
的退出并不一定意味着刷新的缓存行已到达持久性域.
The x86-TSO memory model doesn't allow reordering stores, so it's impossible for another agent to observe x[2] == 100
and x[1] != 100
during normal operation (i.e., in the volatile state without a crash). However, if the system crashed and rebooted, it's possible for the persistent state to be x[2] == 100
and x[1] != 100
. This is possible even if the system crashed after retiring clflush
because the retirement of clflush
doesn't necessarily mean that the cache line flushed has reached the persistence domain.
如果您想消除这种情况,可以按照以下方式移动 clflush
:
If you want to eliminate that possibly, you can either move clflush
as follows:
x[1]=100;
clflush(x);
x[2]=100;
英特尔处理器上的
clflush
是针对所有写入的顺序排列的,这意味着该行可以保证在以后的所有存储变为全局可观察之前到达持久性域.请参阅:永久性存储器编程主程序(PDF)和Intel SDM V2.第二家商店可以在同一行或任何其他行.
clflush
on Intel processors is ordered with respect to all writes, meaning that the line is guaranteed to reach the persistence domain before any later stores become globally observable. See: Persistent Memory Programming Primary (PDF) and the Intel SDM V2. The second store could be to the same line or any other line.
如果希望 x [1] = 100
在 x [2] = 100
成为全局可观察的之前成为持久性,请在之后添加 sfence
Intel CSX上的 clflush
或AMD处理器上的 mfence
( clflush
仅由AMD处理器上的 mfence
订购). clflush
本身足以控制持久顺序.
If you want x[1]=100
to become persistent before x[2]=100
becomes globally observable, add sfence
after clflush
on Intel CSX or mfence
on AMD processors (clflush
is only ordered by mfence
on AMD processors). clflush
by itself sufficient to control persist order.
或者,按如下所示使用序列 clflushopt + sfence
(或 clwb + sfence
):
Alternatively, use the sequenceclflushopt+sfence
(or clwb+sfence
) as follows:
x[1]=100;
clflushopt(x);
sfence;
x[2]=100;
在这种情况下,如果发生崩溃并且 x [2] == 100
处于持久状态,则可以保证 x [1] == 100
. clflushopt
本身不施加任何持久性排序.
In this case, if a crashed happened and if x[2] == 100
in the persistent state, then it's guaranteed that x[1] == 100
. clflushopt
by itself doesn't impose any persist ordering.
这篇关于系统崩溃时clflush或clflushopt是原子的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!