ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Sword 内存屏障-Store Buffer

2021-08-29 14:02:39  阅读:212  来源: 互联网

标签:Buffer cache cpu0 cpu1 buffer Store Sword line store


Store Buffer
     当cpu需要的数据在其他cpu的cache内时,需要请求,并且等待响应,这显然是一个同步行为,优化的方案也很明显,采用异步。

思路大概是在cpu和cache之间加一个store buffer,cpu可以先将数据写到store buffer,同时给其他cpu发送消息,

然后继续做其它事情,等到收到其它cpu发过来的响应消息,再将数据从store buffer移到cache line。

该方案逻辑上有漏洞,需要细化,我们来看几个漏洞。比如有如下代码:

// 初始状态下,假设a,b值都为0,并且a存在cpu1的cache line中(Shared状态),
a = 1;
b = a + 1;
assert(b == 2);
cpu0 要写入a,将a=1写入store buffer,并发出Read Invalidate消息,继续其他指令。
cpu1 收到Read Invalidate,返回Read Response(包含a=0的cache line)和Invalidate ACK,cpu0 收到Read Response,更新cache line(a=0)。
cpu0 开始执行b=a+1,此时cache line中还没有加载b,于是发出Read Invalidate消息,从内存加载b=0,
同时cache line中已有a=0,于是得到b=1,状态为Modified状态。
cpu0 得到 b=1,断言失败。
cpu0 将store buffer中的a=1推送到cache line,然而为时已晚。

造成这个问题的根源在于对同一个cpu存在对a的两份拷贝,一份在cache,一份在store buffer,而cpu计算b=a+1时,a和b的值都来自cache。

仿佛代码的执行顺序变成了这个样子:

b = a + 1;
a = 1;
assert(b == 2);

 

Store Forwarding
    store buffer可能导致破坏程序顺序的问题,硬件工程师在store buffer的基础上,又实现了”store forwarding”技术:,

cpu可以直接从store buffer中加载数据,即支持将cpu存入store buffer的数据传递(forwarding)给后续的加载操作,而不经由cache。

但是在高并发场景下仍然存在漏洞,示例如下:

// 初始状态下,假设a,b值都为0,a存在于cpu1的cache中,b存在于cpu0的cache中,均为Exclusive状态,cpu0执行foo函数,cpu1执行bar函数
void foo() {
    a = 1;
    b = 1;
}
void bar() {
    while (b == 0) continue;
    assert(a == 1)
}
cpu1执行while(b == 0),由于cpu1的Cache中没有b,发出Read b消息
cpu0执行a=1,由于cpu0的cache中没有a,因此它将a(当前值1)写入到store buffer并发出Read Invalidate a消息
cpu0执行b=1,由于b已经存在在cache中,且为Exclusive状态,因此可直接执行写入
cpu0收到Read b消息,将cache中的b(当前值1)返回给cpu1,将b写回到内存,并将cache Line状态改为Shared
cpu1收到包含b的cache line,结束while (b == 0)循环
cpu1执行assert(a == 1),由于此时cpu1 cache line中的a仍然为0并且有效(Exclusive),断言失败
cpu1收到Read Invalidate a消息,返回包含a的cache line,并将本地包含a的cache line置为Invalid,然而已经为时已晚。
cpu0收到cpu1传过来的cache line,然后将store buffer中的a(当前值1)刷新到cache line

出现这个问题的原因在于cpu不知道a, b之间的数据依赖,cpu0对a的写入需要和其他cpu通信,因此有延迟,

而对b的写入直接修改本地cache就行,因此b比a先在cache中生效,导致cpu1读到b=1时,a还存在于store buffer中。

从代码的角度来看,foo函数似乎变成了这个样子:

void foo() {
    b = 1;
    a = 1;
}

foo函数的代码,即使是store forwarding也阻止不了它被cpu"重排",虽然这并没有影响foo函数的正确性,但会影响到所有依赖foo函数赋值顺序的线程。

 

标签:Buffer,cache,cpu0,cpu1,buffer,Store,Sword,line,store
来源: https://www.cnblogs.com/zhanggaofeng/p/15202430.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有