VPERM: Variable Permissions for Concurrency Verification Duy-Khanh Le ICFEM, Kyoto, Japan, Nov 2012

advertisement
VPERM: Variable Permissions for
Concurrency Verification
Duy-Khanh Le, Wei-Ngan Chin, Yong-Meng Teo
ICFEM, Kyoto, Japan, Nov 2012
Outline
Motivation & Example
Formalism
 Programming & Specification Language
 Verification by Entailment Checking
Inferring Variable Permissions
Eliminating Variable Aliasing
Applicability
Experiment
Conclusion
VPERM: Variable Permissions for Concurrency Verification
2
Motivation
Access permissions attracted much
attention for reasoning about shared heap
data structures
State-of-the-art verification tools
 ignore program variables
 or apply the same permission system,
designed for heap memory, to variables
However, variables are simpler than heap
data structures: each variable is distinct
Need a simpler reasoning scheme for
variables
VPERM: Variable Permissions for Concurrency Verification
3
Related Work
Variables as Resource
[Bornat et al. 2006]
Logic + complex permissions
Syntactic Control of Inference
[Reddy et al. 2012]
Syntactic + complex
permissions
Our Variable Permissions
(VPERM)
Logic + simple
Smallfoot
[Berdine et al. 2006]
Syntactic + simple
Expressiveness
Complexity
VPERM: Variable Permissions for Concurrency Verification
4
Related Work
Permission systems for variables
 Variables as resources [1] & syntactic control
of inference [2]
• User fractional/counting permissions to allow
sharing
• Though flexible, this places higher burden on
programmers to figure out the fraction used
Verification systems for concurrency
 Smallfoot [3] uses side conditions to outlaw conflicting accesses
 Chalice [4] does not support permission of variables in method’s
bodies
 Verifast [5] treats variables as heap locations
