学内核之十一:ARM64屏障指令使用指南

article/2025/9/23 19:12:31

关于屏障指令,主要是与乱序有关。特别是在内核开发中,这是一个非常重要的主题。屏障由乱序引起,乱序则是由优化引起。

自从摩尔定律不断被逼近极限,半导体的优化不再单纯通过提升频率来实现。多核心、并发执行变成了主流的优化思路。

让代码并发,有多种方案。一种是代码编写者。通过将代码之间的逻辑关系梳理,让代码做到并发执行。分而治之就是这种思路的典型代表。

写代码时就考虑并发,更多是上层的逻辑和数据依赖的解除。因为软件的复杂性,编写者水平的差异等,这种方法更多是在较高的层次发挥作用。工业实践中,很少考虑微观层面的依赖关系。比如变量之间的前后优化关系,这方面很琐碎,小范围很难起到明显的优化效果。我们还是将代码看成顺序执行来理解和实现业务逻辑。

真正让这种微观层面的优化发挥效果的是编译器的优化。最直观的,这是一种全量的处理,所有被编译的源代码都会被统一处理,因此可以积少成多,达到整体的优化效果。另外,工具处理也明显提升了效率。

为了并发,编译器的优化中有一项策略是乱序。编译器会根据数据的依赖关系,结合硬件架构的缓存特性,对代码进行重排。重排后的代码,并不改变工作逻辑,但是会提升执行效率。举个我们了解的统筹数学方面的例子来类比。假设我们要完成两件事,烧水和炒菜。我们可以先烧水后炒菜,也可以先炒菜后烧水,其实还可以打乱这个顺序,比如烧水的时候,完成切菜的准备工作。这样总体来看,还是正常完成了烧水和炒菜这两件事,但是穿插的做法,因为并行,提升了效率,减少了总的时间花费。

事物都有两面性,编译器的优化带来性能提升的同时,可能还会引入问题。比如内核中,有些指令虽然没有依赖关系,但是却有顺序要求,比如切换任务时候,编译器看到的可能是一堆无关指令的执行,但是实际上,这些指令的作用内在的要求顺序不能变,否则结果就是非预期的。这时候,可能就需要代码编写者明确告诉编译器,这个地方不要做乱序优化。这种操作,一般称为屏障。就是加一个障碍,要求其前后指令的顺序在编译过程中,不要被打乱。

到这里,我们由优化说到了乱序,由乱序说到了屏障。不过我们今天的主角是下面将要讲的屏障。

上面说的乱序是编译乱序。除了编译乱序,还有执行乱序。执行乱序发生在CPU执行指令的过程中。执行乱序的部分原因同编译乱序是类似的。CPU可能先执行当前指令之后的指令,比如因为多核心间cache同步的原因,当前指令的执行需要等待,此时就可以先执行后面的指令,等同步完成,再一起生效。另外,为了提升效率,CPU可能预执行一部分指令,因为内部的执行机构存在多个。这样也可以提升效率。对于这种预执行,可能会预判失败,特别是分支预测时。但是,如果预测成功,则会明显提升效率。

这里,我们只是讲述了一个总体的大概过程,要了解这其中的细节,就需要深入理解代码执行和CPU实现了。

可以看到,执行乱序也是优化的一部分。既然执行存在乱序,那么这种乱序,有没有可能如编译乱序那样,产生问题呢?这就涉及到CPU的一致性了。正常情况来讲,乱序执行只是在最终结果产生之前乱序,真正输出结果的时候,CPU还是按照设计逻辑顺序输出的。也就是乱序执行过程,大部分是CPU内部缓存了指令的执行结果。所以,普通代码的乱序不会产生问题。既然这样说了,那就是留了口子,乱序执行还是有问题存在的。对于强一致性的CPU架构,在部分场景下,CPU并不会乱序,而对于弱一致性的CPU,像ARM,则在很多情况下都存在乱序。比如ARM对读写的各种情况,R-R/R-W/W-R/W-W都可能存在乱序。这样一来,对程序设计者,就有更高的要求。但是,归根结底,无论是强一致性还是弱一致性,代码设计者都要时时有乱序的意识,来规避乱序可能带来的问题。

