Arm64内存屏障

article/2025/9/23 19:56:44

一、内存类型

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

1)普通内存(Normal Memory)

普通内存的特性是,在没有别的写入的情况下,每次读取出来的值都是一样的。针对普通内存,Arm处理器会采用比较激进的优化方式,从而导致指令重排序的问题。

普通内存可以被指定为支持缓存(Cached)或不支持缓存(Non-Cached)。如果两个模块之间不支持数据一致性协议,那么它们之间的共享内存一定是不支持缓存的。

2)设备内存(Device Memory)

设备内存一般是对外部设备的一段内存映射,在没有写入的情况下,可能每次读取出来的值都不一样。也有可能写入这段内存会产生别的边际效应,如触发一个中断。

二、共享域

为了支持数据一致性协议,需要增加硬件很多开销,会降低系统的性能,同时也会增加系统的功耗。但是,很多时候并不需要系统中的所有模块之间都保持数据一致性,而只需要在系统中的某些模块之间保证数据一致性就行了。因此,需要对系统中的所有模块,根据数据一致性的要求,做出更细粒度的划分。

ARMv8架构将这种划分称作为域(Domain),并且一共划分成了四类:

1)非共享(Non-shareable)域

处于这个域中的内存只由当前CPU核访问,既然只能自己访问,那当然不用考虑跟系统中的其它模块,如其它CPU核或其它设备之间的数据同步问题。所以,如果一个内存区域是非共享的,系统中没有任何硬件会保证其缓存一致性。如果一不小心共享出去了,别的CPU核可以访问了,那必须由软件自己来保证其一致性。

2)内部共享(Inner Shareable)域

处于这个域中的内存可以由系统中的多个模块同时访问,并且系统硬件保证对于这段内存,对于处于同一个内部共享域中的所有模块,保证缓存一致性。

一个系统中可以同时存在多个内部共享域,对一个内部共享域做出的操作不会影响另外一个内部共享域。

3)外部共享(Outer Shareable)域

处于这个域中的内存也可以由系统中的多个模块同时访问,并且系统硬件保证对于这段内存,对于处于同一个外部共享域中的所有模块,保证缓存一致性。外部共享域可以包含一个或多个内部共享域,但是一个内部共享域只能属于一个外部共享域,不能被多个外部共享域共享。

对一个外部共享域做出的操作会影响到其包含的所有的内部共享域。

4)全系统共享(Full System)域

这个很好理解,表示对内存的修改可以被系统中的所有模块都感知到。

在一个具体的系统中,不同域的划分是由硬件平台设计者决定的,不由软件控制。并且,Arm的文档中也没有提及具体要怎么划分。但有一些指导原则,一般在一个操作系统中可以看到的所有CPU核要分配在一个内部域里面,如下图所示:

这些域的划分只是为了更细粒度的管理内存的缓存一致性,理论上所有内存都放到全系统共享域中,从功能上说也可以,但会影响性能。

可缓存性和共享性一定是对普通内存才有的概念。设备内存一定是不支持缓存的,且是外部共享的。

三、屏障

前面说的缓存一致性保证的是对同一段内存的操作,系统中的所有模块,在经过一定的时间后,大家读取到的值最终是一样的。比如说,CPU0对全局变量A写入1,而CPU1对全局变量A写入2,那么经过一定时间后,两颗CPU看到全局变量的值要么都是1要么都是2,不会一个是1一个是2。但是,缓存一致性并不能保证内存操作的顺序,这个需要内存屏障来保证。

在ARMv8架构下,共有下面四种指令提供所谓的屏障的功能:

1)指令同步屏障(ISB, Instruction Synchronization Barrier)

Arm系统有两种类型的缓存,一种是指令缓存(I-Cache),还有一种是数据缓存(D-Cache)。因此,内存屏障指令还要区分是对指令的还是针对普通数据的。

指令同步屏障会清洗当前CPU核的流水线和指令预取缓冲,以保证所有这条指令前面的指令都执行完毕之后,才执行这条指令后面的指令。

2)数据内存屏障(DMB, Data Memory Barrier)

数据内存屏障保证,站在系统中其它同属一个域的模块来看,在这条指令之前的存储器访问操作(包括加载或存储)一定比在这条指令之后的存储器访问操作,先被感知到。也就是说,数据内存屏障指令阻止在这条指令之前的所有存储器访问操作被重排序到这条指令之后,同时也会阻止这条指令之后的所有存储器访问指令被重排序到这条指令之前。

3)数据同步屏障(DSB, Data Synchronization Barrier)

数据同步屏障在保证和前面的数据内存屏障相同的存储器访问操作顺序的同时,还会保证在这条指令之后的所有指令(不光是存储器操作指令)一定会在这条指令之后才会执行。因此,数据同步屏障比数据内存屏障更加严格。

DMB和DSB指令都需要带一个参数,这个参数指明了数据屏障指令的作用范围和针对的共享域。共享域前面说过了,一共有四种。作用范围表示数据屏障指令具体对哪些存储器访问操作起作用,ARMv8共定义了三种,分别是:

  1. Load - Load, Load - Store:表示内存屏障保证其之前的所有加载操作一定在其之前完成,其之后的所有加载和存储操作一定在其之后才开始,但是其之前的存储操作有可能会在其之后才执行。
  2. Store - Store:表示内存屏障保证其之前的所有存储操作一定在其之前完成,而其之后的存储操作一定在其之后才能开始,但是对于加载操作没有任何限制。
  3. Any - Any:表示内存屏障保证其之前的所有加载和存储操作一定在其之前完成,而其后的所有加载和存储操作一定在其之后才能开始。

