Refinement Verification of Concurrent Programs and Its Applications
description
Transcript of Refinement Verification of Concurrent Programs and Its Applications
Refinement Verification of Concurrent Programs and Its Applications
Hongjin LiangUniv. of Science and Technology of China
Advisors: Xinyu Feng and Zhong Shao
Refinement
void main() { print a rectangle;}
void main() { print a square;}
T S: T has no more observable behaviors (e.g. I/O events by print) than S.
Concurrent Program Refinement
• Compilers for concurrent programs
T
S
Compiler
MultithreadedJava programs
Java bytecode
Correct(Compiler):S, T. T = Compiler(S) T S
Concurrent Program Refinement
• Compilers for concurrent programs
• Fine-grained impl. of concurrent objects (libraries)
– E.g. java.util.concurrent
Whole program C[O]
…push(7);x = pop();…
…push(6);…
Client code CConcurrent object O
void push(int v) { local b:=false, x, t; x := new Node(v); while (!b) { t := top; x.next = t; b = cas(&top, t, x); }}
…
int pop() { … …
}
How to specify/prove correctness?
Correctness of Concurrent Objects
• Linearizability [Herlihy&Wing’90]
– O lin S : correctness w.r.t. functionality
– Spec S : abstract object (atomic methods)
– Hard to understand/use
• Equivalent to contextual refinement [Filipovic et al.]
– O ctxt S iff C. C[O] C[S]
…x := 7;push( x );…
…y := pop(); print(y);…
Client C
Concrete obj. O
Abstract obj. S
void push(int v) { … }int pop() { … }
push
pop
O ctxt S iff C. C[O] C[S]
Concurrent Program Refinement
• Compilers for concurrent programs
• Linearizability of concurrent objects (libraries)
• Impl. of software transactional memory (STM)
– Atomic block (transaction) fine-grained impl.
Concurrent Program Refinement
• Compilers for concurrent programs
• Linearizability of concurrent objects (libraries)
• Impl. of software transactional memory (STM)
• Impl. of concurrent garbage collectors (GC)
• Impl. of operating system (OS) kernels
Is such a refinement T S general enough & easy to verify?
(Compositionality)T1 || T2 S1 || S2
T1 S1 T2 S2
Problems with T S
Existing work on verifying T S : either is not compositional, or limits applications.
Long-Standing Problems in Verifying Linearizability
• Objects with Non-Fixed Linearization Points (LPs)
– Future-dependent LPs (e.g. lazy set, pair snapshot)
– Helping (e.g. HSY elimination-backoff stack)
Most existing work : either not supports them, or lacks formal soundness.
Refinement vs. Progress Properties ?
• Linearizability– Correctness w.r.t. functionality– Not talk about termination/liveness properties
• Progress properties– Lock-freedom (LF)– Wait-freedom (WF)– Obstruction-freedom (OF)– Deadlock-freedom (DF)– Starvation-freedom (SF)
Non-blocking impl.
Lock-based impl.
Our Contributions (Part 1)
• RGSim = Rely/Guarantee + Simulation
– Compositional w.r.t. parallel composition
– Flexible & applicable
• optimizations in concurrent contexts
• concurrent GC
• fine-grained concurrent obj.
• …
Our Contributions (Part 2)
• RGSim = Rely/Guarantee + Simulation
• A program logic for linearizability– Support non-fixed LPs
– Verified 12 well-known algorithms (some are used in java.util.concurrent)
– Light instrumentation mechanism to help verification
– Formal meta-theory: simulation (extends RGSim)• Establish a contextual refinement
Our Contributions (Part 3)
• RGSim = Rely/Guarantee + Simulation• A program logic for linearizability
• A framework to characterize progress properties via contextual refinement (CR)– Propose different termination-sensitive CR• Equivalent to linearizability + progress• Unify all five progress properties (LF, WF, OF, DF, SF)
– Make modular verification of whole program C[O] easier
– Potential to have a generic verification framework for linearizability + progress
Outline
• Rely-Guarantee-based simulation for modular verification of concurrent refinement
• Logic for linearizability
• Progress properties and contextual refinement
(Compositionality)T1 || T2 S1 || S2
T1 S1 T2 S2
Modular Verification of T S
is NOT compositional w.r.t. parallel composition:
T1 S1 T2 S2
T1 || T2 S1 || S2 T:local t;
t = x;
x = t + 1;
print( x );
S:x++;
print( x );
We have T S, since output(T) output(S) ;
but we do not have T||T S||S .
Existing Proof Methods: Simulation in CompCert
(T, )
(S, ) (S’, ’)
(T’, ’)
* (S’’, ’’)
(T’’, ’’)e
e * …
…
[Leroy et al.]
Source state
Target stateobservable event (e.g. I/O)
T:local t;
t = x;
x = t + 1;
print( x );
S:x++;
print( x );
We have T S , but not T||T S||S
Simulation in CompCert [Leroy et al.]
Can verify refinement of sequential programs
NOT compositional w.r.t. parallel composition
Simulation in CompCert [Leroy et al.]
Can verify refinement of sequential programs
NOT compositional w.r.t. parallel composition Consider NO environments
Simulation in process calculus (e.g. CCS [Milner et al.])
• Assume arbitrary environments
Compositional
Too strong: limited applications
…(T’, ’’) (T’’, ’’’)
(S’, ’’) * (S’’, ’’’) …
’ ’e
e
Assuming Arbitrary Environments
env
env
Too strong to be satisfied, since env. can be arbitrarily bad.
(T, ) (T’, ’)
(S, ) (S’, ’)*
’ ’
Refinement applications have assumptions about S & env.
• Compilers for concurrent programs– Prog. with data races has no semantics (e.g. concurrent C++)– Not guarantee correctness for racy programs
• Fine-grained objects– Accesses use same primitives (e.g. stack: push & pop)– Not guarantee correctness when env. can destroy obj.
• More examples are in the thesis …
Env. of a thread cannot be arbitrarily bad !
[Boehm et al. PLDI’08]
Refinement’s Assumptions
Problems of existing simulations :
Our RGSim :
• Considers no env. in CompCert [Leroy et al.]
NOT compositional w.r.t. parallel composition
• Assumes arbitrary env. in process calculus (e.g. [Milner et al.])
Too strong: limited applications
• Parameterized with the interference with env.
Compositional
More applications
• Use rely/guarantee to specify the interference
[Jones'83]Overview of Rely/Guarantee
• r: acceptable environment transitions• g: state transitions made by the thread
Thread1 Thread2
Nobody else would update x
I guarantee I would not touch y
Nobody else would update y
I guarantee I would not touch xCompatibility (Interference Constraints):
g2 r1 and g1 r2
r1: x = x’
’ r2: y = y’
’
g1: y = y’ ’ g2: x = x’ ’
(T, )
(S, ) (S’, ’)
(T’, ’)
* (S’’, ’’’)
(T’’, ’’’)e
e * …
…
*R
r
G
g
G
g
RGSim = Rely/Guarantee + Simulation
≲ ≲ ≲
(S’, ’’)
(T’, ’’)
≲
(T, r, g) ≲ (S, R, G)
Soundness Theorem
(T, r, g) ≲ (S, R, G)
If we can find r, g, R and G such that
then we have: T S
Parallel Compositionality
(T1||T2, r1r2, g1g2) ≲ (S1||S2, R1R2, G1G2)
(T2, r2, g2) ≲ (S2, R2, G2)
(T1, r1, g1) ≲ (S1, R1, G1)
g1 r2 g2 r1 G1 R2 G2 R1
(PAR)
More on Compositionality
(T1, r, g) ≲ (S1, R, G) (T2, r, g) ≲ (S2, R, G)
(T1; T2, r, g) ≲ (S1; S2, R, G)
(T, r, g) ≲ (S, R, G) b B
(while b do T, r, g) ≲ (while B do S, R, G)
An axiomatic proof system for refinement
…
We have applied RGSim to verify …
• Optimizations in parallel contexts– Loop invariant hoisting, strength reduction and induction
variable elimination, dead code elimination, …
• Fine-grained impl. & concurrent objects– Lock-coupling list, counters, Treiber’s non-blocking stack,
concurrent GCD algorithm, …
• Concurrent garbage collectors– A general GC verification framework– Hans Boehm’s concurrent GC [Boehm et al. 91]
Outline
• Rely-Guarantee-based simulation for modular verification of concurrent refinement
• Logic for linearizability
• Progress properties and contextual refinement
Linearizability of Concurrent Objects
• Correctness w.r.t. functionality
• O lin S : Every concurrent execution of object O is “equivalent” to some sequential execution of spec S
[Herlihy&Wing’90]
A concurrent execution of O:
Thread 1:
Thread 2:
retpush(7)
retpush(6)
ret (7)pop()
time
push(6), ret, push(7), ret, pop(), ret(7)
Sequential execution of S
Linearizability of Object O
Linearization point (LP)
Example: Treiber’s Non-Blocking Stack
…v1 next vk next
Top
push(int v):
1 local b:=false, x, t;
2 x := new Node();
3 x.data := v;
4 while(!b){
5 t := Top;
6 x.next := t;
7 b := cas(&Top, t, x);
8 }
next
t
x
v Is it linearizable?
[Treiber’86]
Line 6: the only command that changes the listLP
Not update the shared list“Fixed”: statically
located in impl code
…v1next
vknext
Top
Treiber’s stack O
push(v):
1 local b:=false, x, t;
2 x := new Node(v);
3 while (!b) {
4 t := top;
5 x.next = t;
6 b = cas(&top, t, x);
7 }
PUSH(v): Stk := v::Stk;
Stk = v1 :: v2 :: … :: vk
Abstract stack Slin?
1 local b:=false, x, t;
2 x := new Node(v);
3 while (!b) {
4 t := Top;
5 x.next := t;
push(v):6 b := cas(&Top, t, x);
if (b)
linself;
>
7 }
…v1 vk
Top
v1 :: v2 :: … :: vk
v
next nextStk =v ::
LP
- { [PUSH(v)] … }
- { [] … }
<
Abstract opr is done
Abstract opr PUSH(v) not done
Execute abstract opr simultaneously
Proved it’s LP
Atomic block
Treiber’s stack O Abstract stack Slin?
Basic Approach to Verify O lin S
• Instrument(O) = D with linself at LPs
• Verify D in program logic with rules for linself– New assertions [S] and []– Ensure O’s LP step corresp. to S’s single step
Not support non-fixed LPs– Future-dependent LPs– Helping
Inspired by [Vafeiadis’ Thesis]
Challenge 1: Future-Dependent LP
m 0 1 … k
t2: write(i, d)t1: readPair(i, j)
write(i, d) updates m[i] to a new value d
[Qadeer et al. MSR-TR-2009-142]
readPair(i, j) intends to return snapshot of m[i] and m[j]
Example: Pair Snapshot
Pair Snapshot
v
readPair(int i, j){1 local s:=false, a, b, v, w;2 while (!s) {3 <a := m[i].d; v := m[i].v>;4 <b := m[j].d; w := m[j].v>;5 <if (v = m[i].v) s := true>; 6 }7 return (a, b);}
d
m 0 1 … k
write(int i, d){8 <m[i].d := d; m[i].v++>;}
LP if line 5 succeeds
• Line 4? But line 5 may fail, m[i] and m[j] may be re-read
Where is the LP ?
know: m[i] = (a,v) at line 4
version number
[Qadeer et al. MSR-TR-2009-142]
Future-dependent LPNot supported by linself
readPair(int i, j){1 local s:=false, a, b, v, w;2 while (!s) {3 <a := m[i].d; v := m[i].v;>
4 <b := m[j].d; w := m[j].v;
5 <if (v = m[i].v) { s:= true;
6 }7 return (a, b);}
- { m[i] = (a, v) [RP, (i,j)] … }[RP, (i,j)]
- { s [, (a,b)] s … }
- { m[i] = (a, v) ( [, (a,b)] ) … }
Solution: Try-Commit
>trylinself;
} >commit( [, (a,b)] );
speculate at potential LP, keep both result and original
Challenge 2: Helping
• Example: elimination-backoff stack [Hendler et al. SPAA’04]
• t1 finishes t2’s opr t2’s LP is in the code of t1
• Need to linearize a thread other than self
• New auxiliary command: lin(t)
• New assertions: t S | t
• Details are in the thesis…
Our Approach to Verify O lin S
• Instrument(O) = D with auxiliary cmds at LPs– linself for fixed LPs– try-commit for future-dependent LPs – lin(t) for helping
• Assertions to describe abstract code & statesp, q ::= … | t S | t | p q | p q
• Verify D in our program logic– Extend an existing logic with rules for aux cmds
Our Logic for O lin S
┝ {p (t S)} lin(t) {q * (t )}
┝ {p} S {q}
┝ {p (cid S)} trylinself {( p * (cid S) ) ( q * (cid ) )}
┝ {p} S {q}
┝ {p q} commit(p) {p}
…
More rules and soundness are in the thesis
Verified AlgorithmsObjects Fut. LP Helping Java Pkg
(JUC)
Treiber stack
HSY stack
MS two-lock queue
MS lock-free queue
DGLM queue
Lock-coupling list
Optimistic list
Heller et al lazy list
Harris-Michael lock-free list
Pair snapshot
CCAS
RDCSS
Soundness via Contextual Refinement
O lin S
• “”: all proof methods for ctxt can verify lin
– ctxt is a well-studied concept in PL community(still challenging though)
• “”: modular verification (view C[O] as C[S])– C[S] is simpler to understand/verify
Theorem (equivalence):
O ctxt SProof follows [Filipovic et al., 2009]
Intentional Extensional
Outline
• Rely-Guarantee-based simulation for modular verification of concurrent refinement
• Logic for linearizability
• Progress properties and contextual refinement
Progress Properties
• Describe whether methods eventually return
• Defined similarly to linearizablity– Describe objects’ behaviors instead of clients’– Intentional instead of extensional– E.g. there always exists a method call that’ll return
Can we use contextual refinement to define progress properties?
Our Results
Termination-sensitive contextual refinement
O P S ( iff C. ObsBeh(C[O]) ObsBeh(C[S]) )
Linearizability O lin S
ProgressP(O)
P LF WF OF DF SF
ObsBeh(C[O]) div t-div i-div f-div f-t-div
ObsBeh(C[S]) div t-div div div t-div
Relationships between Progress Properties
Wait-freedom
Lock-freedom
Starvation-freedom
Obstruction-freedom
Deadlock-freedom
+Linearizability
WF
LF SF
OF DF
equiv. to
Conclusion• RGSim = Rely/Guarantee + Simulation– Idea: parameterized with interference with env.– Compositional!– Applications: optimizations, concurrent GC, …
• Program logic for linearizability– Light instrumentation to help verification• linself for fixed LPs• lin(t) for helping• try-commit for future-dependent LPs
– Verified 12 well-known algorithms
Conclusion
• Contextual refinement (CR) framework to unify linearizability + progress– Intentional Extensional– Different correctness properties correspond to
different observable behaviors– Describe effects over clients (useful for modular
verification)– Borrow existing ideas on CR proof to verify
linearizability + progress — future work