我们举个例子来看看。考虑这样一种场景,CPU核心先向某个内存地址写入数据,然后通知某个外设到这个地址去读取数据。这个外设比如是DMA。显然,这个操作顺序是要被保证的,如果CPU先执行通知DMA,再写数据,那么DMA拿到的就不是正确数据。

既然执行乱序也可能引入问题(其实是很容易引入问题),那么该如何应对呢?这就需要今天我们要讨论的主角----屏障指令登场了。另外,说明的是,下面的内容参考自宋宝华老师的直播课。

这里,屏障指令的目的不变,仍然是限制乱序,也就是限制CPU执行时不要乱序执行。不过,不同于编译屏障,执行屏障指令,可以在不同层面展开。CPU提供了不同的指令来达成目标。这些指令内容包括了dmb/dsb/isb/ldar/star,参数包括了ish/ishld/ishst/osh/oshld/oshst/sy/ld/st。二者结合,产生了很多的组合,这些组合都属于屏障指令,它们之间有什么区别呢?这就是今天我们要重点说明的。理解这些,对理解内核中的屏障指令,有很大的帮助。

我们先来看看上面的命令。在ARM手册中,有如下的相关说明:

关于参数部分,ARM手册中有相关说明如下:

所谓组合,就是二者结合起来。如下面的例子

采用了 DMB + ISHLD

关于上述屏障指令的执行,宋宝华老师总结了三个要素,分别是:

1 谁和谁之间

2 在什么地方

3 在什么方向

下面,我们一个一个来看。

关于谁和谁的问题,是由指令本身解决的。DMB是内存屏障,也就是规范的内存的访问顺序。DSB是内存和其他部件的,比如和系统寄存器。ISB是流水指令的。比如tlb更新后,需要执行ISB,因为物理地址和虚拟地址的对应改变了,CPU内部流水线没有执行的指令不适合再执行,执行ISB可以清空流水线。

关于什么地方、什么方向的问题,是在参数部分解决的。对于“地方”,如上图所示,手册提到了inner、outer和full system三个域。分别对应了参数的ish、osh和sy/ld/st。对于inner来讲,就是CPU内部执行同一份代码的部件之间的关系。比如各个核心之间。Outer则是CPU核心和其他外部部件,比如DMA、GPU之间。而full system则是不同的CPU子系统之间,比如CPU中的实时核心系统和非实时核心系统之间。

关于方向,有读-读、读-写、写-写以及任意,也就是无论任何方向。分别对应了参数里的LD、ST等。

综合起来,就是谁和谁之间,在什么地方,什么方向要进行屏障处理。比如上面例子中的DMB ISHLD,就是在inner里,内存之间,读-读和读-写时,需要进行屏障。

这里,还有一个没有提到,就是LDAR和STLR。这是一个单方向的屏障指令,效果如手册中的下图所示:

从上图可以看出,这两个指令就像是一个水阀门。LDAR是开口向下的阀门效果:

 

上面的指令可以穿过,但是下面的指令则不行。

而STLR则是开口向上的阀门:

 

下面的指令可以穿过,但是上面的指令则不行。

如上图所示,当把两个指令放在一起,那么中间的指令既不能向下穿过,也不能向上穿过,自然就限制在这两条指令之间,从而形成一个关键区,类似加锁的效果。

到这里,我们介绍了多个屏障指令。可能有读者就要问了,不就是限制CPU不要乱序执行吗,为啥要这么多的指令。这还是跟效率有关。我们当然可以只提供一个指令,适应所有情况,但是,这必然就会出现杀鸡使用宰牛刀的情况。设想一个工程任务的有限无环图。从开始到结束,中间经过多个节点,每个节点代表一个里程点。一些里程点之间可能存在前后依赖关系。我们可以精细调整依赖关系,从而得到一个最短的工期路径,也可以采用粗放管理模式,简单排序各个节点,从而也得到一个满足依赖要求的工程路径,就如前面炒菜烧水的例子,严格一项一项来。虽然两种方式都能达到目的,但是精细控制显然能够缩短时间。当CPU里,这种指令大量存在时,整体改变的效果就会凸显,这就是典型的量变引起质变。

针对上面这些情况,内核提供了一些封装,编译跨平台的使用。

