¿Qué significa la instrucción “lock” en el ensamble x86?

Vi un ensamblaje x86 en la fuente de Qt:

q_atomic_increment: movl 4(%esp), %ecx lock incl (%ecx) mov $0,%eax setne %al ret .align 4,0x90 .type q_atomic_increment,@function .size q_atomic_increment,.-q_atomic_increment 
  1. De Google, sabía lock instrucción de lock hará que la CPU bloquee el bus, pero no sé cuándo la CPU libera el bus.

  2. Sobre todo el código anterior, no entiendo cómo este código implementa el Add ?

  1. LOCK no es una instrucción en sí misma: es un prefijo de instrucción, que se aplica a las siguientes instrucciones. Esa instrucción debe ser algo que haga una lectura-modificación-escritura en la memoria ( INC , XCHG , CMPXCHG , etc.) — en este caso, es la instrucción incl (%ecx) que incluye la palabra lógica en la dirección retenida en el registro ecx .

    El prefijo LOCK garantiza que la CPU tenga la propiedad exclusiva de la línea de caché adecuada durante la operación y proporciona ciertas garantías de pedido adicionales. Esto se puede lograr afirmando un locking de bus, pero la CPU evitará esto siempre que sea posible. Si el bus está bloqueado, es solo por la duración de la instrucción bloqueada.

  2. Este código copia la dirección de la variable a incrementar de la stack en el registro ecx , luego lock incl (%ecx) para incrementar atómicamente esa variable en 1. Las siguientes dos instrucciones configuran el registro eax (que contiene el valor de retorno) de la función) a 0 si el nuevo valor de la variable es 0, y 1 de lo contrario. La operación es un incremento , no un complemento (de ahí el nombre).

Lo que puede estar fallando en entender es que el microcódigo requerido para incrementar un valor requiere que primero leamos en el valor anterior.

La palabra clave Lock obliga a las múltiples microinstrucciones que en realidad aparecen a operar atómicamente.

Si tenía 2 hilos cada uno tratando de incrementar la misma variable, y ambos leen el mismo valor original al mismo tiempo, ambos aumentan al mismo valor, y ambos escriben el mismo valor.

En lugar de tener la variable incrementada dos veces, que es la expectativa típica, terminas incrementando la variable una vez.

La palabra clave de locking evita que esto suceda.

Desde google, sabía que la instrucción de locking provocaría que la CPU bloqueara el bus, pero no sé cuándo la CPU liberará el bus.

LOCK es un prefijo de instrucción, por lo tanto, solo se aplica a la siguiente instrucción, la fuente no lo deja muy claro aquí, pero la instrucción real es LOCK INC . Entonces el Bus está bloqueado por el incremento, luego se desbloquea

Sobre todo el código anterior, no entiendo cómo estos códigos implementaron el Add?

No implementan un Add, implementan un incremento, junto con una indicación de retorno si el valor anterior era 0. Una adición usaría LOCK XADD (sin embargo, Windows InterlockedIncrement / Decrement también se implementa con LOCK XADD ).