试图用我的想法去上同时使用软件和硬件的记忆障碍,我可以禁用外,为了优化为与编译器的优化编译代码内部的特定功能的,因此我也使用像Peterson
或Deker
算法需要外的顺序没有执行实现软件旗语,我已经测试了以下代码包含两个SW屏障asm volatile("": : :"memory")
和gcc内建HW屏障__sync_synchronize
:使用内存屏障强制顺序执行
#include <stdio.h>
int main(int argc, char ** argv)
{
int x=0;
asm volatile("": : :"memory");
__sync_synchronize();
x=1;
asm volatile("": : :"memory");
__sync_synchronize();
x=2;
asm volatile("": : :"memory");
__sync_synchronize();
x=3;
printf("%d",x);
return 0;
}
但是,编译输出文件是:
main:
.LFB24:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
mfence
mfence
movl $3, %edx
movl $.LC0, %esi
movl $1, %edi
xorl %eax, %eax
mfence
call __printf_chk
xorl %eax, %eax
addq $8, %rsp
如果我消除障碍并重新编译,我得到:
main
.LFB24:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl $3, %edx
movl $.LC0, %esi
movl $1, %edi
xorl %eax, %eax
call __printf_chk
xorl %eax, %eax
addq $8, %rsp
都在Ubuntu 14.04.1 LTS,86与gcc -Wall -O2
编译。
预期的结果是,包含内存障碍的代码的输出文件将包含我在源代码中的值的所有赋值,其中包含mfence
。
根据相关的StackOverflow职位 -
gcc memory barrier __sync_synchronize vs asm volatile("": : :"memory")
当在每次迭代增加你的内联汇编,GCC不允许改变操作的顺序,经过阻挡
及以后:
Howe版本,当CPU performes这个代码,它允许重新排序 操作“引擎盖下”,只要它不会破坏内存 排序模型。这意味着执行操作可能不按顺序完成(如果CPU支持该操作,就像现在大多数操作一样)。 HW 围栏会阻止这种情况发生。
但正如你所看到的,与记忆障碍的代码,并没有他们的代码之间的唯一区别在于,前者包含了一个办法,我不希望看到它mfence
,而不是所有的任务被包含在内。
为什么与记忆障碍的文件的输出文件并没有如我expected-为什么mfence
顺序已经被改变?为什么编译器删除了一些任务?是否允许编译器进行优化,即使应用了内存屏障并将每行代码分开了?
引用到存储器屏障类型和使用:
术语:**乱序执行独立于内存重新排序**。即使按顺序的CPU也是流水线式的,并且受益于存储缓冲区,特别是对于L1中错过的商店。 (https://en.wikipedia.org/wiki/MESI_protocol#Memory_Barriers。一旦它们被认为不是推测性的,只有通过内存排序逻辑才能对它们进行跟踪(如果需要,可以强制执行StoreStore和LoadStore排序),直到它们实际上在管道忘记它们之后提交到L1缓存。)'MFENCE'不会序列化流水线;它仅序列化内存操作变为全局可见的顺序。 –