Concurrent Separation Logic and Assume

Download Report

Transcript Concurrent Separation Logic and Assume

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!
Exponential state space caused by
interleaving of execution.
T1
T1
T2
Memory aliasing makes it harder to ensure
non-interference.
Modularity is the key!
T2
T1
T2
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
l  n
• Cannot access resource without ownership
• Shared resources are protected by critical
regions (CRs)
• Transfer of ownership at boundary of CR
CSL assertions
emp
empty heap
l  n
l
pq
pq
n
p
q
p  q
Locks and Critical Regions
l.acq();
…
…
…
…
l.rel()
Lock-based critical regions (CR):
Invariants about memory protected
by locks:
 = {l1  r1, …, ln  rn}
l1
ln
...
r1 
 rn
Concurrent Separation Logic
(l1)
p1
(l1)  p2
p1
p2
l1.rel()
(l2)
(l2)
(l1)
l1.acq()
(l1)  p2
p1
…
(l2)
p1
p 2
(l2)
Example: List
 = { l  List(x) }
x
…
getNode():
-{emp}
l.acq();
-{emp * List(x)};
…
-{Node(y) * List(x)}
l.rel();
-{Node(y)}
y
x
…
Concurrent Separation Logic
• Thread modularity
 ┝ {p} C {q}
• 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
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
Non-Interference of threads:
G1  …  Gi-1  Gi+1  …  Gn  Ai
Gi  A1  …  Ai-1  Ai+1  …  An
To certify each thread:
preservation of precondition:
 S, S'. a S  A S S'  a S'
transitions satisfy the guarantee:
G S Nextc(S)
A-G reasoning
a1a2
G1
a1a2
G2
a1
A2
a2
a2
A1
a1
a1a2
A-G reasoning
• Thread modular
– separate verification of threads
(A,G)┝ {a} C {a’}
• 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
Example: data modularity broken
100
101
…
…
[100] := m;
[101] := n;
…
…
G1: [101] = [101]'
G2: [100] = [100]'
A1: [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)
SAGL – Access Private Resource
p2
p1
a1a2
p1
p2'
a1a2
Example: regained data modularity
100
-{(emp , 100  _) }
101
-{(emp , 101  _)}
…
…
[100] := m;
[101] := n;
…
…
G1: emp
G2: emp
A1: emp
A2: emp
SAGL – Access Shared Resource
p2
p1
a1a2
G2
a1
p2
A1
a1
p1
a1a2'
A-G reasoning: a special case where
p1 and p2 are emp.
SAGL - Redistribution
p2
p2
p1
p1
a1a2
a1a2'
p2
p1
G2
A1
A1
a1a2
G2
SAGL
• Thread modular
– separate verification of threads
(A,G)┝ {(a,p)} C {(a’,p’)}
• 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
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
(l1)
p1
(l1)  p2
p1
p2
l1.rel()
(l2)
(l2)
(l1)
l1.acq()
(l1)  p2
p1
…
(l2)
p1
p 2
(l2)
Implicit Invariants in CSL
Shared resources are well-formed outside
of critical regions.
Invariants of shared resources:
a  Inv(l1)  …  Inv(ln)
Inv(li)  (free(li)  (li))  ( free(li)  emp)
At each program point:
(p1  …  pn)  a S
Specialization of SAGL
At each program point in SAGL:
(p1  …  pn)  (a1  …  an)
p2
p1
a1a2
Specialize ai into a
(p1  …  pn)  (a  …  a)
 (p1  …  pn)  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'
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.
Example: List
 = { l  List(x) }
a = free(l)  List(x) 
x
…
free(l)  emp
getNode():
-{(a, emp)}
l.acq();
y
-{(emp, emp * List(x))};
…
-{(emp, Node(y) * List(x))}
l.rel();
-{(List(x), Node(y))}
x
…
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
initially: x = ; y = ;
while(x <> y){
while(x <> y){
if (x > y)
if (y > x)
x = x – y;
y = y – x;
}
}
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
initially: x = ; y = ;
while(x <> y){
while(x <> y){
if (x > y)
if (y > x)
x = x – y;
}
y = y – x;
}
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
{ emp }

x = alloc(1);
{x_}
{ emp }
y = alloc(1);

{y_}
[x] = 2;
[y] = 3;
if ( odd([x]) ){
if ( even([y]) ){
//should never reach here
}
//should never reach here
}
G1: ???
G2: ???
A1: ???
A1: ???
Example: malloc
-{ (emp, emp) }
-{ (emp, emp }
x = alloc(1);
y = alloc(1);
-{ (emp, x  _) }
-{ (emp, y  _) }
[x] = 2;
[y] = 3;
if ( odd([x]) ){
if ( even([y]) ){
//should never reach here
}
//should never reach here
}
G1: emp
G2: emp
A1: emp
A1: emp
Soundness of SAGL
• Safety: progress & preservation
• Partial correctness:
– assertions assigned to program points hold
when we reach these points