__smp_load_acquire()

__smp_store_acquire()

这两个是对LDAR 和 STAR的封装

__smp_mb()          dmb ish

__smp_rmb           dmb ishld

__smp_wmb          dmb ishst

上面是对内部域内存访问屏障的封装

dma_rb()                  dmb osh

dma_rmb()               dmb oshld

dma_wmb()             dmb_oshst

上面几条指令是用于CPU和外部域直接的内存访问屏障。DMA就是此含义。

mb()           dsb sy

rmb()          dsb lt

wmb           dsb st

上面的几条是用于系统域内存和其他部件,比如系统寄存器访问的屏障指令。

显然,内存屏障指令的可能组合不止这些。不过,就常用情况来看,这些应该是能够满足大部分情况的。如果确实需要特殊组合,可以直接汇编指令完成。

最后,在宋宝华老师的直播课上,提到了上海交大陈海波教授团队发表的一篇有关屏障性能的分析。其中的结论这里就直接复制粘贴了:

鉴于篇幅关系,直播课的例子就不再这里列出了。

最后说两点,1是计算机领域精益求精永不过时;2是将复杂的计算机概念通过简练的语言讲述清楚,这并不容易。宋宝华老师和吴军老师都是这方面的优秀代表。


http://chatgpt.dhexx.cn/article/6MObh2Ki.shtml

相关文章

WTM

WTM的由来 WalkingTec.Mvvm框架(简称WTM)最早开发与2013年,基于Asp.net MVC3 和 最早的Entity Framework, 当初主要是为了解决公司内部开发效率低,代码风格不统一的问题。经历了四年间数十个项目的考验,框架逐步的完善…

WMIC使用

目录 WMI 远程创建进程 wmiexec wmiexec.py wmiexec.vbs Invoke-WmiCommand.ps1 Invoke-WMIMethod WMI WMI全称“windows管理规范”,是一个windows服务。从win2003开始一直存在。它原本的作用是方便管理员对windows主机进行管理。因此在内网渗透中&#xff…

Arm64内存屏障

一、内存类型 ARMv8架构将系统中所有的内存,按照它们的特性,划分成两种,即普通内存和设备内存。并且它们是互斥的,也就是说系统中的某段内存要么是普通内存,要么是设备内存,不能都是。 1)普通…

barrier(wmb,mb,rmb)和cache coherence

http://www.linuxforum.net/forum/gshowflat.php?Cat&BoardlinuxK&Number428239&page5&viewcollapsed&sb5&oall&fpart 注: 这里的barrier 指的是wmb, rmb, mb. 一 直找不到合适的资料说明barrier和 Cache coherence 之间的关系. 在<<ldd>…

mw与dbm换算

1. 基本概念 dbm&#xff1a;意即分贝毫X&#xff0c;可以表示分贝毫伏&#xff0c;或者分贝毫瓦。他是一个表示功率绝对值的单位。 功率/电平&#xff08;dBm&#xff09;&#xff1a;放大器的输出能力&#xff0c;一般单位为w、mw、dBm。dBm是取1mw作基准值&#xff0c;以分贝…

[architecture]-DBG、DMB、DSB 和 ISB指令介绍

快速链接: . &#x1f449;&#x1f449;&#x1f449; 个人博客笔记导读目录(全部) &#x1f448;&#x1f448;&#x1f448; 付费专栏-付费课程 【购买须知】: 【精选】ARMv8/ARMv9架构入门到精通-[目录] &#x1f448;&#x1f448;&#x1f448; 1、DBG、DMB、DSB 和 IS…

WMB在项目中的应用

提纲&#xff1a; 1、 WebSphere Message Broker Introduction a) ESB Overview b) Message Broker Overview c) Message Broker Performance Report 2、 ESB Project Sharing 内容&#xff1a; 1、 Message Broker是建立在MQ基础之上的。【说明消息中间件对于MB是何等的重…

【HTML/CSS】简单登录注册表单制作

实现效果&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthde…

登录注册弹出框html,jQuery实现弹出窗口中切换登录与注册表单

