on the relationship between concurrent separation logic and assume-guarantee reasoning xinyu feng...
Post on 20-Dec-2015
213 views
TRANSCRIPT
On the Relationship Between Concurrent Separation Logic and Assume-Guarantee Reasoning
Xinyu Feng
Yale University
Joint work with Rodrigo Ferreira and Zhong Shao
Motivation
Concurrency verification is challenging!
T1
T1 T1
T2
T2 T2
Exponential state space caused by interleaving of execution.
Memory aliasing makes it harder to ensure non-interference.
Modularity is the key!
Two kinds of modularity
• Control modularity– a.k.a. thread-modularity– each thread is verified independently of others
• Data modularity– a.k.a. information hiding– each thread only cares about data it uses
Existing work
• Assume-Guarantee (A-G) reasoning [Misra&Chandy’81, Jones’83]
thread modularity general: no restriction over synchronization pattern spec of A&G requires global data invariants
• Concurrent Separation Logic (CSL) [O’Hearn, Brookes 2004]
thread modularity data modularity: local reasoning restrictive synchronization pattern
shared resources can be accessed only inside critical regions
Our Contributions
• SAGL: combining CSL and A-G reasoning– extend A-G logic with local reasoning better data modularity (than A-G reasoning) thread modularity no restriction over synchronization pattern
• A formal study of the relationship between CSL and A-G reasoning
Outline of this talk
• Background– Concurrent Separation Logic– Assume-Guarantee reasoning
• SAGL: combination of CSL & A-G reasoning
• Interpretation of CSL in SAGL
Concurrent Separation Logic
• Assertions capture ownerships of resources
• Cannot access resource without ownership
• Shared resources are protected by critical regions (CRs)
• Transfer of ownership at boundary of CR
l n
CSL assertions
l n nl
p q p q
emp empty heap
p qp q
Locks and Critical Regions
Lock-based critical regions (CR): l.acq();…………
l.rel()
Invariants about memory protected by locks:
= {l1 r1, …, ln rn}
r1 rn
. . .
l1 ln
p1
(l2)
p2
(l1)
p1
(l2)
(l1) p2
Concurrent Separation Logic
p1
(l2)
p2
(l1)
l1.acq()
l1.rel()
…
p1
(l2)
(l1) p2
Example: List
x… = { l List(x) }
getNode():
l.acq();
…
l.rel();
-{emp}
-{emp * List(x)};
-{Node(y) * List(x)}
-{Node(y)}
x … y
Concurrent Separation Logic
• Thread modularity
• Data modularity by local reasoning– do not need knowledge of other threads’ data
Ownership transfer is bound with CRs– requires built-in critical regions– hard to support ad-hoc synchronizations
┝ {p} C {q}
Outline of this talk
• Background– Concurrent Separation Logic– Assume-Guarantee reasoning
• SAGL: combination of CSL & A-G reasoning
• Interpretation of CSL in SAGL
Assume-Guarantee Reasoning
• Thread T and its environment– Environment: the collection of all other threads except T
• A: assumption about environment’s transition
• G: guarantee to the environment
• a: precondition
Assume-Guarantee Reasoning
To certify each thread:
S, S'. a S A S S' a S'
Non-Interference of threads:
G1 … Gi-1 Gi+1 … Gn Ai
Gi A1 … Ai-1 Ai+1 … An
preservation of precondition:
G S Nextc(S)
transitions satisfy the guarantee:
A-G reasoning
a1a2
a1a2 a1a2
G2
A1A2
G1
a2
a2
a1
a1
A-G reasoning
• Thread modular– separate verification of threads
• Not require CRs– but need to know smallest granularity of transitions
A, G: global invariants about all resources– hard to define– lack data modularity
Need to check A and G at every step
(A,G) {a} C {a’}┝
Example: data modularity broken
…
[100] := m;
…
…
[101] := n;
…
100 101
G1: [101] = [101]'
A1: [100] = [100]'
G2: [100] = [100]'
A2: [101] = [101]'
Outline of this talk
• Background– Concurrent Separation Logic– Assume-Guarantee reasoning
• SAGL: combination of CSL & A-G reasoning
• Interpretation of CSL in SAGL
SAGL: Separated A-G Logic
• Partition of each thread’s resource– shared and private– shared can be accessed at any time
• governed by A and G
– exclusive access to private resources• follows local reasoning in CSL• not specified in A and G• better memory modularity
• Dynamic change of partition– may occur at any point, not tied with CR boundaries
SAGL: Specification of Threads
• A, G: assumption and guarantee
• a: precondition about shared resources
• p: precondition about private resources
• Spec for Ti: ((ai, pi), Ai, Gi)
p1
a1a2
p2'
p1
a1a2
p2
SAGL – Access Private Resource
Example: regained data modularity
…
[100] := m;
…
…
[101] := n;
…
100 101
-{(emp , 100 _) } -{(emp , 101 _)}
G1: emp
A1: emp
G2: emp
A2: emp
p1
a1a2'
p2
p1
a1a2
p2
SAGL – Access Shared Resource
A1
G2
a1 a1
A-G reasoning: a special case where
p1 and p2 are emp.
p1
a1a2
p2
p1
a1a2
p2
p1
a1a2'
p2
SAGL - Redistribution
A1
G2 A1
G2
SAGL
• Thread modular– separate verification of threads
• Not require CRs– but need to know smallest granularity of transitions
• A, G: only specifies shared resources– better modularity
• Need to check A and G at every step– but the check is trivial if only private resource is used
(A,G) {(a,p)} C {(a’,p’)}┝
Outline of this talk
• Background– Concurrent Separation Logic– Assume-Guarantee reasoning
• SAGL: combination of CSL & A-G reasoning
• Interpretation of CSL in SAGL
p1
(l2)
p2
(l1)
p1
(l2)
(l1) p2
Concurrent Separation Logic
p1
(l2)
p2
(l1)
l1.acq()
l1.rel()
…
p1
(l2)
(l1) p2
Implicit Invariants in CSL
Shared resources are well-formed outside of critical regions.
Invariants of shared resources:
a Inv(l1) … Inv(ln)
At each program point:
(p1 … pn) a S
Inv(li) (free(li) (li)) ( free(li) emp)
p1
a1a2
p2
Specialization of SAGL
At each program point in SAGL: (p1 … pn) (a1 … an)
Specialize ai into a
(p1 … pn) (a … a)
Specialize A and G to enforce a at every step
A S S' a S a S'
G S S' a S a S'
(p1 … pn) a
Interpretation of CSL in SAGL
If ┝CSL {p} C {q},
then
(A,G)┝SAGL {(a,p)} C {(a,q)}
Also a new way to prove the soundness of CSL! The soundness of SAGL is proved following the syntactic approach (by proving progress & preservation).
Proofs have been formalized in Coq.
getNode():
l.acq();
…
l.rel();
-{(a, emp)}
Example: List = { l List(x) }
-{(emp, emp * List(x))};
-{(emp, Node(y) * List(x))}
-{(List(x), Node(y))}
a = free(l) List(x)
free(l) emp
x…
x … y a
a
a
Conclusion
• SAGL– combination of local reasoning with A-G reasoning– improved modularity than A-G reasoning– more flexible than CSL
• Embedding of CSL in SAGL– formalization of invariants:
shared resources are well-formed outside of CRs– a new way to prove the soundness of CSL
Thank you!
Example: GCD
while(x <> y){
if (x > y)
x = x – y;
}
while(x <> y){
if (y > x)
y = y – x;
}
initially: x = ; y = ;
result: x = GCD(, ); y = GCD(, );
G1: (y = y') (x y x = x') (GCD(x, y) = GCD(x', y'))
A1: (x = x') (y x y = y') (GCD(x, y) = GCD(x', y'))
G2 = A1; A2 = G1
Example: GCD
while(x <> y){
if (x > y)
x = x – y;
}
while(x <> y){
if (y > x)
y = y – x;
}
initially: x = ; y = ;
result: x = GCD(, ); y = GCD(, );
Hard to certify using CSL without rewriting the program and adding auxiliary variables.
Problem with CSL
• Needs to rewrite code using CRs– then needs to prove semantic preservation
• CSL is a program logic– what if the language does not support CRs?
• only use “cas” to do synchronization
Example: malloc
x = alloc(1);
[x] = 2;
if ( odd([x]) ){
//should never reach here
}
y = alloc(1);
[y] = 3;
if ( even([y]) ){
//should never reach here
}
G1: ???
A1: ???
G2: ???
A1: ???
{ emp } { emp }
{ x _ } { y _ }
Example: malloc
x = alloc(1);
[x] = 2;
if ( odd([x]) ){
//should never reach here
}
y = alloc(1);
[y] = 3;
if ( even([y]) ){
//should never reach here
}
G1: emp
A1: emp
G2: emp
A1: emp
-{ (emp, emp) } -{ (emp, emp }
-{ (emp, x _) } -{ (emp, y _) }
Soundness of SAGL
• Safety: progress & preservation
• Partial correctness:– assertions assigned to program points hold
when we reach these points