Lukas' Notes

computer-architecture concurrency

Definition

Atomic Operation

An atomic operation on a shared variable is an indivisible sequence of instructions that appears to execute at a single instant to every other thread. No other thread can observe an intermediate state.

Formally, an atomic operation on a memory location is linearisable: there exists a linearisation point between invocation and response such that the effect of on occurs at .

Motivation

Why atomicity is needed

A lock implemented with ordinary loads and stores fails because the read of *lockvar and the subsequent write are separate instructions. Another thread may observe the same value in between and also enter the critical section.

The read-check-write sequence is not indivisible, so it cannot enforce mutual exclusion.

Hardware

Atomicity must be provided by the CPU. All modern CPUs expose atomic instructions in the ISA.

RISC-V AMO

The RISC-V atomic extension provides AMO (atomic memory operation) instructions.

amoswap.w.aq a2, a1, (a0)

This atomically swaps the word at (a0): a2 receives the old value and a1 is written to memory.

Patterns

PatternEffectExample
Atomic swap; return old amoswap.w
Atomic fetch-and-add; return old amoadd.w
Test-and-setif then amoswap.w
Compare-and-swapif then LR/SC]

C++

std::atomic<T>

std::atomic<int> lockvar{0};
int old = lockvar.exchange(1, std::memory_order_acquire);
lockvar.store(0, std::memory_order_release);

The compiler emits atomic instructions and the required ordering constraints.