当点击页面中的登录或注册按钮时,将会弹出一个模态窗口,就是一个弹出层,我们可以在弹出层上轻松的切换登录与注册表单,极大的方便用户,不需要关闭层再去点击转向其他操作,在很多网站上已经广泛应用。 本文结合实例,通过使用jQuery以及CSS3和HTML5技术实现这一效果。 HTM…

html5漂亮的登录与注册界面设计,漂亮的网页登陆/注册表单设计

漂亮的网页登陆/注册表单设计 7月 4, 2012 评论 Sponsor 网页设计中登陆和注册表单是非常常用的&#xff0c;而且使用率也非常高&#xff0c;一个表单的设计其实也不是简单的事情&#xff0c;你要考虑很多用户体验&#xff0c;有的喜欢把注册和登陆都放在一个页面&#xff0c;有…

3.6 用正则表达式验证注册表单页面

用正则表达式验证注册表单页面 制作一张注册页&#xff0c;页面自行设计&#xff0c;页面元素命名自行设置&#xff0c;需要验证如下信息&#xff1a; 用户名&#xff1a;&#xff08;允许2-4个汉字&#xff09; 电话&#xff1a;&#xff08;开头3或4位,”-”号隔开&#xff…

制作一个注册表单页面

制作一个表单注册页面 在Dreamweaver中创建一个.html文件&#xff0c;添加一个11行2列的表格&#xff0c;左侧的内容是手动输入&#xff08;第一行也手动输入&#xff09;&#xff0c;右侧的内容是用代码来写的&#xff08;最后一行也是用代码来写&#xff09;&#xff08;用…

Html+CSS实现简单的注册表单

目录 预览 教程如下 首先新建一个HTML文件 接下来,我们在body标签的内部编写网页的主题内容 新建一个CSS文件 label: input: .submit_btn: CSS 居中显示: 这就结束啦!! 完整代码 html: css: 这次和大家分享一个用html语言实现的一个简单的注册表单,豪华升级版在文…

js实现注册表单验证

js实现注册表单验证 验证用户名必须为&#xff1a;要求6-20位&#xff0c;只能有大小写字母和数字&#xff0c;并且大小写字母和数字都要有 var name_re/[0-9a-zA-Z]{3,8}/; var pwd_re/^\S{6,20}$/; <!DOCTYPE html> <html> <head><meta charset"…

A.2 实验2:注册表单和登录表单

A.2 实验2&#xff1a;注册表单和登录表单 A.2.1目的与要求A.2.2 实验内容 本实验初步创建用于学生注册的模块文件registration.php和用于登录的模块文件login.php。这两个模块文件都保存于教务选课系统项目xk中的“源文件”结点。 本实验主要完成注册表单和登录表单外观的设计…

HTML注册表单的页面制作

效果1&#xff1a;效果2&#xff1a; 效果1&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><tit…

【HTML | CSS | JS】耗时一下午,整理出了一个精美的响应式登陆注册表单(附源码)

&#x1f482;作者简介&#xff1a; THUNDER王&#xff0c;一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学会计学专业大二本科在读&#xff0c;同时任汉硕云&#xff08;广东&#xff09;科技有限公司ABAP开发顾问。在学习工作中&#xff0c;我通常使用偏后…

html的练习之用户注册表单

这是最终效果图&#xff0c;具体实现代码在下面&#xff0c;一些注意点在代码里有注释&#xff0c;对是新手学习html基础比较友好。 本人刚接触前端学习&#xff0c;这里当作作业的练习&#xff0c;不足之处&#xff0c;欢迎交流&#xff0c;共同进步&#xff01; <!DOCTYPE…

Java Web注册表单编写

编写注册表单 1.要做下列的这样一个表单信息&#xff1a; 2.方法主体里面添加表单 < form action“提交地址” method“post”> 表单内容&#xff08;包括按钮&#xff0c;输入框&#xff0c;选择框等&#xff09;< /form> 我们可以看到在测试中的结果&#xff…

003_用户注册表单【HTML-form表单】

文章目录 一、HTML-form表单1、用户注册表单2、用户注册表单 - 小升级3、HTML5表单新特性① 新的input type 一、HTML-form表单 1、用户注册表单 <html><head><meta charset"UTF-8"><title>HTML用户注册表单</title></head>&l…