VPERM: Variable Permissions for Concurrency Verification
5
Objective
Propose a simple permission system to
ensure data-race freedom when accessing
variables
VPERM: Variable Permissions for Concurrency Verification
6
A Motivating Example
void inc(ref int i, int j)
{
i=i+j;
}
pass-by-ref
pass-by-value
int creator(ref int x,ref int y)
{
int tid;
tid=fork(inc,x,1);
inc(y,2);
return tid;
}
void main()
{
int id;
int x,y;
x=0;y=0;
id = creator(x,y);
…
join(id);
assert (x+y=3);
}
1. Any accesses to x
after fork and
before join are
unsafe (racy)
2. How to propagate
the above fact
across procedure
boundaries
VPERM: Variable Permissions for Concurrency Verification
7
A Motivating Example with Specifications
void inc(ref int i, int j)
requires true
ensures i'=i+j;
{
main thread
i=i+j;
}
child thread
void main()
requires true
ensures true;
{
int id;
int x,y;
x=0;y=0;
id = creator(x,y);
…
join(id);
assert (x+y=3);
}
int creator(ref int x, ref int y)
requires true
implicit
ensures y’=y+2 & res=tid & thread=main
and x'=x+1 & thread=tid;
{
int id;
id=fork(inc,x,1);
inc(y,2);
return id;
}
VPERM: Variable Permissions for Concurrency Verification
8
A Motivating Example with Specifications
void inc(ref int i, int j)
requires true
ensures i'=i+j;
{
main thread
i=i+j;
}
child thread
void main()
requires true
ensures true;
{
int id;
int x,y;
x=0;y=0;
id = creator(x,y);
…
join(id);
assert (x+y=3);
}
int creator(ref int x, ref int y)
requires true
ensures y’=y+2 & res=tid
and x'=x+1 & thread=tid;
{
int id;
id=fork(inc,x,1);
inc(y,2);
return id;
}
VPERM: Variable Permissions for Concurrency Verification
9
A Motivating Example with VPERM
void inc(ref int i, int j)
requires @full[i] & @value[j]
ensures i'=i+j & @full[i];
{
main thread
i=i+j;
}
child thread
void main()
requires true
ensures true;
{
int id;
int x,y;
x=0;y=0;
id = creator(x,y);
…
join(id);
assert (x+y=3);
}
int creator(ref int x, ref int y)
requires @full[x,y]
ensures @full[y] & y’=y+2 & res=tid
and @full[x] & x'=x+1 & thread=tid;
{
int id;
id=fork(inc,x,1);
inc(y,2);
return id;
}
VPERM: Variable Permissions for Concurrency Verification
10
A Motivating Example with VPERM
void inc(ref int i, int j)
requires @full[i] & @value[j]
ensures i'=i+j & @full[i];
{
i=i+j;
}
int creator(ref int x, ref int y)
requires @full[x,y]
ensures @full[y] & y’=y+2 & res=tid
and @full[x] & x'=x+1 & thread=tid;
{
int id;
// @full[x,y] & x’=x & y’=y & id’=0
}
id=fork(inc,x,1);
// @full[y] & y’=y & id’=tid
// and @full[x] & x'=x+1 & thread=tid;
inc(y,2);
// @full[y] & y’=y+2 & id’=tid
// and @full[x] & x'=x+1 & thread=tid;
return id;
// @full[y] & y’=y+2 & id’=tid & res=tid
// and @full[x] & x'=x+1 & thread=tid;
VPERM: Variable Permissions for Concurrency Verification
main thread
main thread
and child thread
11
A Motivating Example with VPERM
void inc(ref int i, int j)
requires @full[i] & @value[j]
ensures i'=i+j & @full[i];
{
i=i+j;
}
void main()
requires true
ensures true;
{
int id;
int x,y;
x=0;y=0;
id = creator(x,y);
…
join(id);
assert (x+y=3);
}
int creator(ref int x, ref int y)
requires @full[x,y]
ensures @full[y] & y’=y+2 & res=tid
and @full[x] & x'=x+1 & thread=tid;
{
int id;
id=fork(inc,x,1);
inc(y,2);
return id;
}
// @full[id]
// @full[id,x,y]
// @full[id,x,y]
// @full[id,y] and @full[x]
// @full[id,y] and @full[x]
// @full[id,x,y]
// @full[id,x,y]
VPERM: Variable Permissions for Concurrency Verification
12
Programming Language
VPERM: Variable Permissions for Concurrency Verification
13
Specification Language
VPERM: Variable Permissions for Concurrency Verification
14
Variable Permissions
 Two key annotations for variable permissions
 @full[w*]
 In a pre-condition
• w* is a list of pass-by-ref variables
• variable permissions are passed from caller to callee
 In a post-condition
• variable permissions are returned from callee to caller
 @value[w*]
 In a pre-condition
• w* is a list of pass-by-value variables
 Not exist in post-conditions