注意,ARMv8不提供所谓的Store-Load型的顺序保证,如果真的需要这种保证,只能使用Any-Any型的。关于DMB和DSB指令的参数,可以总结为如下表格:

参数作用范围共享域
OSHLDLoad - Load, Load - Store外部共享域
OSHSTStore - Store外部共享域
OSHAny - Any外部共享域
NSHLDLoad - Load, Load - Store非共享域
NSHSTStore - Store非共享域
NSHAny - Any非共享域
ISHLDLoad - Load, Load - Store内部共享域
ISHSTStore - Store内部共享域
ISHAny - Any内部共享域
LDLoad - Load, Load - Store全系统共享域
STStore - Store全系统共享域
SYAny - Any全系统共享域

4)单向屏障(Load-Acquire, Store-Release)

前面的所有屏障指令对于ARMv8之前所有的架构都有效,在ARMv8架构下,还加入了一类单向屏障指令,也就是所谓的Load-Acquire(LDAR指令)和Store-Release(STLR指令)。

普通的内存屏障一般是双向的,也就是可以控制内存屏障之前的某些存储操作要在内存屏障之前完成,并且内存屏障之后的某些存储操作要在内存屏障之后才能开始。但是Load-Acquire和Store-Release却只限定了单个方向的:

  • Load-Acquire:这条指令之后的所有加载和存储操作一定不会被重排序到这条指令之前,但是没有要求这条指令之前的所有加载和存储操作一定不能被重排序到这条指令之后。所以,可以看出来,这条指令是个单向屏障,只挡住了后面出现的所有内存操作指令,但是没有挡住这条指令之前的所有内存操作指令。
  • Store-Release:这条指令之前的所有加载和存储才做一定不会被重排序到这条指令之后,但是没有要求这条指令之后的所有加载和存储操作一定不能被重排序到这条指令之前。所以,这条指令也是一个单向屏障,只挡住了前面出现的所有内存操作指令,但是没有挡住这条指令之后的所有内存操作指令。

LDAR和STLR指令也有作用的共享域,只不过没有明确在指令中表示出来。这两条指令的共享域就是它们操作的内存的共享域。比如,如果LDAR指令读取内存的地址是属于内部共享域的,那么这条指令锁提供的屏障也只是作用于这个内部共享域。

还有一点,如果LDAR指令出现在STLR指令之后,处理器也会保证LDAR指令一定不会被重排序到STLR指令之前。

单向屏障的作用范围可以总结为下面这张图:

四、Linux内核中对内存屏障的定义

Linux将不同类型的内存屏障和ARMv8提供的屏障指令都做了映射(代码位于arch/arm64/include/asm/barrier.h中):

#define isb()		asm volatile("isb" : : : "memory")
#define dmb(opt)	asm volatile("dmb " #opt : : : "memory")
#define dsb(opt)	asm volatile("dsb " #opt : : : "memory")
......
#define spec_bar()	asm volatile(ALTERNATIVE("dsb nsh\nisb\n",		\SB_BARRIER_INSN"nop\n",	\ARM64_HAS_SB))#define mb()		dsb(sy)
#define rmb()		dsb(ld)
#define wmb()		dsb(st)#define dma_rmb()	dmb(oshld)
#define dma_wmb()	dmb(oshst)
......
#define __smp_mb()	dmb(ish)
#define __smp_rmb()	dmb(ishld)
#define __smp_wmb()	dmb(ishst)

没有带任何前缀的mb()、rmb()和wmb()都是映射到了DSB指令,并且针对的共享域是最大的全系统共享域。作用范围最大的是mb()屏障,它被映射成限制Any-Any类型的,rmb()被映射成限制Load-Load, Load-Store类型的,搞好完美匹配对读内存屏障的要求,wmb()被映射成限制Store-Store类型的。

DMA设备都是属于外部共享域,所以dma_rmb()的参数是oshld,而dma_wmb的参数是oshst。并且它们只是限制对内存的操作,不限制其它指令,所以使用的是DMB指令。

带__smp_前缀的,表示限制的是所有CPU核,前面提到过一般在一个操作系统中可以看到的所有CPU核要分配在一个内部域里面,因此这里使用的参数都以i打头,表示作用域是内部共享域。

spec_bar()宏比较特殊,表示禁止当前CPU核的预测机制,使用了DSB指令,作用域是非共享域,只对当前CPU核有效。


http://chatgpt.dhexx.cn/article/wRVx4WSw.shtml

相关文章

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…

javascript实现较全功能注册表单

今天笔者仿照京东注册表单&#xff0c;进行设计了一个表单案例&#xff0c;在这个案例中&#xff0c;可以完成常见表单注册的绝大部分功能&#xff0c;比如表单注册信息的验证&#xff0c;校验用户名&#xff0c;校验密码强弱&#xff0c;注册信息的追踪。这其中用到了正则表达…

HTML5实现注册表单

注册表单代码 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title>注册账号</title></head><body><form action"getSend.php" method"GET"><fieldset><legend>注册…

JQuery用户注册表单验证

使用jquery编写代码实现用户注册表单的验证功能&#xff1a; 用户名、密码、确认密码和手机号不能为空密码长度在8~20位之间&#xff0c;密码至少由数字、字母或下划线其中两种组成确认密码必须和密码一致手机号应该是11位&#xff0c;并且是合法的手机号段验证码随机生成&…