The Store-Order Consistency Testing Problem
for C-like Memory Models
Grace Tan (National University of Singapore)
advised by Umang Mathur (National University of Singapore)
in collaboration with Shankaranarayanan Krishna (IIT Bombay) and Andreas Pavlogiannis (Aarhus University)
1
Why study consistency testing?
2
Concurrency is everywhere
3
Simplified Dekker’s Algorithm (no unlock)
t0:� wants_to_enter[0] = true� while wants_to_enter[1] {� if turn != 0 {� wants_to_enter[0] = false� while turn != 0 {� // busy wait� }� wants_to_enter[0] = true� }� }�� // critical section
t1:� wants_to_enter[1] = true� while wants_to_enter[0] {� if turn != 1 {� wants_to_enter[1] = false� while turn != 1 {� // busy wait� }� wants_to_enter[1] = true� }� }�� // critical section
4
Simplified Dekker’s Algorithm (no unlock)
t0:� wants_to_enter[0] = true� while wants_to_enter[1] {� if turn != 0 {� wants_to_enter[0] = false� while turn != 0 {� // busy wait� }� wants_to_enter[0] = true� }� }�� // critical section
t1:� wants_to_enter[1] = true� while wants_to_enter[0] {� if turn != 1 {� wants_to_enter[1] = false� while turn != 1 {� // busy wait� }� wants_to_enter[1] = true� }� }�� // critical section
5
Textbooks: Correct under sequential consistency
Reality: Not sequentially consistent...
Need to consider weak memory!
x86
ARM
C / C++
CUDA
...
compiler passes
caches
reordering
parallelism
...
Q: Can this terminate?
t0:� wants_to_enter[0] = true� while wants_to_enter[1] {� if turn != 0 {� wants_to_enter[0] = false� while turn != 0 {� // busy wait� }� wants_to_enter[0] = true� }� }�� // critical section
t1:� wants_to_enter[1] = true� while wants_to_enter[0] {� if turn != 1 {� wants_to_enter[1] = false� while turn != 1 {� // busy wait� }� wants_to_enter[1] = true� }� }�� // critical section
6
Program
Q: Can this terminate?
t0:� wants_to_enter[0] = true� while wants_to_enter[1] {� if turn != 0 {� wants_to_enter[0] = false� while turn != 0 {� // busy wait� }� wants_to_enter[0] = true� }� }�� // critical section
t1:� wants_to_enter[1] = true� while wants_to_enter[0] {� if turn != 1 {� wants_to_enter[1] = false� while turn != 1 {� // busy wait� }� wants_to_enter[1] = true� }� }�� // critical section
7
Program
Idea: try simulating possible terminating behaviours,
check if any are feasible
on the actual machine
Q: Can this terminate? (Simulate possible behaviour)
t0:� wants_to_enter[0] = true� while wants_to_enter[1] {� // skipped� }�� // critical section
t1:� wants_to_enter[1] = true� while wants_to_enter[0] {� // skipped� }�� // critical section
8
“Run of the program”
Q: Can this terminate? (Simulate possible behaviour)
t0:
w(x0, true)�r(x1, false)
t1:
w(x1, true)�r(x0, false)
9
Abstract execution
Q: Can this terminate? (SC: no)
t0:
w(x0, true)�r(x1, false)
t1:
w(x1, true)�r(x0, false)
10
Under sequential consistency, this is not feasible.
Proof sketch:
Assume WLOG r(x1, false) executes before r(x0, false)
Then x0 must’ve already been set to true.
Sequential consistency
Q: Can this terminate? (TSO: yes)
t0:
w(x0, true)�r(x1, false)
t1:
w(x1, true)�r(x0, false)
11
Under TSO, both writes can remain buffered, causing the both reads to read the initial value of false.
x86 (TSO)
Consistency Testing
12
Consistency Testing
13
We focus on formalisations of the
C / C++ memory model in this work,
in particular RC20 and its variants.
Consistency Testing
14
Consistency Testing
t0:
w(x0, false)�w(x1, false)
w(x0, true)�r(x1, false)
t1:
�
w(x1, true)�r(x0, false)
t0:
w(x0, false)�w(x1, false)
w(x0, true)�r(x1, false)
t1:
�
w(x1, true)�r(x0, false)
15
Input
Output
Consistency Testing
Note: Sometimes one abstract execution (input)�can have multiple concrete executions (output).
We’re generally concerned with existence, not enumeration.
t0:
w(x0, false)�w(x1, false)
w(x0, false)�w(x0, true)�r(x1, false)
t1:
�
w(x1, true)�r(x0, false)
t0:
w(x0, false)�w(x1, false)
w(x0, false)�w(x0, true)�r(x1, false)
t1:
�
w(x1, true)�r(x0, false)
16
Input
Output 1
Consistency Testing
Note: Sometimes one abstract execution (input)�can have multiple concrete executions (output).
We’re generally concerned with existence, not enumeration.
t0:
w(x0, false)�w(x1, false)
w(x0, false)�w(x0, true)�r(x1, false)
t1:
�
w(x1, true)�r(x0, false)
t0:
w(x0, false)�w(x1, false)
w(x0, false)�w(x0, true)�r(x1, false)
t1:
�
w(x1, true)�r(x0, false)
17
Input
Output 2
Why study store-order consistency testing?
18
Bad news: Consistency Testing is NP-complete...
But model checkers exist in real life! (e.g. GenMC)
How did we fix this issue? Reads-From Consistency Testing
19
Reads-From Consistency Testing
20
Store-Order Consistency Testing
21
Store-Order Based Methods Have Potential
Different programs work better under different tools,�so having variety is good!
It’s also possible enumerating store-order is cheaper!
t0:
w(x0, false)�w(x1, false)
w(x0, false)�w(x0, true)�r(x1, false)
t1:
�
w(x1, true)�r(x0, false)
t0:
w(x0, false)�w(x1, false)
w(x0, false)�w(x0, true)�r(x1, false)
t1:
�
w(x1, true)�r(x0, false)
22
Input
1 mo, 2 rf
The complexity of store-order testing
23
Our results
24
Our results: Store-order testing is intractable...
25
Our results: ... but tractable under single-writer!
26
(Reasonably tight bounds!)
Our results: 5 proofs
27
Thanks for listening!
28
Link to extended abstract:
What is Store-Order Consistency Testing and why do we care?
29
What is Store-Order Consistency Testing and why do we care?
30
What is Store-Order Consistency Testing and why do we care?
31
Shared memory
Thread 1
Thread 2
Thread 3
What is Store-Order Consistency Testing and why do we care?
32
Shared memory
Thread 1
Thread 2
Thread 3
w(x, 1)
What is Store-Order Consistency Testing and why do we care?
33
Shared memory
Thread 1
Thread 2
Thread 3
r(x, 42)
What is Store-Order Consistency Testing and why do we care?
34
What is Store-Order Consistency Testing and why do we care?
35
This is what a “memory model” is
What is Store-Order Consistency Testing and why do we care?
36
What is Store-Order Consistency Testing and why do we care?
37
What is Store-Order Consistency Testing and why do we care?
38
Bad news:
Consistency Testing is NP-complete!
What is Store-Order Consistency Testing and why do we care?
39
Informally, the input has too little “information”
Brief detour: Memory models
40
Shared memory
Thread 1
Thread 2
Thread 3
Brief detour: Memory models (examples)
41
main memory
Thread 1
Thread 2
Thread 3
Brief detour: Memory models (examples)
42
main memory
Thread 1
Thread 2
Thread 3
store buffer
store buffer
store buffer
Brief detour: Memory models (examples)
In these cases, testing�boils down to finding an�“execution order” for�the events.
43
main memory
Thread 1
Thread 2
Thread 3
store buffer
store buffer
store buffer
Brief detour: Memory models (axiomatic)
44
Brief detour: Memory models (axiomatic)
45
Brief detour: Memory models (axiomatic)
(Initial values are 0)
46
Thread 1:
Thread 2:
“Vanilla” Consistency Testing
47
Reads-From Consistency Testing
48
Input now provides the rf!
Store-Order Consistency Testing
49
Input now provides the mo!
What is Store-Order Consistency Testing and why do we care?
50
Choices for which executions to enumerate
# of executions Consistency testing
51
Choices for which executions to enumerate
52
Our results
53
Thanks for listening!
54
Link to extended abstract: