C++ x86 汇编中的“锁定”指令是什么意思?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8891067/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What does the "lock" instruction mean in x86 assembly?
提问by gemfield
I saw some x86 assembly in Qt's source:
我在 Qt 的源代码中看到了一些 x86 程序集:
q_atomic_increment:
movl 4(%esp), %ecx
lock
incl (%ecx)
mov ##代码##,%eax
setne %al
ret
.align 4,0x90
.type q_atomic_increment,@function
.size q_atomic_increment,.-q_atomic_increment
From Googling, I knew
lock
instruction will cause CPU to lock the bus, but I don't know when CPU frees the bus?About the whole above code, I don't understand how this code implements the
Add
?
从谷歌搜索,我知道
lock
指令会导致 CPU 锁定总线,但我不知道 CPU 何时释放总线?关于上面的整个代码,我不明白这段代码是如何实现的
Add
?
回答by Anthony Williams
LOCK
is not an instruction itself: it is an instruction prefix, which applies to the following instruction. That instruction must be something that does a read-modify-write on memory (INC
,XCHG
,CMPXCHG
etc.) --- in this case it is theincl (%ecx)
instruction whichinc
rements thel
ong word at the address held in theecx
register.The
LOCK
prefix ensures that the CPU has exclusive ownership of the appropriate cache line for the duration of the operation, and provides certain additional ordering guarantees. This may be achieved by asserting a bus lock, but the CPU will avoid this where possible. If the bus is locked then it is only for the duration of the locked instruction.This code copies the address of the variable to be incremented off the stack into the
ecx
register, then it doeslock incl (%ecx)
to atomically increment that variable by 1. The next two instructions set theeax
register (which holds the return value from the function) to 0 if the new value of the variable is 0, and 1 otherwise. The operation is an increment, not an add (hence the name).
LOCK
不是指令本身:它是指令前缀,适用于以下指令。该指令必须的东西做内存(读-修改-写INC
,XCHG
,CMPXCHG
等)---在这种情况下它是incl (%ecx)
哪个指令inc
rements的l
在举行的地址翁字ecx
寄存器。该
LOCK
前缀可确保 CPU 在操作期间拥有相应缓存行的独占所有权,并提供某些额外的排序保证。这可以通过断言总线锁定来实现,但 CPU 将在可能的情况下避免这种情况。如果总线被锁定,那么它只是在锁定指令的持续时间内。此代码将要从堆栈中递增的变量的地址复制到
ecx
寄存器中,然后lock incl (%ecx)
以原子方式将该变量递增 1。接下来的两条指令将eax
寄存器(保存函数的返回值)设置为 0,如果变量的新值为 0,否则为 1。该操作是increment,而不是 add (因此得名)。
回答by Dan
What you may be failing to understand is that the microcode required to increment a value requires that we read in the old value first.
您可能无法理解的是,增加值所需的微代码要求我们首先读取旧值。
The Lock keyword forces the multiple micro instructions that are actually occuring to appear to operate atomically.
Lock 关键字强制实际发生的多条微指令以原子方式操作。
If you had 2 threads each trying to increment the same variable, and they both read the same original value at the same time then they both increment to the same value, and they both write out the same value.
如果您有 2 个线程,每个线程都试图增加相同的变量,并且它们同时读取相同的原始值,那么它们都增加到相同的值,并且它们都写出相同的值。
Instead of having the variable incremented twice, which is the typical expectation, you end up incrementing the variable once.
不是让变量增加两次,这是典型的期望,你最终增加了一次变量。
The lock keyword prevents this from happening.
lock 关键字可防止这种情况发生。
回答by Necrolis
From google, I knew lock instruction will cause cpu lock the bus,but I don't know when cpu free the bus ?
从谷歌,我知道锁定指令会导致 cpu 锁定总线,但我不知道 cpu 何时释放总线?
LOCK
is an instruction prefix, hence it only applies to the following instruction, the source doesn't make it very clear here but the real instruction is LOCK INC
. So the Bus is locked for the increment, then unlocked
LOCK
是一个指令前缀,因此它只适用于下面的指令,来源在这里没有说得很清楚,但真正的指令是LOCK INC
. 所以总线被锁定为增量,然后解锁
About the whole above code, I don't understand how these code implemented the Add?
关于上面的整个代码,我不明白这些代码是如何实现Add的?
They don't implement an Add, they implement an increment, along with a return indication if the old value was 0. An addition would use LOCK XADD
(however, windows InterlockedIncrement/Decrement are also implement with LOCK XADD
).
它们不实现 Add ,它们实现了一个增量,如果旧值是 0 则返回指示。一个加法将使用LOCK XADD
(但是,windows InterlockedIncrement/Decrement 也实现了LOCK XADD
)。