VPERM: Variable Permissions for Concurrency Verification
15
Verification by Entailment Checking
VPERM: Variable Permissions for Concurrency Verification
16
Entailment Rules for VPERM
VPERM: Variable Permissions for Concurrency Verification
17
Soundness
Proofs are in the paper
VPERM: Variable Permissions for Concurrency Verification
18
Inferring Variable Permissions
int creator(ref int x, ref int y)
requires true
ensures y’=y+2 & res=tid
and x'=x+1 & thread=tid;
{
int id;
id=fork(inc,x,1);
inc(y,2);
return id;
}
Vpost = {x,y}
@full[y] , Vpost = {x}
VPERM: Variable Permissions for Concurrency Verification
19
Inferring Variable Permissions
int creator(ref int x, ref int y)
requires true
ensures y’=y+2 & res=tid
and x'=x+1 & thread=tid;
{
int id;
id=fork(inc,x,1);
inc(y,2);
return id;
}
@full[y] , Vpost = {x}
@full[x] , Vpost = {}
VPERM: Variable Permissions for Concurrency Verification
20
Inferring Variable Permissions
int creator(ref int x, ref int y)
requires true
ensures y’=y+2 & res=tid
and x'=x+1 & thread=tid;
{
int id;
id=fork(inc,x,1);
inc(y,2);
return id;
}
Vpre = {x,y}
@full[x,y]
@full[y]
@full[x]
VPERM: Variable Permissions for Concurrency Verification
21
Inferring Variable Permissions
int creator(ref int x, ref int y)
requires true
ensures y’=y+2 & res=tid
and x'=x+1 & thread=tid;
{
int id;
id=fork(inc,x,1);
inc(y,2);
return id;
}
@full[x,y]
@full[y]
@full[x]
(*) Algorithm and Soundness in the paper
VPERM: Variable Permissions for Concurrency Verification
22
Eliminating Variable Aliasing
void inc(ref int i, int j)
requires @full [i] ∧ @value[j]
ensures @full [i] ∧ i’=i+j;
{ i = i + j; }
void main()
{
int x = 0;
int ∗ p = &x;
int id;
id = fork(inc, x, 1);
...
//accesses to *p are racy
join(id);
}
VPERM: Variable Permissions for Concurrency Verification
23
Eliminating Variable Aliasing
void inc(ref int i, int j)
requires @full [i] ∧ @value[j]
ensures @full [i] ∧ i’=i+j;
{ i = i + j; }
void main()
{
int x = 0;
int ∗ p = &x;
int id;
id = fork(inc, x, 1);
...
join(id);
}
// @full[x]
// @full[x,p]
// @full[x,p,id]
// @full[p,id]
// @full[p,id]
// @full[x,p,id]
Solution: a translation
to eliminate * and &
still have permission
to access p and
indirectly x
VPERM: Variable Permissions for Concurrency Verification
24
Translation Scheme
void inc(ref int i, int j)
requires @full [i] ∧ @value[j]
ensures @full [i] ∧ i’=i+j;
{ i = i + j; }
void inc(int_ptr i, int j)
requires i::int_ptr<old_i>& @value[i,j]
ensures i::int_ptr<new_i> & new_i=old_i+j;
{ i.val = i.val + j; }
void main()
{
promote
int x = 0;
int ∗ p = &x;
int id;
id = fork(inc, x, 1);
...
join(id);
void main()
{
int_ptr x = new int_ptr(0);
int_ptr p = x;
int id;
id = fork(inc, x, 1);
...
join(id);
delete(x);
(*) details are in the paper
}
}
VPERM: Variable Permissions for Concurrency Verification
25
Applicability
Pthread
Vperm
 pthread_create requires
a single pointer to heap
memory
 Passing the pointer by
value when fork
Cilk
 More flexible, either
pass-by-ref or pass-byvalue
 Pass-by-ref and passby-value
VPERM: Variable Permissions for Concurrency Verification
26
Applicability: Cilk
cilk int fib (int n)
{
if (n<=1) return n;
else{
int x, y;
x = spawn fib (n-1);
y = spawn fib (n-2);
… // not safe to access x and y
sync;
return (x+y);
}
}
VPERM: Variable Permissions for Concurrency Verification
27
Applicability: Cilk
cilk int fib (int n)
void fib(int n, ref int result)
requires @value[n] & @full [result] & n>=0
ensures @full [result] & fiba(n, result );
{
{
if (n<=1) return n;
if (n<=1){ result = n; }
else{
else{
int x, y;
int x, y;
x = spawn fib (n-1);
int id1 = fork(fib,n−1, x);
y = spawn fib (n-2);
int id2 = fork(fib,n−2, y);
… // not safe to access x and y
… // cannot access x and y
sync;
join(id1);
join(id2);
return (x+y);
result=x+y;
}
}
}
}
VPERM: Variable Permissions for Concurrency Verification
28
Experiments
Trade-off: higher verification time (machine effort) BUT less manual
annotation (human effort).
Download or try VPERM online at
http://loris-7.ddns.comp.nus.edu.sg/~project/vperm/
VPERM: Variable Permissions for Concurrency Verification
29
Conclusion
A simple permission system for variables
 Simple to understand
 Simple to reason about
 Simple to infer
Expressive enough to capture real-world
programming languages such as Pthreads,
Cilk
Feasible to incorporate into a tool VPERM
Experiments show less annotation
overheads compared to state-of-the-art
VPERM: Variable Permissions for Concurrency Verification
30
Q&A
THANK YOU
leduykha@comp.nus.edu.sg
Download or try VPERM online at
http://loris-7.ddns.comp.nus.edu.sg/~project/vperm/
END
VPERM: Variable Permissions for Concurrency Verification
31
Limitations
Phased Accesses to Shared Variables
 Read outside a critical region but write inside
a critical region
 This requires partial permissions
 BUT we could use pseudo-heap locations for
this type of complex reasoning
VPERM: Variable Permissions for Concurrency Verification
32
Phased Accesses
inv<x,a,b> := @full[x] & @half[a,b] & x=a+b;
int x=0; int a = 0; int b = 0; lock l;
//@full[x,a,b,l]
init(l);
//@full[l] & half[a,b]
// l is passed by value to child thread
//full[l] & half[a]
acquire(l);
//full[l,x,a] & half[b]
x = x +1;
a = 1;
//full[l,x,a] & half[b]
release(l);
//full[l] & half[a]
//full[l] & half[b]
acquire(l);
//full[l,x,b] & half[a]
x = x +1;
b = 1;
//full[l,x,b] & half[a]
release(l);
//full[l] & half[b]
//@full[l] & half[a,b]
assert(x’=2);
For this complex reasoning, convert two integer auxiliary variables a,b to
int_ptr and use the complex reasoning over heap
Phased Accesses
inv<x,a,b> := @full[x] & x=a.val+b.val;
int x=0; int_ptr a = new int_ptr(0); int_ptr b = new int_ptr(0); lock l;
//@full[x,a,b,l]
init(l);
//@full[l] & half[a,b]
// l,a,b is passed by value to child thread
//a::int_ptr(1/2)<> & full[l,a]
acquire(l);
//full[l,x,a] & half[b]
x = x +1;
a.val = 1;
//full[l,x,a] & half[b]
release(l);
//full[l] & half[a]
//full[l] & half[b]
acquire(l);
//full[l,x,b] & half[a]
x = x +1;
b.val = 1;
//full[l,x,b] & half[a]
release(l);
//full[l] & half[b]
//@full[l] & half[a,b]
assert(x’=2);
For this complex reasoning, convert two integer auxiliary variables a,b to
int_ptr and use the complex reasoning over heap
Verification by Entailment Checking (Full)
VPERM: Variable Permissions for Concurrency Verification
35
Background
Heap vs stack
x1
 A stack variable x pointing to
 A heap location containing an integer
 E.g. int_ptr x = new int_ptr(1);
Separation logic
{x2 * y2} [x]=3 {x3 * y2}
Fractional permissions
0.5
0.5
1.0
{x2 * x2}  {x2}
How about program (stack) variables?
VPERM: Variable Permissions for Concurrency Verification
36
Background
Heap vs stack
x1
 A stack variable x pointing to
 A heap location containing an integer 1
 E.g. int_ptr x = new int_ptr(1);
Hoare’s logic
{x1 /\ y2} x=3 {x3 /\ y2}
{x2 /\ y2} x=3 {x3 /\ y2}
 ok
 what if x and y aliased ???
Separation logic
{x2 * y2} x=3 {x3 * y2}
 no alias
Fractional permissions
{x2 * x2}  {x2}
VPERM: Variable Permissions for Concurrency Verification
37
Download