内存屏障产生的原因:
程序执行时实际内存访问顺序和程序代码编写的访问顺序不一致,会导致内存乱序访问(注意:和指令的乱序执行(OO)是两码事)。内存乱序访问的目的是提高程序运行时的性能。
内存乱序访问发生在两种情况:
- 编译时,编译器优化导致内存乱序访问;
- 运行时,多个CPU之间交互引起的内存乱序访问。
编译时的乱序访问可以通过volatile关键字规避,比如:
#define barrier() __asm__ __volatile__ ("":::memory)
barrier 函数高速编译器,不要为了性能优化而将这些代码(哪些代码?)重排;
ARM提供的内存屏障指令:
- 数据存储屏障(Data Memory Barrier,DMB):数据存储器隔离,DMB指令保证:仅当所有在它前面的存储器访问操作都执行完毕后才提交在它后面的存取访问操作指令。当位于此指令前的所有内存访问均完成是,DMB指令才会完成。
- 数据同步屏障(Data synchronization Barrier,DSB):数据同步隔离: 比DMB要严格,仅当所有在它前面的存储器访问操作都执行完毕后,才回去执行后面的指令,即任何指令都要等待DSB前面的存储访问完成。位于此指令前段的所有缓存,如分支预测和TLB维护操作全部完成。
- 指令同步屏障(Instructiono synchronization Barrier,ISB):最严格的同步指令,冲洗流水线(Flush Pipeline)和预取buffers(pretcLbuffers)后,才会从cache或者内存中预取ISB指令之后的指令。ISB通常用来保证上下文切换的效果,例如更改ASID(Address Space Identifier),TLB维护操作和C15寄存器的修改。