Init: int x = y = 0;
thr1 thr2
---- ----
y = 1; x = 1; WRITE to global variables
a = x; b = y; READ from global variables
print(a); print(b);
在上面以TSO内存模型运行的代码段中,众所周知,两个线程都可以同时打印0
,因为CPU可以在指令执行之前对命令进行重新排序以执行读取指令(即线程的第二行)。写指令。
然后,将发生什么事情,我们在读取指令上插入了断点,而在命中断点时却继续执行,除了执行任何操作外,什么都不做?两个线程仍然可以同时打印0
,还是断点阻止了重新排序?
我假设使用x86-64体系结构和x86-TSO内存模型。但是,如果给出架构(或存储器模型)之间的任何区别,将是可以理解的。另外,我猜硬件断点和软件断点不会在结果上有所不同(因为它们都触发异常,并且x86体系结构以类似方式处理它们)。这个猜测正确吗?
对于与https://preshing.com/20120515/memory-reordering-caught-in-the-act/相同的情况,我假设这是汇编的伪代码(不是C,可能会发生大量编译时优化)StoreLoad重新排序的位置将可见。
带有断点处理程序的断点可以立即返回,这只是序列化指令(如CPUID或IRET)的一种非常昂贵的选择,该序列化指令可确保所有先前的指令均已执行,并且所有先前的存储都将提交给相干缓存(即清空存储缓冲区)。
原因是从断点返回可能涉及IRET,这是一个序列化指令。(就像MFENCE一样,还可以序列化无序的exec)。
所以是的,断点是其他线程观察到的内存重新排序的全部障碍。
这适用于硬件断点或软件断点,其中调试器必须还原原始指令的第一个字节以使其能够正常执行,而不是0xcc int3
软件断点。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句