Gaurantees of Atomic Operations#
Atomic operations provide three main guarantees:
- Indivisibility: Atomic operations cannot be interrupted halfway through. So, it either completes fully or not at all.
- Visibility: Other cores can see the update consistently. No stale or torn reads.
- Ordering: Prevents reordering around the atomic operation, ensuring correct sequence of operations.
Normal C code is not atomic#
For example, consider the following C code:
ctr--;On hardware this one line becomes:
load r1, [ctr] ; Load current value of ctr into register r1
sub r1, r1, 1 ; Decrement the value in register r1
store [ctr], r1 ; Store the updated value back to memoryBetween load and store another CPU can modify ctr, or a context switch can occur.
This is why atomic operations are needed.
Atomic operations implementation#
The CPU locks exclusive access to a memory location or cache line while performing the operation. Example: in x86 there is a special atomic instruction
LOCK XADD [mem], regThis:
- Locks the cache line
- Perform read + modify + write
- Release lock
No other CPU can touch that memory during this window. Under the hood this is done using cache coherence protocols like MESI. This is also called a lock-based approach.
How does ARM do it?#
ARM does not lock the memory bus like x86. Instead it uses a pair of instructions:
LDXR r0, [addr] ; Load + mark exclusive
STXR r1, r2, [addr] ; Store only if still exclusiveIf another core touches the address:
STXRfails- Operation is retried
This is more efficient than locking the bus, allowing better concurrency. This is also called a reservation-based approach.