Open kenttanl opened 3 years ago
引用至:https://www.felixcloutier.com/x86/lock#description
Description ¶
Causes the processor’s LOCK# signal to be asserted during execution of the accompanying instruction (turns the instruction into an atomic instruction). In a multiprocessor environment, the LOCK# signal ensures that the processor has exclusive use of any shared memory while the signal is asserted.
In most IA-32 and all Intel 64 processors, locking may occur without the LOCK# signal being asserted. See the “IA-32 Architecture Compatibility” section below for more details.
The LOCK prefix can be prepended only to the following instructions and only to those forms of the instructions where the destination operand is a memory operand: ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCH8B, CMPXCHG16B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, and XCHG. If the LOCK prefix is used with one of these instructions and the source operand is a memory operand, an undefined opcode exception (#UD) may be generated. An undefined opcode exception will also be generated if the LOCK prefix is used with any instruction not in the above list. The XCHG instruction always asserts the LOCK# signal regardless of the presence or absence of the LOCK prefix.
The LOCK prefix is typically used with the BTS instruction to perform a read-modify-write operation on a memory location in shared memory environment.
The integrity of the LOCK prefix is not affected by the alignment of the memory field. Memory locking is observed for arbitrarily misaligned fields.
This instruction’s operation is the same in non-64-bit modes and 64-bit mode.
谷歌翻译:
使处理器的 LOCK# 信号在执行伴随指令的过程中被声明(将指令转换为原子指令)。在多处理器环境中,LOCK# 信号可确保在断言该信号时处理器拥有对任何共享内存的独占使用。
在大多数IA-32和所有Intel 64处理器中,锁定可能会在未声明LOCK#信号的情况下发生。有关更多详细信息,请参见下面的“ IA-32体系结构兼容性”部分。
LOCK 前缀只能加在以下指令之前,并且只能加在目标操作数是存储器操作数的那些形式的指令之前:ADD,ADC,AND,BTC,BTR,BTS,CMPXCHG,CMPXCH8B,CMPXCHG16B,DEC,INC, NEG,NOT,OR,SBB,SUB,XOR,XADD和XCHG。如果LOCK 前缀与这些指令之一一起使用,并且源操作数是内存操作数,则可能会生成未定义的操作码异常(#UD)。如果 LOCK 前缀与上面列表中未包含的任何指令一起使用,也会生成未定义的操作码异常。不管是否存在 LOCK 前缀,XCHG 指令始终声明 LOCK#信号。
LOCK 前缀通常与 BTS 指令一起使用,以对共享内存环境中的内存位置执行读-修改-写操作。
LOCK 前缀的完整性不受存储字段对齐的影响。对于任意未对齐的字段,观察到内存锁定。
在非64位模式和 64 位模式下,该指令的操作相同。
引用至:https://www.felixcloutier.com/x86/cmpxchg#description
Description ¶
Compares the value in the AL, AX, EAX, or RAX register with the first operand (destination operand). If the two values are equal, the second operand (source operand) is loaded into the destination operand. Otherwise, the destination operand is loaded into the AL, AX, EAX or RAX register. RAX register is available only in 64-bit mode.
This instruction can be used with a LOCK prefix to allow the instruction to be executed atomically. To simplify the interface to the processor’s bus, the destination operand receives a write cycle without regard to the result of the comparison. The destination operand is written back if the comparison fails; otherwise, the source operand is written into the destination. (The processor never produces a locked read without also producing a locked write.)
In 64-bit mode, the instruction’s default operation size is 32 bits. Use of the REX.R prefix permits access to additional registers (R8-R15). Use of the REX.W prefix promotes operation to 64 bits. See the summary chart at the beginning of this section for encoding data and limits.
谷歌翻译:
将AL,AX,EAX或RAX寄存器中的值与第一个操作数(目标操作数)进行比较。如果两个值相等,则将第二个操作数(源操作数)加载到目标操作数中。否则,目标操作数将被加载到AL,AX,EAX或RAX寄存器中。 RAX寄存器仅在64位模式下可用。
该指令可以与LOCK前缀一起使用,以允许原子执行该指令。为了简化与处理器总线的接口,目标操作数接收一个写周期,而不考虑比较结果。如果比较失败,则写回目标操作数;否则,将写回目标操作数。否则,将源操作数写入目标。 (处理器从不产生锁定的读取,而不产生锁定的写入。)
在64位模式下,指令的默认操作大小为32位。使用REX.R前缀允许访问其他寄存器(R8-R15)。使用REX.W前缀可将操作提升到64位。有关数据和限制的编码,请参见本节开头的摘要表。
CAS
源码
Unsafe.class 中声明 compareAndSwap 的 native 方法:
compareAndSwap native 方法的实现: unsafe.cpp L1607 & unsafe.cpp L1185
最终调用了 Atomic::cmpxchg(x, addr, e) 方法
linux_x86 的实现: atomic_linux_x86.inline.hpp L93
说明:
os::is_MP()
用于判断计算机系统是否为多核系统;__asm__
表示接下来是内联的汇编代码;volatile
表示禁止编译器优化;LOCK_IF_MP
是一个内联函数,用于在多核处理器上的指令中添加 lock 前缀,源码:atomic_linux_x86.inline.hpp L147总结: