Code

View on GitHub

Base race condition #

make race
./race

Source: race.c

Naive Peterson implementation #

make peterson_naive
./peterson_naive

Source: peterson_naive.c

Reorderings #

make store_buffer_test
./store_buffer_test

Source: store_buffer_test.c

Try inserting atomic_thread_fence() and observe reorderings gone!

Peterson correct #

make peterson_atomic
./peterson_atomic

Source: peterson_atomic.c

Note that using atomic_int solves all problems:

  • provides atomic store-load behavior
  • prevents any kinds of reorderings around stores and loads

Compare timings:

make all
time ./race
time ./peterson_naive
time ./peterson_atomic

Atomic swap #

make atomic_swap
./atomic_swap

Source: atomic_swap.c

Atomic Test-And-Set #

make atomic_tas
./atomic_tas

Source: atomic_tas.c

Try blocking inside CS and see what happens with CPU:

make atomic_tas_pause
./atomic_tas_pause
top -H -p $(pidof atomic_tas_pause)

Semaphore #

make semaphore
./semaphore

Source: semaphore.c

make semaphore_pause
./semaphore_pause
top -H -p $(pidof semaphore_pause)

Futex mutex #

make futex
strace ./futex