在研究Java Memory Model指令重排、追溯到具体的平台实现时,遇到了类似的在IA32架构下的CPU指令重排问题(与Java无关哈):
简单说,初始时x=0, y=0
p0处理器做
x = 1
r1 = x
r2 = y
p1处理器做
y = 1
r3 = y
r4 = x
体现上述代码的具体mov指令请见最后的原文附图;并且此问题限定x, y区域都是Write-Back类型内存。
简单说,初始时x=0, y=0
p0处理器做
x = 1
r1 = x
r2 = y
p1处理器做
y = 1
r3 = y
r4 = x
体现上述代码的具体mov指令请见最后的原文附图;并且此问题限定x, y区域都是Write-Back类型内存。
问题是:最后结果可以出现r2 = 0且r4 = 0的情况。但我推算的结果是当r2=0时,会得出r4=1;推算过程:
(1) 对p0不允许指令重拍,因为指令1与2是对同一地址读写,指令2与3是LoadLoad指令在IA32下不允许重排;同样,p1的3条指令亦不能重排;(根据《Intel-64-IA32-手册》 section 8.2)
(2) 假设p0的3条指令都在p1的3条指令前执行,这样可得r2=0;
(3) 考虑到p0和p1都会有cache的MESI一致性控制协议(《Intel-64-IA32-手册》 section 11.4),那么对p0的x = 1情况分类:
(3.a) x = 1暂未写回内存,则还在p0的cache中,并且按照MESI协议会通知p1变量x有变动,在p1使用x的时候也会通过snoop方式直接传给p1变量x的最新值x=1;
(3.b) x = 1直接写回内存,那么按照MESI协议,p1的关于x=0的cache line应该会被标记为无效,再r4=x时,也应该读到x=1吧。
(1) 对p0不允许指令重拍,因为指令1与2是对同一地址读写,指令2与3是LoadLoad指令在IA32下不允许重排;同样,p1的3条指令亦不能重排;(根据《Intel-64-IA32-手册》 section 8.2)
(2) 假设p0的3条指令都在p1的3条指令前执行,这样可得r2=0;
(3) 考虑到p0和p1都会有cache的MESI一致性控制协议(《Intel-64-IA32-手册》 section 11.4),那么对p0的x = 1情况分类:
(3.a) x = 1暂未写回内存,则还在p0的cache中,并且按照MESI协议会通知p1变量x有变动,在p1使用x的时候也会通过snoop方式直接传给p1变量x的最新值x=1;
(3.b) x = 1直接写回内存,那么按照MESI协议,p1的关于x=0的cache line应该会被标记为无效,再r4=x时,也应该读到x=1吧。
所以得出在r2=0时,是有r4=1的。向大大们请教下,这个过程哪里有问题呢?谢谢!
上面提到《Intel-64-IA32-手册》,是Intel® 64 and IA-32 Architectures Software Developer Manuals Volume 3 (3A, 3B & 3C): System Programming Guide(http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html);上述问题的原文截图如下
《Intel-64-IA32-手册》8.2.3.5章节写道
