A case for relaxed program logics Separation logic as a tool - - PowerPoint PPT Presentation
A case for relaxed program logics Separation logic as a tool - - PowerPoint PPT Presentation
A case for relaxed program logics Separation logic as a tool for understanding and debugging the C/C++ concurrency model Viktor Vafeiadis Max Planck Institute for Software Systems (MPI-SWS)
Introduction Goal: Understand weak memory models Tool: Relaxed
✭✭✭✭✭✭ ✭ ❤❤❤❤❤❤ ❤
Concurrent program logics What have we achieved?? Verified some C11 programs Debugged the C11 weak memory model
Viktor Vafeiadis A case for relaxed program logics 2/8
The C11 memory model Two types of locations: ordinary and atomic Races on ordinary accesses ❀ error A spectrum of atomic accesses: Relaxed ❀ no fence Consume reads ❀ no fence, but preserve deps Release writes ❀ no fence (x86); lwsync (PPC) Acquire reads ❀ no fence (x86); isync (PPC)
- Seq. consistent ❀ full memory fence
Viktor Vafeiadis A case for relaxed program logics 3/8
Release-acquire synchronization: message passing Initially a = x = 0. a = 5; x.store(release, 1); while (x.load(acq) == 0); print(a); This will always print 5. Justification:
Wna(a, 5)
- Racq(x, 1)
- Wrel(x, 1)
- Rna(x, 5)
Release-acquire synchronization
Viktor Vafeiadis A case for relaxed program logics 4/8
Release-acquire synchronization: message passing Initially a = x = 0. Let J def = {0: emp, 1: &a → 5}. {&a → 0 ∗ WJ(x)} a = 5; {&a → 5 ∗ WJ(x)} x.store(release, 1); {RJ(x)} while (x.load(acq) == 0); {&a → 5} print(a); This will always print 5. PL consequences: Ownership transfer works!
Viktor Vafeiadis A case for relaxed program logics 4/8
Dependency cycles Initially x = y = 0. if (x.load(rlx) == 1) y.store(1, rlx); if (y.load(rlx) == 1) x.store(1, rlx); C11 allows the outcome x = y = 1. Justification:
Rrlx(x, 1)
- Rrlx(y, 1)
- Wrlx(y, 1)
- Wrlx(x, 1)
- Relaxed accesses
don’t synchronize
Viktor Vafeiadis A case for relaxed program logics 5/8
Dependency cycles Initially x = y = 0. if (x.load(rlx) == 1) y.store(1, rlx); if (y.load(rlx) == 1) x.store(1, rlx); C11 allows the outcome x = y = 1. What goes wrong: Non-relational invariants are unsound. x = 0 ∧ y = 0 The DRF-property does not hold.
Viktor Vafeiadis A case for relaxed program logics 5/8
Dependency cycles Initially x = y = 0. if (x.load(rlx) == 1) y.store(1, rlx); if (y.load(rlx) == 1) x.store(1, rlx); C11 allows the outcome x = y = 1. How to fix this: Don’t use relaxed writes ∨ Disallow RW reoderings.
Viktor Vafeiadis A case for relaxed program logics 5/8
Release-consume synchronization Initially a = x = 0. a = 5; x.store(release, &a); t = x.load(consume); if (t = 0) print(∗t); This program cannot crash nor print 0. Justification:
Wna(a, 5)
- Rcon(x, &a)
- Wrel(x, &a)
- Rna(a, 5)
Release-consume synchronization
Viktor Vafeiadis A case for relaxed program logics 6/8
Release-consume synchronization Initially a = x = 0. Let J(t) def = t = 0 ∨ t → 5. {&a → 0 ∗ WJ(x)} a = 5; {&a → 5 ∗ WJ(x)} x.store(release, &a); {RJ(x)} t = x.load(consume); {✷t(t = 0 ∨ t → 5)} if (t = 0) print(∗t); This program cannot crash nor print 0. PL consequences: Needs funny modality, but otherwise OK.
Viktor Vafeiadis A case for relaxed program logics 6/8
Release-acquire too weak in the presence of consume Initially x = y = 0. a = 1; x.store(1, release); while (x.read(consume) = 1); y.store(1, release); (∗) while (y.load(acquire) = 1); (∗) a = 2; C11 deems this program racy. Only different thread rel-acq synchronize. What goes wrong in PL: On ownership transfers, we must prove that we don’t read from the same thread.
Viktor Vafeiadis A case for relaxed program logics 7/8
Release-acquire too weak in the presence of consume Initially x = y = 0. a = 1; x.store(1, release); while (x.read(consume) = 1); y.store(1, release); (∗) while (y.load(acquire) = 1); (∗) a = 2; C11 deems this program racy. But, it is not racy: On x86-TSO, Power, ARM, and Itanium. Or if we move the (∗) lines to a new thread. So, drop the “different thread” restriction.
Viktor Vafeiadis A case for relaxed program logics 7/8
Status report We know how to reason about: Release-acquire Consume reads (work in progress) C11 memory fences (work in progress) We found the following bugs in the model: Dependency cycles (also in [Batty et al. ’03]) Same thread rel-acq don’t synchronize Semantics of SC accesses odd and too weak. . . . . . when mixed with non-SC accesses Release sequences too strong
Viktor Vafeiadis A case for relaxed program logics 8/8