[RFC]RISC-V内存一致性模型

原文:https://gitee.com/laokz/OS-kernel-test/blob/master/memorder/riscv.md

RFC:请求批评指正,勿作引用。本文未解释内存一致性基本概念

《The RISC-V Instruction Set Manual, Volume I: User-Level ISA》明确规范了RISC-V的内存一致性模型,称为“RVWMO” (RISC-V Weak Memory Ordering)。RVWMO主要遵循了RC(release consistency)理论模型,用较少的内存访问顺序约束,为硬件实现和性能优化提供了宽松的条件;同时,禁止若干过于复杂费解的乱序情况,方便了软件程序的开发利用。总体上RVWMO是一种弱内存序模型。

为了便于从x86体系结构向RISC-V迁移,规范还明确了一个称为“Ztso”的标准扩展,提供完全兼容x86架构的RVTSO(RISC-V Total Store Ordering)内存模型。本文主要聚焦RVWMO,从软件视角梳理总结了RISC-V内存一致性模型主要内容。

RISC-V是正处于发展阶段的新兴指令集架构,RVWMO也是如此。这里描述的内容源自2019年最后发布的版本。

0、写在前面

为了避免歧义,在介绍RVWMO前先说明几个问题:

  • 用hart表示执行线程或执行单元。RISC-V使用hart一词表示一个逻辑CPU, 即一个硬件线程(超线程)。比如一个双核处理器,每核两个硬件线程,则该处理器有四个hart。hart不仅限于通常意义的处理器范畴,设备控制器甚至CPU集成的内存管理单元(MMU)都可以是hart。这些hart之间共享内存构成了内存乱序的源泉。

  • 指令执行用词。指令发生(happen)、执行(perform、execute)、完成(complete)这几个词对硬件来说有显著区别,但对于软件程序员,并不关心硬件如何分解执行指令,反而关心的是一条指令要么执行了,看到了结果,要么没执行。本文为软件视角,因此在使用这些词汇时,除特别说明外均指代同一含义。

  • 忽略内存对齐和大小问题。内存访问顺序约束的有效性依赖内存地址对齐和大小,未对齐的地址、超过机器字的大小,对内存访问顺序有复杂的影响,一般规律是拆分成多个自然对齐的访存指令,但需要根据规范和具体实现专门考察。本文忽略这一问题,假定所有的内存访问都是“自然对齐”、“自然大小”,都是原子性的访问(single-copy atomicity)。

  • 内存模型与具体实现是两回事。看似废话但值得一提。RVWMO是关于内存访问顺序约束的软硬件接口规范,明确了RISC-V合规架构最少要遵守的规则,提供了“最弱”的内存序约束;但是不排斥具体实现采取更加保守的策略,提供“更强”的内存序约束。因此,RVWMO上的乱序问题,包括litmus模拟测试中的乱序结果,在真实机器上并不必然存在!类似实验数据在《A Tutorial Introduction to the ARM and POWER Relaxed Memory Models》第4.7节可查到。明确这一点仅是为了更加深入地理解内存模型,编程实践中应遵循RVWMO模型以保证最大的兼容性。当然如果你的软件专用于特定机器,根据其特性忽视一些乱序问题可能会有效益。

  • 几个符号表示xxx ->po yyy表示程序序中指令xxx在yyy之前,xxx ->ppo yyy表示全局序和程序序中指令xxx都在yyy之前。

一、规则

目前RVWMO只是规范了常规内存的一致性要求,没有规范I/O内存的行为。RVWMO明确了13条规则、4条公理,为便于记忆和理解,可以归纳总结为以下4句话:

1. 遵守多拷贝原子性(multi-copy atomicity)

RVWMO通过全局序(global memory order)定义内存访问顺序约束,对于不允许乱序的情况称为“保留程序序”(preserved program order,PPO)。全局序即所有并行(并发)线程在内存系统中形成的最终内存访问顺序,各个线程对这个全局序的观察都是一致的,除了store buffer带来的“写后读”情况。store buffer是hart私有缓存,用于暂时存储要写入内存系统的数据,这里的数据对本hart可见,即写后再读可以读到这个写入的值,但对其它hart不可见,也因此双方可能观察到不一样的访问顺序。RISC-V包容这种情况。

为了形成一致的全局序,一个hart如果看到了另一个hart的写,则必须所有的hart都看到了这个写,否则会出现不一致(实际硬件实现并不一定有这种“同时看到”时间保证)。这个特性称为多拷贝原子性。也因为包容“写后读”情况,有的称这种原子性为other-multi-copy atomicity。

有了多拷贝原子性保证,程序员就无需再担心“因果性”(causality)、“累积性”(cumulativity)等令人头痛的问题。奇怪的是,规范正文中并没有明确说明这一特性,而仅是在附录中对此进行了解释。

2. 遵守自然的语法依赖

语法依赖准确的定义比较复杂且很绕,想追究细节最好是研读原文。简单地讲,语法依赖是指一条指令的源操作数与前面指令(不一定紧邻)的目的操作数是同一个寄存器,前面不出结果后面没法执行,这种逻辑上的限制“自然而然”地约束指令顺序。理解要点,一是看寄存器名而不分析值,这也是叫语法依赖而不叫语义依赖的原因;二是不是所有指令都有目的操作数,因此没有指令会依赖一条store语句(不包括sc指令),因为它没有目的操作数,见规范14.3节;三是x0寄存器不构成任何依赖,因为它的值是固定的、已知的。

显然,语法依赖具有传递性:B依赖A,则A ->ppo B;C依赖B,则B ->ppo C;所以必然A ->ppo C,即A全局序必在C之前。注意,规范也没有明确指

  • 2
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值