3

It is said an assembly instruction prefixed by "lock" is atomic. I want to know if "lock" can only affect one assembly instruction; Is an assembly instruction itself not atomic?

Here is an example of an atomic function in linux kernel:

static __inline__ int atomic_sub_and_test(int i, atomic_t *v)
 { unsigned char c;
 __asm__ __volatile__(
 LOCK "subl %2,%0; sete %1" 
    :"=m" (v->counter), "=qm" (c) 
     :"ir" (i), "m" (v->counter) : "memory"); 
return c; }

In this example can subl and sete be interrupted?

venus.w
  • 2,171
  • 7
  • 28
  • 42

3 Answers3

9

The lock prefix affects a single instruction.

Instructions stop being atomic when they modify memory shared between several CPUs. Modifications that involve reading a memory operand, performing some operation on it (e.g. AND, XOR, INC, etc) and then writing it back are not seen as atomic by other CPUs. The lock prefix "locks" the memory location, so the 3 steps (Read, Modify, Write) look as one, i.e. other CPUs can only observe what was before and what was after the locked instruction.

See the official CPU documentation from Intel or AMD.

EDIT: In your newly added example neither of those instructions can be interrupted, if we're talking about interrupts. Interrupts occur between entire instructions. The lock prefix makes the sub instruction atomic. The sete instruction is not intended to be atomic, it's there to transform the ZF flag into a zero or non-zero integer value.

Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
  • I have added an example to this question. – venus.w Jul 07 '12 at 03:46
  • I mean can interrupts occur between the two instructions? – venus.w Jul 07 '12 at 03:52
  • Yes, they can. Is there any problem with that? – Alexey Frunze Jul 07 '12 at 03:58
  • AlexeyFrunze: I guess @venus.w worried that an interrupts occur between the two instructions may violate the flag register and cause the ste results wrongly. But actually, when the interrupt returns, the flag register will be restored. – Lai Jiangshan Jul 18 '12 at 14:20
  • `sete (mem)` would be an atomic store if the compiler happened to pick memory. It's not an RMW, just a byte store (of a value derived from FLAGS), so it's trivially atomic; x86 guarantees atomicity of single-byte stores in all cases. (It's not part of the same transaction as the `lock sub`, and it's operating on a variable that isn't shared, so this is totally irrelevant to this use-case. Atomicity for narrow aligned pure-load and pure-store is relatively easy and basically happens for free in most CPUs.) – Peter Cordes Sep 22 '22 at 02:18
4

An instruction is not atomic with respect to other instructions running concurrently on other CPU cores. What the LOCK prefix does is lock the bus so that other cores can't access memory while the locked instruction is running, preventing conflicts where two cores try to access the same location at the same time.

Wyzard
  • 33,849
  • 3
  • 67
  • 87
  • It works *as if* it locks a shared bus, but actually it only has to make the current core hang on to MESI exclusive ownership of the cache line between the load and store parts of the RMW. (aka a "cache lock"). Multiple cores can be running atomic RMW operations on *different* cache lines in parallel, with no slowdown or off-core traffic, just hitting in their L1d caches. – Peter Cordes Sep 22 '22 at 02:10
  • As in [LOCK prefix vs MESI protocol?](https://stackoverflow.com/q/29880015) – Peter Cordes Sep 22 '22 at 02:15
3

Only a very few certain assembly instructions are atomic. x86 is largely a CISC architecture, meaning that a single instruction does a lot of work, where a single instruction can load values from a memory address into registers, perform operations on it, and then store the result back in memory. This is a complex operation that takes much time and CPU cycles to execute; in order to boost performance, many such instructions are pipelined and their execution order is interwoven.

Basically, assembly is a language like any other. Especially when speaking about CISC architecture, there are many "high level" constructs and operations that can be carried out in a single command, they are not guaranteed to execute atomically unless that's explicitly specified either in the documentation for the instruction or with the lock modifier.

Mahmoud Al-Qudsi
  • 28,357
  • 12
  • 85
  • 125