LoadLoad 保证第一个 Load 先于第二个,那么其实就是在第一个 Load 后面加入读内存屏障,阻塞等待 invalidate queue 完全处理完;
StoreStore 保证第一个 Store 先于第二个,那么其实就是在第一个写入后面放写内存屏障,阻塞等待 store buffer 完全刷入 CPU 缓存;
LoadStore 同理,保证第一个 Load 先于第二个 Store,只要 invalidate queue 处理完,那么当前 CPU 中就没有对应的脏数据了,就不需要等待当前的 CPU 的store buffer也清空。
对于 StoreLoad,比较特殊,由于第二个 Load 需要看到 Store 的最新值,也就是更新不能只到 store buffer(在写数据的时候,会先写到store buffer中,之后会刷回主存),同时过期不能存在于 invalidate queue 未处理,所以需要读写内存屏障,即全屏障;也就是说既需要写屏障把store buffer中的数据刷回主存,又需要读屏障来保证invalidate queue中的过期数据都处理完,因此叫做全屏障
invalidate queue是什么呢?可以看看下边
当cpu收到使某个cache失效的消息时,预期的行为是cpu马上执行这个失效操作。但实际上cpu并不会马上执行失效操作,而是先发送确认收到的消息,然后将失效操作加入到invalidate queue中,queue中的操作随后会在适当的时刻执行(并不一定是马上)。之所以需要invalidate queue同样是因为invalidate操作开销比较大,cpu为了执行invalidate操作必须丢弃cache,导致cache命中率下降。这样的好处是能够提高cpu的性能,但同时也导致cache中可能存在过期的数据。
简单总结了一下:
关键就是 等待invalidate queue清空 和 写入store buffer
1、load的,需要等invalidate queue清空,再写入load buffer
2、store的,写入store buffer,再写回主存
3、两者结合的情况的话有两种情况:
(1)loadStore 在写之前读,所以只需要清空invalidate queue,至于后面的store buffer清不清空,已经无所谓,所以无需等待,所以两者并没有强关联的关系,所以这个不算全屏障
(2)SotreLoad 在读之前写,所以一开始就需要先写入store buffer一定要保证写回主存,然后再等待invalidate queue清空,再读入load buffer才算是完成整个操作,是一个完整且紧凑的强关联操作,所以是全屏障