编译器提供头文件 mbarrier.h,该文件为 SPARC 和 x86 处理程序定义各种内存边界内部函数。这些内部函数对于使用自己的同步基元编写多线程代码的开发人员很有用。建议用户参考其处理器文档,以确定他们的特定情况是否需要以及何时需要这些内部函数。
mbarrier.h 支持的内存排序内部函数:
__machine_r_barrier()-这是读取边界。它确保边界之前的所有装入操作都在边界之后的所有装入操作之前完成。
__machine_w_barrier()-这是写入边界。它确保边界之前的所有存储操作都在边界之后的所有存储操作之前完成。
__machine_rw_barrier()-这是读写边界。它确保边界之前的所有装入和存储操作都在边界之后的所有装入和存储操作之前完成。
__machine_acq_barrier()-这是具有获取语义的边界。它确保边界之前的所有装入操作都在边界之后的所有装入和存储操作之前完成。
__machine_rel_barrier()-这是具有发行语义的边界。它确保边界之前的所有装入和存储操作都在边界之后的所有存储操作之前完成。
__compiler_barrier()-禁止编译器跨边界移动内存访问。
除 __compiler_barrier() 内部函数之外的所有边界内部函数都会生成内存排序指令,在 x86 上为 mfence、sfence 或 lfence 指令,在 SPARC 平台上为 membar 指令。
__compiler_barrier() 内部函数不生成任何指令,而是通知编译器必须先完成之前的所有内存操作,才能启动以后的内存操作。这样的特殊结果是,具有静态存储类说明符的所有非局部变量和局部变量都将存储回内存中的边界之前,并在边界之前重新装入,编译器不会将边界之前的内存操作与边界之后的内存操作混合。所有其他边界都隐式包含 __compiler_barrier() 内部函数的行为。
例如,在下面的代码中,__compiler_barrier() 内部函数的出现会禁止编译器合并两个循环:
#include "mbarrier.h" int thread_start[16]; void start_work() { /* Start all threads */ for (int i=0; i<8; i++) { thread_start[i]=1; } __compiler_barrier(); /* Wait for all threads to complete */ for (int i=0; i<8; i++) { while (thread_start[i]==1){} } } |