Assembly 在x86:lock+;addl还是xchgl?
Linux内核使用Assembly 在x86:lock+;addl还是xchgl?,assembly,x86,memory-barriers,Assembly,X86,Memory Barriers,Linux内核使用锁;添加$0,0(%%esp)作为写屏障,而RE2库使用xchgl(%0),%0作为写屏障。有什么区别,哪一个更好 x86是否也需要读屏障说明?RE2将其读屏障函数定义为x86上的no op,而Linux将其定义为lfence或no op,具体取决于SSE2是否可用。什么时候需要锁?锁的重要部分;addl和xchgl是lock前缀。对于xchgl,它是隐式的。两者之间真的没有区别。我会看看他们是如何组装的,并选择一个更短的(以字节为单位),因为对于x86上的等效操作,这通常更快
锁;添加$0,0(%%esp)
作为写屏障,而RE2库使用xchgl(%0),%0
作为写屏障。有什么区别,哪一个更好
x86是否也需要读屏障说明?RE2将其读屏障函数定义为x86上的no op,而Linux将其定义为
lfence
或no op,具体取决于SSE2是否可用。什么时候需要锁?锁的重要部分;addl和xchgl
是lock
前缀。对于xchgl
,它是隐式的。两者之间真的没有区别。我会看看他们是如何组装的,并选择一个更短的(以字节为单位),因为对于x86上的等效操作,这通常更快(因此有一些技巧,比如xorl-eax,eax
)
SSE2的存在可能只是实际情况的一个代理,而实际情况最终是cpuid
的一个函数。结果可能是,SSE2意味着存在lfence
,并且在引导时检查/缓存了SSE2的可用性lfence
在可用时是必需的。如果我们在(%%esp)地址测试lock变量的0状态,“lock;addl$0,0(%%esp)”会更快。因为我们将0值添加到lock变量,如果地址(%%esp)处变量的锁值为0,则零标志设置为1
lfence来自英特尔数据表: 在上执行序列化操作 所有从内存加载的指令 都是在选举前发出的 指示这个连载 操作保证了每一个负载 在程序中位于前面的指令 命令LFENCE指令为 在任何加载之前全局可见 遵循规则的指令 指令是全局可见的 (编者注:或
锁定
ed操作是唯一有用的顺序一致性围栏(在存储之后)lfence
不会阻止存储缓冲区对存储加载进行重新排序。)
例如:内存写入指令,如'mov'是原子的(它们不需要锁前缀),如果它们正确对齐的话。但该指令通常在CPU缓存中执行,此时对于所有其他线程都不会全局可见,因为必须首先执行内存限制,以使该线程等待,直到其他线程可以看到以前的存储
因此,这两条指令之间的主要区别在于xchgl指令不会对条件标志产生任何影响。当然,我们可以使用lock cmpxchg指令测试锁变量状态,但这仍然比使用lock add$0指令更复杂。引用IA32手册(第3A卷,第8.2章:内存排序): 在定义为可回写缓存的内存区域的单处理器系统中,内存排序模型遵循以下原则[…]
- 读取不会与其他读取一起重新排序
- 写入不会与旧的读取一起重新排序
- 对内存的写入不会与其他写入一起重新排序,但
- 使用
指令执行的写入CLFLUSH
- 使用非临时移动指令执行的流存储(写入)([此处的指令列表])
- 串操作(见第8.2.4.1节)
- 使用
- 读操作可以通过较旧的写入操作重新排序到不同的位置,但不能通过较旧的写入操作重新排序到同一位置
- 不能使用I/O指令、锁定指令或序列化指令对读取或写入进行重新排序
- 读取无法传递
和LFENCE
指令MFENCE
- 写入无法传递
和SFENCE
指令MFENCE
- 锁定指令有一个总订单
lock
前缀(隐式或显式),它禁止所有重新排序,并确保多处理器系统中的所有处理器都以相同的顺序看到操作
此外,在写回内存中,读取永远不会重新排序,因此不需要读屏障。最近的x86处理器对于流存储和写入组合内存(通常用于映射图形内存)具有较弱的内存一致性模型。这就是各种
fence
指令发挥作用的地方;它们对于任何其他内存类型都不是必需的,但是Linux内核中的一些驱动程序确实处理写组合内存,所以它们只是以这种方式定义了它们的读屏障。IA-32手册第3A卷第11.3.1节列出了每种内存类型的订购型号。短版本:直写、回写和写保护允许推测性读取(遵循上面详述的规则),不可缓存和强不可缓存内存具有强排序保证(无处理器重新排序,读取/写入立即执行,用于MMIO),写组合内存具有弱排序(即需要围栏的宽松排序规则)。除了其他答案之外,HotSpot开发者发现,在某些处理器上,零偏移量的锁定;添加$0,0(%%esp)
可能不是最优的
movl $1, a a = 1; Atomic for aligned a
# barrier needed here
movl b, %eax tmp = b; Atomic for aligned b