内核同步机制-优化屏障和内存屏障
优化屏障
编译器编译源代码时,会将源代码进行优化,将源代码的指令进行重排序,以适合于CPU的并行执行。然而,内核同步必须避免指令重新排序,优化屏障(Optimization barrier)避免编译器的重排序优化操作,保证编译程序时在优化屏障之前的指令不会在优化屏障之后执行。
Linux用宏barrier实现优化屏障,gcc编译器的优化屏障宏定义列出如下(在include/linux/compiler-gcc.h中):
上述定义中,“__asm__”表示插入了汇编语言程序,“__volatile__”表示阻止编译器对该值进行优化,确保变量使用了用户定义的精确地址,而不是装有同一信息的一些别名。“memory”表示指令修改了内存单元。
内存屏障
软件可通过读写屏障强制内存访问次序。读写屏障像一堵墙,所有在设置读写屏障之前发起的内存访问,必须先于在设置屏障之后发起的内存访问之前完成,确保内存访问按程序的顺序完成。
读写屏障通过处理器构架的特殊指令mfence(内存屏障)、lfence(读屏障)和sfence(写屏障)完成,见《x86-64构架规范》一章。另外,在x86-64处理器中,对硬件进行操作的汇编语言指令是“串行的”,也具有内存屏障的作用,如:对I/O端口进行操作的所有指令、带lock前缀的指令以及写控制寄存器、系统寄存器或调试寄存器的所有指令(如:cli和sti)。
Linux内核提供的内存屏障API函数说明如表2。内存屏障可用于多处理器和单处理器系统,如果仅用于多处理器系统,就使用smp_xxx函数,在单处理器系统上,它们什么都不要。
表2 内存屏障API函数说明
内存屏障的宏定义 | 功能说明 |
mb() | 适用于多处理器和单处理器的内存屏障。 |
rmb() | 适用于多处理器和单处理器的读内存屏障。 |
wmb() | 适用于多处理器和单处理器的写内存屏障。 |
smp_mb() | 适用于多处理器的内存屏障。 |
smp_rmb() | 适用于多处理器的读内存屏障。 |
smp_wmb() | 适用于多处理器的写内存屏障。 |
适合于多处理器和单处理器的内存屏障宏定义列出如下(在include/asm-x86/system.h中):
/*指令“lock; addl $0,0(%%esp)”表示加锁,把0加到栈顶的内存单元,该指令操作本身无意义,但这些指令起到内存屏障的作用,让前面的指令执行完成。具有XMM2特征的CPU已有内存屏障指令,就直接使用该指令*/
#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
#else
#define mb() asm volatile("mfence":::"memory")
#define rmb() asm volatile("lfence":::"memory")
#define wmb() asm volatile("sfence" ::: "memory")
#endif
/*刷新后面的读所依赖的所有挂起读操作,在x86-64构架上不需要*/
#define read_barrier_depends() do { } while (0)
宏定义ead_barrier_depends()刷新后面的读所依赖的所有挂起读操作,后面的读操作依赖于正处理的读操作返回的数据。在x86-64构架上不需要此宏。它表明:在此屏障之前,没有来自内存区域数据所依赖的读曾经重排序。所有的读操作处理此原语,保证在跟随此原语的任何读操作此原语之前访问内存(但不需要其他CPU的cache)。此原语在大多数CPU上有比rmb()更轻的份量。
本地CPU和编译器遵循内存屏障的排序限制,仅内存屏障原语保证排序,即使数据有依赖关系,也不能保证排序。例如:下面代码将强迫排序,因为*q的读操作依赖于p的读操作,并且这两个读操作被read_barrier_depends()分开。在CPU 0和CPU 1上执行的程序语句分别列出如下:
b = 2;
memory_barrier();
p = &b; q = p;
read_barrier_depends();
d = *q;
下面的代码没有强制排序,因为在a和b的读操作之间没有依赖关系,因此,在一些CPU上,如:Alpha,y将设置为3,x设置为0。类似这种没有数据依赖关系的读操作,需要排序应使用rmb()。
a = 2;
memory_barrier();
b = 3; y = b;
read_barrier_depends();
x = a;
适合于多处理器的内存屏障宏定义列出如下(在include/asm-x86/system.h中):
#define smp_mb() mb()
#ifdef CONFIG_X86_PPRO_FENCE
# define smp_rmb() rmb()
#else
# define smp_rmb() barrier()
#endif
#ifdef CONFIG_X86_OOSTORE
# define smp_wmb() wmb()
#else
# define smp_wmb() barrier()
#endif
#define smp_read_barrier_depends() read_barrier_depends()
#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
#else
#define smp_mb() barrier()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
#define smp_read_barrier_depends() do { } while (0)
#define set_mb(var, value) do { var = value; barrier(); } while (0)
#endif
函数rdtsc_barrier用于加内存屏障阻止RDTSC猜测,当在一个定义的代码区域使用读取时间戳计数器(Read Time-Stamp Counter,RDTSC)函数(或者函数get_cycles或vread)时,必须加内存屏障阻止RDTSC猜测。其列出如下:
{
alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
}
内核同步机制-优化屏障和内存屏障相关推荐
- 【Linux 内核 内存管理】优化内存屏障 ④ ( 处理器内存屏障 | 八种处理器内存屏障 | 通用内存屏障 | 写内存屏障 | 读内存屏障 | 数据依赖屏障 | 强制性内存屏障 |SMP内存屏障 )
文章目录 一.处理器内存屏障 二.Linux 内核处理器内存屏障 一.处理器内存屏障 " 处理器内存屏障 " 针对 " CPU " 之间的内存访问乱序 和 CP ...
- 【Linux 内核 内存管理】优化内存屏障 ② ( 内存屏障 | 编译器屏障 | 处理器内存屏障 | 内存映射 I/O 写屏障 )
文章目录 一.内存屏障 二.编译器屏障 三.处理器内存屏障 一.内存屏障 内存屏障 , 又称为 " 屏障指令 " , 用于保证 " 编译器 " 或 " ...
- Linux并发与同步专题 (1)原子操作和内存屏障
关键词:. <Linux并发与同步专题 (1)原子操作和内存屏障> <Linux并发与同步专题 (2)spinlock> <Linux并发与同步专题 (3) 信号量> ...
- Linux内核同步机制之(四):spin lock【转】
转自:http://www.wowotech.net/kernel_synchronization/spinlock.html 一.前言 在linux kernel的实现中,经常会遇到这样的场景:共享 ...
- 内核同步机制-RCU同步机制
转自http://www.360doc.com/content/09/0805/00/36491_4675691.shtml 目录 [隐藏] 1 RCU同步机制 1.1 RCU介绍 1.2 RCU A ...
- 内核同步机制-读写信号量(rw_semaphore)
四.读写信号量(rw_semaphore) 读/写信号量适于在读多写少的情况下使用.如果一个任务需要读和写操作时,它将被看作写者,在不需要写操作的情况下可降级为读者.任意多个读者可同时拥有一个读/写信 ...
- java内存屏障_java内存屏障
java内存屏障 java的内存屏障通常所谓的四种即LoadLoad,StoreStore,LoadStore,StoreLoad实际上也是上述两种的组合,完成一系列的屏障和数据同步功能. LoadL ...
- linux 内存屏障,理解内存屏障(一)
作者:新浪微博() 计算机学习微信公众号(jsj_xx) 1 前言 内存屏障是搞软件的需要面对的一个涉及硬件cpu的问题,很多人困惑不解.本文是我们对linux内核内存屏障的理解,参考linux内核( ...
- java内存屏障_内存屏障 | 并发编程网 – ifeve.com
本文我将和大家讨论并发编程中最基础的一项技术:内存屏障或内存栅栏,也就是让一个CPU处理单元中的内存状态对其它处理单元可见的一项技术. CPU使用了很多优化技术来实现一个目标:CPU执行单元的速度要远 ...
最新文章
- for...in和for...of以及for( :)的区别
- birt脚本for循环语句_python循环语句(while amp; for)
- uniapp 如何配置MySQL_uniapp后台api设计(微信user表)
- php+tcpdf+表格,PHP使用tcpdf类生成PDF文件
- HB哈勃与HB公链【尊皇社区】深度揭秘分析!
- 【多目标追踪算法】多目标跟踪评价指标
- 点阵字库怎样才能做到字符显示更紧凑?
- python处理图片文件,python 间接处理webp图片文件
- 2019年最新目标检测算法综述汇总
- 【关于如何调用java的private成员变量】
- 2012年度江西省科学技术奖授奖项目名单
- python读parquet文件 pandas读parquet文件
- 2016年GitHub上史上最全的Android开源项目分类汇总
- Amazon SES 邮件发送服务
- 不要做联表查询!!!
- 图像分辨率、像素总数、文件大小之间的详细区别
- 假如你是QQ的产品经理
- 微信公众平台SDK! Senparc.Weixin.MP.dll(资料整理)
- 【HDU 5445】Food Problem(DP)
- DCDC直流转换器(自用版
热门文章
- cdr自动排版插件_CDR ymxkDoc插件 支持X72020到以后版本
- zookeeper注册中心 kerberos_ZooKeeper 并不适合做注册中心
- gitee项目能用SVN拉取吗_基于SpringBoot的车牌识别系统(附项目地址)
- 瑞芯微和全志哪个好_瑞芯微和全志科技基本面信息简要对比和整理
- 打算年后跳槽的注意了... 这个岗位,人才缺口30万 薪资水涨船高
- python sys模块 argv用法_python中sys模块的argv
- python中模块文件的扩展名不一定是py_python模块和python包有什么区别?
- java.io.serializable_java.io.NotSerializableException即使我实现“Serializable”
- 卷积神经网络创建模型
- Java改环境变量把path修改了,CentOS查看和修改PATH环境变量的方法