Memory Barrier原理科普

举报
way 发表于 2020/12/21 14:21:04 2020/12/21
【摘要】 https://zhuanlan.zhihu.com/p/94421667现代CPU都是Out-of-Order处理模型,比如流水线,一个指令没有完成,下个指令就出去了,这些指令到底起作用没有,CPU是没法知道的,只能等目标端响应了才能知道。比如你现在有下面三个动作(我们假设a,b,c都是内存变量):a = 1;b = 2;c = 3;写a地址的指令发射出去了,你就该等内存系统反馈是否完成写...

https://zhuanlan.zhihu.com/p/94421667


现代CPU都是Out-of-Order处理模型,比如流水线,一个指令没有完成,下个指令就出去了,这些指令到底起作用没有,CPU是没法知道的,只能等目标端响应了才能知道。
比如你现在有下面三个动作(我们假设a,b,c都是内存变量):
a = 1;
b = 2;
c = 3;
写a地址的指令发射出去了,你就该等内存系统反馈是否完成写入,但写一个DDR的时间常常是上百甚至几百个Cycle,而你这个写的动作,其实只要一个cycle。CPU百无聊赖坐着,你说他怎么办呢?要不别等了,先把b也写了吧……我们要知道现代CPU总线是一个网络,经过这个网络,a先写到内存中,还是b先写到内存中,这难说得很。但其实无所谓的,我们只要保证什么时候读这个a,b的时候,它里面肯定是我们的值就好了,这样我们的程序是没有问题的。
但这样用来写程序是没有问题,用来通讯就有问题了。比如我们上面这个序列是这样的:
a = 1;
b = 2;
a_b_valid = TRUE;
另一个CPU或者设备根据你这个a_b_valid变成TRUE就读a, b的值,但因为没有这个先后保证,a_b_valid更新完了,a和b还没有更新,这样,那个CPU就完蛋了,读了一个错的a和b的值。
这样你就需要加一个mb,像这样:
a = 1;
b = 2;
write_mb();
a_b_valid = TRUE;
这样就创建了一个栅栏,这条指令就是通知CPU,之前发射过的写操作的响应没有全部回来前,你不要再发射内存指令了。这样就能保证a_b_valid更新成功前,a和b一定是更新成功的。
这个mb的行为可以分开读写隔断,也可以同时隔断。为了优化,它可以分很多类型,比如ARM平台的dsb等指令,可以带很多参数,用来隔断读,写,内存,IO,TLB等等不同行为。

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。