4.3.5 汇编语言:指令隔离(barrier)指令和存储器隔离指令
CM3 中的另一股新鲜空气是一系列的隔离指令(亦可以译成“屏障”、“路障”,可互换使用——译者 注)。它们在一些结构比较复杂的存储器系统中是需要的(典型地用于流水线和写缓冲——译者注)。在 这类系统中,如果没有必要的隔离,会导致系统发生紊乱危象(race condition),(相当于数电中的“竞争 与冒险”——译者注).
举例来说,如果可以在运行时更改存储器的映射关系或者内存保护区的设置,(通过写 MPU 的寄存 器),就必须在更改之后立即补上一条 DSB 指令(数据同步指令)。因为对 MPU 的写操作很可能会被放 到一个写缓冲中。写缓冲是为了提高存储器的总体访问效率而设的,但它也有副作用,其中之一,就是 会导致写内存的指令被延迟几个周期执行,因此对存储器的设置不能即刻生效,这会导致紧临着的下一 条指令仍然使用旧的存储器设置——但程序员的本意显然是使用新的存储器设置。这种紊乱危象是后患 无穷的,常会破坏未知地址的数据,有时也会产生非法地址访问 fault。紊乱危象还有其它的表现形式, 后续章节会一一介绍。CM3 提供隔离指令族,就是要消灭这些紊乱危象(在有些讲解计算机体系体系结 构的书中,这类紊乱危象也被称为“存储器相关”——译注)。
指令名
功能描述
DMB
数据存储器隔离。DMB 指令保证: 仅当所有在它前面的存储器访问操作
都执行完毕后,才提交(commit)在它后面的存储器访问操作。
DSB
数据同步隔离。比 DMB 严格: 仅当所有在它前面的存储器访问操作
都执行完毕后,才执行在它后面的指令(亦即任何指令都要等待存储器访 问操作——译者注)
ISB
指令同步隔离。最严格:它会清洗流水线,以保证所有它前面的指令都执
行完毕之后,才执行它后面的指令。
DMB 在双口 RAM 以及多核架构的操作中很有用。如果 RAM 的访问是带缓冲的,并且写完之后
马上读,就必须让它“喘口气”——用 DMB 指令来隔离,以保证缓冲中的数据已经落实到 RAM 中。 DSB 比 DMB 更保险(当然也是有执行代价的),它是宁可错杀也不漏网——清空了写缓冲,使得任 何它后面的指令,不管要不要使用先前的存储器访问结果,通通等待访问完成。大虾们可以在有绝 对信心时使用 DMB,新手还是使用 DSB 比较保险。
同 DMB/DSB 相比,ISB 指令看起来似乎最强悍,但是却一身都是“愣劲”,不由分说就“动粗”。
不过它还有其它的用场——对于高级底层技巧:“自我更新”(self-mofifying)代码,非常有用。举例 来说,如果某个程序从下一条要执行的指令处更新了自己,但是先前的旧指令已经被预取到流水线 中去了,此时就必须清洗流水线,把旧版本的指令洗出去,再预取新版本的指令。因此,必须在被 更新代码段的前面使用 ISB,以保证旧的代码从流水线中被清洗出去,不再有机会执行(译者觉得 这种做法太工于技巧,有点“作秀”,现实编程中应该极少会用到,因此读者不必太钻它)。