Compare-and-Swap in Hardware: How the Cache Controller Implements the Atomic Primitive Every Lock-Free Algorithm Depends On

2026-09-01

Every lock-free data structure you've written — every std::atomic::compare_exchange, every Java AtomicReference.compareAndSet — bottoms out at a single instruction: CMPXCHG on x86, CAS on SPARC. Software treats it as a magic primitive. Hardware has to actually make it atomic across a coherent multi-core system, and the mechanism is surprisingly concrete.

The naive implementation locks the memory bus for the duration: assert LOCK#, do a read-modify-write, release. This is what the original Pentium's LOCK CMPXCHG literally did — every other core stalled. It works, but it doesn't scale past a handful of cores because the bus becomes the bottleneck.

Modern implementations do it entirely in the cache coherence protocol. The sequence on an Intel Skylake core:

The whole operation is atomic because between the RFO and the unlock, no other core can even observe the line, let alone modify it. The coherence protocol enforces the atomicity — no explicit bus lock needed.

Concrete real-world example: a lock-free stack push using CAS on Skylake. Uncontended CAS takes ~5-6 cycles (L1 hit, line already in M state). Contended CAS with the line in another core's L1 takes ~40-60 cycles just for the RFO snoop round-trip across the ring bus. This is why uncontended lock-free code is fast and contended lock-free code often loses to a well-designed mutex — the CAS itself isn't the cost, the coherence traffic is.

Rule of thumb: a successful CAS on a line already in M state ≈ 5 cycles. A CAS on a line owned by another core on the same socket ≈ 40 cycles. A CAS on a line owned by another socket ≈ 200+ cycles. Multiply by your CAS-retry loop depth to predict lock-free algorithm performance under contention.

See it in action: Check out Silicon to Token: How the Hardware of Machine Learning Actually Works by Vector Meridian to see this theory applied.
Key Takeaway: Hardware makes CAS atomic by locking a single cache line inside the coherence protocol — the cost isn't the compare, it's the RFO snoop that pulls the line into Modified state.

All newsletters