CPUID 可以用作序列化指令,如此处和此处所述。在C++中以这种方式使用它的最小/最简单的 asm 语法是什么?
// Is that enough?
// What to do with registers and memory?
// Is volatile necessary?
asm volatile("CPUID":::);
您没有使用围栏操作的原因是什么?如果目标是序列化一段代码,您可以执行以下操作:
asm __volatile__ (
" mfence n" // drain the store buffer
" lfence n" // and wait for that instruction to retire, draining the ROB
::: "memory"); // block compile-time reordering.
Your code here
asm __volatile__ (
" mfence n"
" lfence n"
::: "memory" );
这与您从内存和指令重新排序方面从cpuid
获得的序列化差不多。 但两者都不是英特尔技术术语中的正式序列化指令。
软件预取不能保证按围栏指令订购,因此至少在纸面上,较早的prefetcht0
可能会导致数据在lfence
之后到达。 (但是,lfence
之后的prefetcht0
在lfence
完成之前无法执行,因为在lfence
之后的任何指令都不会发送到执行单元,直到之前的所有指令都已停用。 英特尔文档中的"本地完成"。
lfence
阻塞指令重新排序是英特尔 CPU 始终的工作方式,但 AMD 仅具有 MSR 设置。 执行 Spectre 缓解的操作系统设置了 MSR:LFENCE 是否在 AMD 处理器上序列化?