Download presentation
Presentation is loading. Please wait.
1
Lazy Abstraction Lecture 2: Modular Analyses Ranjit Jhala UC San Diego With: Tom Henzinger, Rupak Majumdar, Ken McMillan, Gregoire Sutre
2
Program Verification by Lazy Abstraction Ranjit Jhala UC San Diego Lecture 1 With: Tom Henzinger, Rupak Majumdar, Ken McMillan, Gregoire Sutre
3
Last lecture … Lazy Abstraction for Sequential Programs Predicates: –Abstract infinite program states Counterexample-guided Refinement: –Find predicates tailored to prog, property 1.Abstraction : Expensive Reachability Tree 2.Refinement : Find predicates, use locations Proof of unsat of TF + Interpolation
4
This Lecture: Modular Analyses Procedures - Summaries Concurrency - Thread-Context Reasoning
5
An example main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; } main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; }
6
Inline Calls in Reach Tree main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; } main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } 1 2 1,2 Initial 2,2 4,2 3,2 4,2 3 3 4 1,4 2,4 4,4 3,4 4,4 5 5
7
Inline Calls in Reach Tree 1 2 1,2 Initial 2,2 4,2 3,2 4,2 3 3 4 1,4 2,4 4,4 3,4 4,4 5 5 Problem -Repeated analysis for “inc” -Exploding call contexts int x; //global f1(){ 1: x = 0; 2: if(*) f2(); 3: else f2(); 4: if (x<0) ERROR; return; } int x; //global f1(){ 1: x = 0; 2: if(*) f2(); 3: else f2(); 4: if (x<0) ERROR; return; } f2(){ 1: if(*) f3(); 2: else f3(); return; } f2(){ 1: if(*) f3(); 2: else f3(); return; } f3(){ 1: if(*) f4(); 2: else f4(); return; } f3(){ 1: if(*) f4(); 2: else f4(); return; } f4(){ 1: if(*) f5(); 2: else f5(); return; } f4(){ 1: if(*) f5(); 2: else f5(); return; } fn(){ 1: x ++; return; } fn(){ 1: x ++; return; } 2 n nodes in Reach Tree
8
Inline Calls in Reach Tree 1 2 1,2 Initial 2,2 4,2 3,2 4,2 3 3 4 1,4 2,4 4,4 3,4 4,4 5 5 Problem -Repeated analysis for “inc” -Exploding call contexts -Cyclic call graph (Recursion) -Infinite Tree!
9
Solution : Procedure Summaries Summaries: Input/Output behavior Plug summaries in at each callsite … instead of inlining entire procedure [Sharir-Pnueli 81, Reps-Horwitz-Sagiv 95] Summary = set of (F F’) –F : Precondition formula describing input state –F’ : Postcondition formula describing output state
10
Solution : Procedure Summaries Summaries: Input/Output behavior Plug summaries in at each callsite … instead of inlining entire procedure [Sharir-Pnueli 81, Reps-Horwitz-Sagiv 95, Ball-Rajamani 01] Summary = set of (F F’) –F : Precondition formula describing input state –F’ : Postcondition formula describing output state inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } ( : sign=0 rv > a) (sign = 0 rv < a) Q. How to compute, use summaries ?
11
Lazy Abstraction + Procedure Summaries Abstract Refine C Program Safe Trace Yes No Property Q. How to compute, use summaries ?
12
Abstraction with Summaries main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; } main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } 1 2 main Predicates: flag=0, y>x, y<z sign=0, rv>a, rv<a : flag=0 a=x sign=flag : sign=0 [flag!=0]
13
Abstraction with Summaries main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; } main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } 1 2 1 main 2 4 Predicates: flag=0, y>x, y<z sign=0, rv>a, rv<a inc : flag=0 : sign=0 a=x sign=flag : sign=0 [sign!=0] : sign=0 rv=a+1 rv>a Summary: ( : sign=0 rv>a),
14
Summary Successor main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; } main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } 1 2 1 main 2 4 Predicates: flag=0, y>x, y<z sign=0, rv>a, rv<a inc : flag=0 : sign=0 rv>a Summary: ( : sign=0 rv>a), 3 a=x sign=flag y>x assume rv>a y=rv
15
Abstraction with Summaries main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; } main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } 1 2 1 main 2 4 Predicates: flag=0, y>x, y<z sign=0, rv>a, rv<a inc : flag=0 : sign=0 rv>a Summary: ( : sign=0 rv>a), 3 y>x [y<=x] 3 4 flag=0 a=x sign=flag sign=0 [sign=0] [flag==0]
16
Abstraction with Summaries main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; } main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } 1 2 1 main 2 4 Predicates: flag=0, y>x, y<z sign=0, rv>a, rv<a inc : flag=0 : sign=0 rv>a Summary: ( : sign=0 rv>a), (sign=0 rv<a) 3 y>x 3 4 flag=0 a=x sign=flag sign=0 1 2 3 4 rv<a
17
Summary Successor main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; } main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } 1 2 1 main 2 4 Predicates: flag=0, y>x, y<z sign=0, rv>a, rv<a inc : flag=0 : sign=0 rv>a Summary: ( : sign=0 rv>a), (sign=0 rv<a) 3 y>x 3 4 flag=0 1 sign=0 2 3 4 rv<a a=x sign=flag assume rv<a y=rv 3 y<z
18
Abstraction with Summaries main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; } main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } 1 2 1 main 2 4 Predicates: flag=0, y>x, y<z sign=0, rv>a, rv<a inc : flag=0 : sign=0 rv>a Summary: ( : sign=0 rv>a), (sign=0 rv<a) 3 y>x 3 4 flag=0 1 sign=0 2 3 4 rv<a 3 y<z [y>=z]
19
Another Call … main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } 6: y1 = inc(z1,1); 7: if (y1<=z1) ERROR; return; } main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } 6: y1 = inc(z1,1); 7: if (y1<=z1) ERROR; return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } 1 2 1 main 2 4 inc : flag=0 : sign=0 rv>a Summary: ( : sign=0 rv>a), (sign=0 rv<a) 3 6 y>x 3 4 flag=0 1 sign=0 2 3 4 rv<a 3 y<z a=z1 sign=1 : sign=0 6 Predicates: flag=0,y>x,y z1 sign=0, rv>a, rv<a
20
Another Call … main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } 6: y1 = inc(z1,1); 7: if (y1<=z1) ERROR; return; } main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } 6: y1 = inc(z1,1); 7: if (y1<=z1) ERROR; return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } 1 2 1 main 2 4 Predicates: flag=0,y>x,y z1 sign=0, rv>a, rv<a inc : flag=0 : sign=0 rv>a Summary: ( : sign=0 rv>a), (sign=0 rv<a) 3 6 y>x 3 4 flag=0 1 sign=0 2 3 4 rv<a 3 y<z 7 a=z1 sign=1 assume rv>a y1=rv 6 y1>z1 SAFE Note: Predicates are well-scoped …
21
Lazy Abstraction + Procedure Summaries Abstract Refine C Program Safe Trace Yes No Property Q. How to find scoped predicates ?
22
pc 1 : x 1 = 3 pc 2 : assume (x 1 >0) pc 3 : x 3 = f 1 (x 1 ) pc 4 : y 2 = y 1 pc 5 : y 3 = f 2 (y 2 ) pc 6 : z 2 = z 1 +1 pc 7 : z 3 = 2*z 2 pc 8 : return z 3 pc 9 : return y 3 pc 10 : x 4 = x 3 +1 pc 11 : x 5 = f 3 (x 4 ) pc 12 : assume(w 1 <5) pc 13 : return w 1 pc 14 : assume x 4 >5 pc 15 : assume (x 1 =x 3 +2) Traces with Procedure Calls Trace Formula i Trace i Find predicate needed at point i pc 1 : x 1 = 3 pc 2 : assume (x 1 >0) pc 3 : x 3 = f 1 (x 1 ) pc 4 : y 2 = y 1 pc 5 : y 3 = f 2 (y 2 ) pc 6 : z 2 = z 1 +1 pc 7 : z 3 = 2*z 2 pc 8 : return z 3 pc 9 : return y 3 pc 10 : x 4 = x 3 +1 pc 11 : x 5 = f 3 (x 4 ) pc 12 : assume(w 1 <5) pc 13 : return w 1 pc 14 : assume x 4 >5 pc 15 : assume(x 1 =x 3 +2)
23
Interprocedural Analysis Trace Formula i Trace i Require at each point i : Scoped predicates YES: Variables visible at i NO: Caller’s local variables Find predicate needed at point i YES NO
24
Problems with Cutting Trace Formula i Trace i -- ++ Caller variables common to - and + Unsuitable interpolant: not well-scoped
25
Scoped Cuts Trace Formula i Call begins Trace i
26
Scoped Cuts -- ++ Trace Formula i Call begins Trace i Predicate at pc i = Interpolant from cut i
27
Common Variables Formals Current locals Trace Formula Predicate at pc i = Interpolant from i-cut i Trace i -- ++ Common Variables Formals Well-scoped
28
Example Trace m1: assume(flag!=0) m2: y=inc(x,flag) i1: assume(sign!=0) i2: rv = a+1 i4: return rv m3: assume(y<=x) ERROR: main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; } main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; } inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; }
29
Trace Formula Trace SSA Trace m1: assume(flag!=0) m2: y=inc(x,flag) i1: assume(sign!=0) i2: rv = a+1 i4: return rv m3: assume(y<=x) m1: assume(flag 0 !=0) m2: a 0 =x 0, sign 0 =flag 0 i1: assume(sign 0 !=0) i2: rv 0 =a 0 +1 i4: y 0 =rv 0 m3: assume(y 0 <= x 0 )
30
Trace Formula TraceTrace Formula m1: assume(flag!=0) m2: y=inc(x,flag) i1: assume(sign!=0) i2: rv = a+1 i4: return rv m3: assume(y<=x) Æ flag 0 0 Æ a 0 =x 0 Æ sign 0 = flag 0 Æ sign 0 0 Æ rv 0 =a 0 +1 Æ y 0 =rv 0 Æ y 0 <= x 0 ii Call begins
31
Trace Formula TraceTrace Formula m1: assume(flag!=0) m2: y=inc(x,flag) i1: assume(sign!=0) i2: rv = a+1 i4: return rv m3: assume(y<=x) Æ flag 0 0 Æ a 0 =x 0 Æ sign 0 = flag 0 Æ sign 0 0 Æ rv 0 =a 0 +1 Æ y 0 =rv 0 Æ y 0 <= x 0 -- ++ ii
32
Trace Formula TraceTrace Formula m1: assume(flag!=0) m2: y=inc(x,flag) i1: assume(sign!=0) i2: rv = a+1 i4: return rv m3: assume(y<=x) Æ flag 0 0 Æ a 0 =x 0 Æ sign 0 = flag 0 Æ sign 0 0 Æ rv 0 =a 0 +1 Æ y 0 =rv 0 Æ y 0 <= x 0 i -- ++ i rv 0 a0a0 a0a0 rv 0 > a 0 Interpolate
33
Lazy Abstraction + Procedure Summaries Abstract Refine C Program Safe Trace Yes No Property Q. How to find scoped predicates ? Solution: Scoped Cuts + Interpolation
34
Review : Procedures Modular Analysis via Summaries –Summary = (In,Out) vertices’ formulas Requires scoped predicates –Scoped cuts + Interpolation
35
This Lecture: Modular Analyses Procedures - Summaries Concurrency - Thread-Context Reasoning
36
This Lecture: Modular Analyses Procedures - Summaries Concurrency - Thread-Context Reasoning
37
Multithreaded Programs OS, WebServers, Databases, Embedded Systems Curse of Interleaving Non-deterministic scheduling Exponentially many behaviors: hard to detect, reproduce errors Testing exercises a fraction of possible behaviors Thread Shared Memory x Thread Thread
38
Data Races x:= x+1 x:= x+1 x:= x-5 x:= x-5 x A data race on x is a state where: Two threads can access x One of the accesses is a write Unpredictable, undesirable Synchronization: Must hold lock when accessing x lock(l) unlock(l) lock(l) unlock(l)
39
Previous Work : Locks x:= x+1 x:= x+1 lock(l) unlock(l) 1.Infer some lock(s) that protect x 2.Check lock(s) held when accessing x 3.Report error if lock(s) not held Static LockSet [Sterling 93], [Engler-Ashcraft 03] [Flanagan-Freund 00] [Bacon et al. 00] [Boyapati et al. 02] [Dinning-Schonberg 90] [Savage et al. 97] [Cheng et al. 98] [Choi et al. 02] Type-based Dynamic LockSet Object Usage Graph [von Praun-Gross 03] Scalable Restricted to locking
40
Other Synchronization Idioms Producer-Consumer atomic{ old:= state; if(state==0){ state:=1; } if(old==0){ x++; state:=0; } atomic{ old:= state; if(state==0){ state:=1; } if(old==0){ x++; state:=0; } State-basedInterrupt-toggling x
41
Previous Work : Model Checking Producer-Consumer atomic{ old:= state; if(state==0){ state:=1; } if(old==0){ x++; state:=0; } atomic{ old:= state; if(state==0){ state:=1; } if(old==0){ x++; state:=0; } State-basedInterrupt-toggling x Model Checking (State Exploration) [Godefroid 97] [Holzmann][Havelund-Visser] [Dwyer-Hatcliff][Avrunin-Clarke] [Musuvathi-Dill-Engler 02] [Yahav 01] Any Synch. Idiom Fixed #threads Manual Abstraction State Explosion
42
Data Race Shared Memory Initial Race Checking by State Exploration Is there a path from Initial to Race ?
43
Problem: State Explosion Shared Memory Data Race Initial Is there a path from Initial to Race ?
44
Problem: State Explosion 2. Control k threads, m locations = m k - k=4,m=100, states = 1 billion Unbounded threads ? 1. Data Infinitely many valuations for program variables Data Race Initial
45
LA for Multithreaded Programs 1.Data Races –Previous Work –State Explosion 2.Abstractions 3.Context Inference
46
1.Data Races –Previous Work –State Explosion 2.Abstractions 3.Context Inference LA for Multithreaded Programs
47
Problem: State Explosion 2. Control k threads, m locations = m k - k=4,m=100, states = 1 billion Unbounded threads ? 1. Data Infinitely many valuations for program variables Data Race Initial
48
Solution: Abstract Irrelevant Detail 1. Data Infinitely many valuations for program variables 2. Control k threads, m locations = m k - k=4,m=100, states = 1 billion Unbounded threads ? Observe - Analyze system as Thread + Context - Context: Summary of all other threads (w.r.t. property) 2. Thread-Context Analysis Observe - Few relevant variables, relationships - Track predicates (relationships) instead of values 1. Predicate Abstraction
49
Example Check for races on x: Initially: s is 0 1 st thread into atomic : - sets old to 0 (value of s ) - sets s to 1 - passes test before access Later threads: - set old to 1 (value set by 1 st thread) - fail test before access (until the 1 st thread is done) 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work() 5: if(old==0){ 6: x++; 7: s:=0;} } 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work() 5: if(old==0){ 6: x++; 7: s:=0;} }
50
1.Data Races –Previous Work –State Explosion 2.Abstractions –Data: Predicate Abstraction –Control: Thread-Context Reasoning 3.Verifying Multithreaded Programs LA for Multithreaded Programs
51
Predicate Abstraction 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work() 5: if(old==0){ 6: x++; 7: s:=0;} } 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work() 5: if(old==0){ 6: x++; 7: s:=0;} } Predicates on Variables s=0, old=0 s=0 1 2 3 4 1 Reachability Graph s=0 s=0, old=0 5 6 : s=0, old=0 : s=0 old=0 s=0 old=0 Q: What about other threads ? x++
52
1.Data Races –Previous Work –State Explosion 2.Abstractions –Data: Predicate Abstraction –Control: Contexts Thread-Context Reasoning 3.Context Inference LA for Multithreaded Programs
53
Threads, Contexts Q: What about other threads ? Shared Memory Assume threads run same code Context: Summary of all other threads - Precise enough to check property System = Thread + Context Q: What does a Context look like ? Context
54
Thread, Contexts Context: Summary of all other threads 1. Summarize a single thread 2. Multiple threads by counting Q: What does a Context look like ? Shared Memory Context 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work() 5: if(old==0){ 6: x++; 7: s:=0;} } 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work() 5: if(old==0){ 6: x++; 7: s:=0;} } s=0 s s,x s0s0 s0s0 ThreadSummary Context
55
Many Threads by Counting s=0 s s,x s0s0 s0s0 Context True 1 1 1 0 0 0 s=0 State s 0s 0 s 0 Æ s=0 Initial loc = 1, other = 0 Operations 1. Pick edge w/ source counter > 0, 2. Source counter -1 Target counter +1 Havoc variables on edge, Assume predicate on target Unbounded threads k-Counter Abstraction: Value > k abstracted to 1 for k=1, values: 0,1, 1 Q: What does a Context look like ? 1 Contra! 1 2 1
56
1.Data Races –Previous Work –State Explosion 2.Abstractions –Data: Predicate Abstraction –Control: Contexts Thread-Context Reasoning 3.Context Inference LA for Multithreaded Programs
57
Thread-Context Reasoning Q: How to check race-freedom ? Given an Abstraction: 1. Data:Predicates 2. Control: Summary, k 1 Use Context Build finite Reach Graph Check Race unreachable 2 Verify Context Sound Check Summary Overapproximates single Thread’s behavior k k Shared Memory No Race µ Reach Graph Summarize Computed Summary Given Summary
58
Q: How to check race-freedom ? Given an Abstraction: 1. Data:Predicates 2. Control: Summary, k 1 2 Shared Memory Assume-Guarantee (Use) (Verify) No Race k Shared Memory No Race µ Reach Graph Summarize Thread-Context Reasoning Computed Summary Given Summary
59
1.Data Races –Previous Work –State Explosion 2.Abstractions –Data: Predicate Abstraction –Control: Thread-Context Reasoning 3.Context Inference LA for Multithreaded Programs
60
1.Data Races –Previous Work –State Explosion 2.Abstractions –Data: Predicate Abstraction –Control: Thread-Context Reasoning 3.Context Inference LA for Multithreaded Programs
61
Inference: Build Summary 1 Reach Grap h 2 ; µ ; Summarize 1 Reach Grap h No Race Race Trace Abstraction Preds: P 0 Ctr: k 0
62
Inference: Trace Analysis Trace FeasibleInfeasible Refine using Trace Either: 1.Add new predicates 2.Increase k Abstraction Preds: P 0 Ctr: k 0 Report Trace Interleaved sequence of threads’ ops Abstraction Preds: P 1 Ctr: k 1
63
Inference: Build Summary 1 Reach Graph 2 µ ; Summarize Abstraction Preds: P 0 Ctr: k 0 Abstraction Preds: P 1 Ctr: k 1 1 Reach Graph 2 µ Summarize 1 Reach Graph 2 µ Summarize ;
64
Context Inferred 1 Reach Graph 2 µ Summarize Shared Memory Assume-Guarantee No Race
65
NO (trace) Context Inference Init. Abstraction Preds: P 0 Ctr: k 0 Init. Summary Summary: ; 1 Reach Graph YES Summarize Safe? 2 µ ? YES NO Update Summary Refine using Trace Feasible? YES NO Output SAFE No Data Races Output Data Race TRACE ANALYSIS BUILD SUMMARY
66
Plan 1.Data Races –Previous Work –State Explosion 2.Abstractions –Data: Predicate Abstraction –Control: Thread-Context Reasoning 3.Context Inference –Example
67
Ex: Races on x 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work() 5: if(old==0){ 6: x++; 7: s:=0;} } 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work() 5: if(old==0){ 6: x++; 7: s:=0;} } ; Abstraction Preds = ; k=1 1 2 3 4 5 6 Reach Graph T 7 x++; Summarize 2 µ ; 1 x Build Summary x Control-Flow Graph
68
Ex: Races on x 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work() 5: if(old==0){ 6: x++; 7: s:=0;} } 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work() 5: if(old==0){ 6: x++; 7: s:=0;} } Abstraction Preds = ; k=1 Reach Graph 1 Build Summary x 1 2 3 4 5 6 x++ 6 Race x
69
Thread 1 Ex: Races on x 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work() 5: if(old==0){ 6: x++; 7: s:=0;} } 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work() 5: if(old==0){ 6: x++; 7: s:=0;} } Abstraction Preds = ; k=1 Reach Graph 1 Trace Analysis x 1 2 3 4 5 6 x++ 6 Trace x Thread 0 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work() 5: if(old==0){ 6: x++; 7: s:=0;} } 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work() 5: if(old==0){ 6: x++; 7: s:=0;} } x assume (True) old := s assume (s==0) s:= 1 // do_work() assume (old==0) //write x enabled 1 2 3 4 5 6 T 7 x++; assume (True) old := s assume (s==0) s:= 1 // do_work() assume (old==0) //write x enabled
70
Thread 1 Ex: Races on x Trace Analysis Trace Thread 0 assume (True) old := s assume (s==0) s:= 1 // do_work() assume (old==0) //write x enabled assume (True) old := s assume (s==0) s:= 1 // do_work() assume (old==0) //write x enabled Time s is set to 1 Infeasible branch New Predicate s = 0 Infeasible Trace
71
Ex: Races on x 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work() 5: if(old==0){ 6: x++; 7: s:=0;} } 1: while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work() 5: if(old==0){ 6: x++; 7: s:=0;} } ; Abstraction Preds: s=0 k=1 Reach Graph Summarize 2 µ ; 1 Build Summary, old=0 s=0 1 2 3 4 s=0 old=0 5 6 : s=0 old=0 7 x++ s:=0 : s=0 old=0 Local Pred. old=0 - Prunes infeasible paths - Invisible to other threads - Quantified away s:=1 s=0 x s0s0 s s s0s0 x s0s0 s s s0s0
72
Ex: Races on x 1:while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work() 5: if(old==0){ 6: x++; 7: s:=0;} } 1:while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work() 5: if(old==0){ 6: x++; 7: s:=0;} } Abstraction Preds: s=0 k=1 Reach Graph Summarize 2 µ 1 Build Summary, old=0 1 2 3 4 s=0 Ç s 0 5 6 s=0 old=0 s 0 old=0 x++ s:=0 s:=1 T T 5 Context changes s s 0 old 0 s=0 s s,x s0s0 s0s0 s=0 x s0s0 s s s0s0 Local Pred. old=0 - Cuts locally infeasible paths - Invisible to other threads - Quantified away s=0 x s0s0 s s s0s0 s s,x s0s0 s0s0 s=0 Ç s 0
73
Ex: Races on x 1:while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work() 5: if(old==0){ 6: x++; 7: s:=0;} } 1:while(1){ atomic{ 2: old := s; 3: if(s==0){ 4: s := 1; } // do_work() 5: if(old==0){ 6: x++; 7: s:=0;} } Abstraction Preds: s=0 k=1 Reach Graph Sumz 2 µ 1 Build Summary, old=0 1 2 3 4 5 6 s=0 old=0 s 0 old=0 x++ s:=0 s:=1 T T T 5 s 0 old 0 s=0 s s,x s0s0 s0s0 s=0 s s,x s0s0 s0s0 s=0 s s,x s0s0 s0s0 SAFE No Races on x
74
Plan 1.Data Races –Previous Work –State Explosion 2.Abstractions –Data: Predicate Abstraction –Control: Thread-Context Reasoning 3.Context Inference –Example 4. Experiments
75
Data Races in NesC Programs PL for Networked Embedded Systems [Gay et al. 03] Interrupts fire events, which fire other events or post tasks which run asynchronously Race-freedom important –Non-trivial synchronization idioms –Flow-based analysis Compiled to C
76
Case Study: sense.nc atomic{ old:= state; if(state==0){ state:=1; } if(old==0){ x++; atomic{ old:= state; if(state==0){ state:=1; } if(old==0){ x++; Interrupt 1 fires old := state if (state ==0){ state := 1 assume (old == 0){ about to write x Interrupt 2 fires state := 0 Interrupt 1 fires old := state assume (state ==0){ state := 1 If (old == 0){ about to write x Interrupt 1 handler disables interrupt 2 BLAST finds information proves no races
77
Review : Multithreaded 1.Multithreaded Verification is hard –Data, Control Explosion –Abstract Irrelevant details 2.Combine Abstractions 1.Data: Predicates 2.Control: Contexts (Summary + Counter) 3.Iterative Context Inference
78
Next lecture … Partial-program analysis: From verification to interfaces
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.