• 正文
  • 相关推荐
申请入驻 产业图谱

一文看懂ARM架构的原子操作

10/27 15:41
1688
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

原子操作是保证指令以原子的方式执行,执行过程不会被打断。例如一条i++指令,不管该指令被反汇编成多少条指令,这些指令之间是不会被打断的。如果处理器还是用原来的ldr,add,str这三条指令,这些指令的属性并不能保证不被打断,此时需要新的指令告诉cpu不能打断该执行过程。

ARMv8使用两种方式来实现原子操作: 一种是独占内存访问指令 (load-exclusive和store-exclusive),这种方式也叫连接加载(load-link)/条件存储(store-conditional),也就是常说的LL/SC操作;另一种是ARMv8.1新支持的LSE指令

1. 独占内存访问指令

LL/SC操作最早用于并发与同步访问内存的CPU指令,它分为两部分。第一部分(LL)表示从地址中读取值,并且处理器监控该值,看看其他处理器是否会修改该内存地址。第二部分(SC)表示如果这段时间内其他处理器没有修改该内存地址,则把新值写入该地址,如果SC失败,那么重新开始整个操作。ARMv8通过LDXR和STXR指令来实现LL/SC机制

ldxr指令是以内存独占加载指令,它从内存中以独占的方式加载内存地址的值到通用寄存器。以下是LDXR指令的原型,它把Xn或者SP地址的值原子地加载到Xt寄存器里。

ldxr <xt>, [xn | sp]

stxr指令是内存独占存储指令,它把Xt寄存器的值原子地存储到到Xn或者SP地址里,执行的结果反映到Ws寄存器中。若Ws寄存器为0, 说明ldxr和stxr指令执行完成;如果结果不为0,说明执行错误,需要重新跳到ldxr处重新执行原子加载和原子存储。

stxr <ws>, <xt>, [xn, sp]

LDXP和STXP是多字节独占内存访问指令,一条指令可以独占地加载和存储16字节,也就是说这两条指令能够实现两个数据的同时操作。

ldxp <xt1>, <xt2>, [xn | sp]
stxp <ws>, <xt1>, <xt2>, [xn | sp] 

应用场景:  ldxr和stxr指令可以和加载-获取,存储-释放内存屏障原语结合使用。构成一个类似临界区的内存屏障。在一些自旋锁的实现场景下非常有用。

独占内存访问的工作原理

独占监视器(exclusive monitor)用来监控对内存的访问。独占监视器是一个硬件状态机,用于跟踪读-修改-写序列,并支持Load和Store操作。exclusive monitor一共有两个状态:开放访问状态和独占访问状态

当CPU执行LDXR指令时,独占监视器会把对应内存地址标记为独占访问模式,保证以独占的方式来访问这个内存地址;而STXR是有条件的存储指令,当CPU执行STXR指令将新数据写入到LDXR指令标记的独占访问内存地址时,会根据独占监视器的状态来进行处理:

    若独占监视器为独占访问状态,那么STRX指令执行成功,并且独占监视器会切换状态到开放访问状态;若独占监视器为开放访问状态,则STRX指令执行失败,数据无法存储。

ARMv8体系提供了三类独占监视器:

    本地独占监视器(local monitor)内部缓存一致性全局独占监视器(internal coherent global monitor)外部全局独占监视器(external global monitor)

2. LSE指令

LL/SC操作本质上是多个CPU核竞争某个内存变量的独占访问,当系统处理器的数量很少时,这可以正常工作;当增加处理器的数量时,处理器之间的竞争冲突会加剧,这会严重影响系统系统;再加上Cache的影响,先前访问到内存变量的处理器会更容易再次获得变量的访问权,这使得多核间访问变量的公平性也难以保证。

ARMv8.1架构新增了LSE(Large System Extension)扩展,LSE提供多种原子操作指令,用于替代原来的LL/SC机制。LSE提升了多处理器系统中原子操作的性能,可以在单个指令中提供不可中断的读-修改-写序列。原子指令可以在指定的内存位置上执行简单的算术或逻辑操作,并将更新的值返回给处理器。原子内存访问操作需要AMBA总线中的CHI支持。

LSE主要新增了三类指令:

    原子内存访问指令,包含LD<op>和ST<op>,其中<op>可以是ADD、CLR、EOR、SET、SMAX、SMIN、UMAX和UMIN;比较并交换指令(Compare And Swap),包括CAS和CASP等;交换指令,SWP。

原子内存操作指令

原子内存操作指令分成两类:原子加载指令和原子存储指令。原子内存访问指令的格式如下:

ld<op>  <xs>, <xt>, [<xn|sp>]st<op>  <xs>, [<xn|sp>]

支持的原子操作后缀:

CAS指令

CAS指令的格式如下:

cas <Ws>, <Wt>, [<Xn|SP>{,#0}]cas <Xs>, <Xt>, [<Xn|SP>{,#0}]
casp <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>{,#0}]casp <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>{,#0}]

SWP指令

交换指令的指令格式如下:

swp <Ws>, <Wt>, [<Xn|SP>]swp <Xs>, <Xt>, [<Xn|SP>]

参考:

    ARM64体系结构编程与实践

浅析ARMv8体系结构:原子操作_原子内存访问-CSDN博客

相关推荐