refinement verification of concurrent programs and its applications hongjin liang univ. of science...

51
Refinement Verification of Concurrent Programs and Its Applications Hongjin Liang Univ. of Science and Technology of China Advisors: Xinyu Feng and Zhong Shao

Upload: shamar-southwell

Post on 14-Dec-2015

219 views

Category:

Documents


2 download

TRANSCRIPT

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