3.9Atomic Operations with SC

book p. 33 · ~2 min read

  • atomic RMW
  • test-and-set
  • spin-lock
  • deferred coherence requests

Why atomics exist

Writing multithreaded code requires synchronizing threads, and synchronization often means performing pairs of operations atomically. That functionality comes from read-modify-write instructions — test-and-set, fetch-and-increment, compare-and-swap — the raw material of spin-locks and every other synchronization primitive. For a spin-lock, the programmer uses an RMW to atomically read whether the lock is free (say, 0) and write it taken (1).

Under SC, atomicity has a precise meaning inherited from §3.5: the RMW’s load and store must appear consecutively in the memory order . Nothing — to the same address or any other — may interpose between the test and the set.

Three implementations, increasingly clever

Conceptually simple; naively slow. Step through the progression:

Core C1test-and-set(lock)C1's L1 cachelock = 0 (free)state IOthercoresSC rule: L(lock) and S(lock) adjacent in <m — the test and the set with nothing in between

1 / 5The job: an atomic test-and-set

A spin-lock acquire must READ whether the lock is free (0) and WRITE it taken (1) atomically. Under SC that means the RMW's load and store appear CONSECUTIVELY in memory order — no other operation, to any address, may slip between them.

The key insight behind the fast versions: SC requires only the appearance of a total order. The standard implementation obtains the block in state M and then loads and stores entirely within the cache — no coherence messages, no bus locking — while briefly deferring any incoming coherence request for that block until after the store. The deferral cannot deadlock, because the store is guaranteed to complete.

The optimized version goes further: with the block merely in a read-only state, the load part performs speculatively right away while the cache controller issues the upgrade to read-write; the store part performs when M arrives. Atomicity survives as long as the block was not evicted between the two parts — verified with exactly the speculation support of §3.8 (track the block; squash and retry on eviction or invalidation).

Check yourself

1.What does SC require of an atomic RMW's two memory operations?

2.Why does the standard implementation (obtain M, then defer incoming coherence requests until after the store) not risk deadlock?

3.Flashback to pop-quiz question 3: must a core always communicate with other cores to perform an atomic RMW?

4.In the optimized implementation, the load part executes speculatively while an upgrade to M is in flight. What check preserves the illusion of atomicity?

4 questions