Post on 21-Jan-2016
description
Thread-modularAbstraction Refinement
Tom HenzingerRanjit Jhala
Rupak Majumdar[UC Berkeley]
Shaz Qadeer[Microsoft Research]
Introduction
• Model Checking Software– “Little theorems about big programs”– “automatic”, Path sensitive properties– Limited to sequential programs
• Thread-modular Reasoning– Efficiently decompose checks– Requires manual (or divine) intervention
• TAR: Thread-modular Abstraction Refinement – Eliminate the divine using abstraction-refinement– Safety checking for concurrent programs
The story so far ...
• Analyzing Sequential programs– BLAST/SLAM/…– Iterative Abstraction-Refinement [Kurshan ’93]
YES
SAFEexplanation
NO! (Trace)
BUG
feasible
Seed Abstraction
Program
Why infeasible ? infeasible
Refine
Abstract Is model safe ?Check
… and what of Concurrent Programs?
• Shared Memory (multithreaded)• Message Passing
• Hard to analyze ! – Interleavings / State explosion
• One approach: Thread-modular analysis– Analyse threads separately– Compose analyses
• [Jones ’83, CALVIN (FQS ’02), Assume-Guarantee]
The Problem
• boxes = threads• white denotes shared variables
Safety checking:Is an ERROR state
reachable ?
Thread-modular analysis (take1)
safe
safe
safe
Thread-modular analysis (take1)
safe
safe
• If only… !Threads are correct in constrained environments
Second Attempt: Summaries
• “Summarize” each thread’s behavior• Use/verify summaries (circular)
safe
Use Summaries (“Assume”)
safe
safe
Verify Summaries (“Guarantee”)
µ µ
safe
Thread-modular analysis (take 2)
µ
safe
µ
safe
safe
Our Contribution
• Problem with TM Reasoning:– Divining (small) summaries
? ?
• Algorithm TAR– Compute/use/verify summaries – Using iterative abstraction-refinement
An Example: Race Detection
Producer {
1: while (*) {
2: while (flag) {};
3: data = newdata();
4: flag = true; } }
Consumer { 1: while (*) {
2: while (!flag) {};
3: read = data;
4: flag = false;
}}
• Shared variables: data, flag, P, C• Error states: P Æ C• Initial states: : P Æ : C (Æ : flag)
P´ ´ C
An Example: Race Detection
Producer {
1: while (*) {
2: while (flag) {};
3: data = newdata();
4: flag = true; } }
Consumer { 1: while (*) {
2: while (!flag) {};
3: read = data;
4: flag = false;
}}
P´ ´ C
• Correctness Invariant:– Producer ensures: P ) :flag– Consumer ensures: C ) flag
SProducer{ : flag !(flag’ Ç :flag’)Æ :P’|: flag ! : flag’Æ P’}
Summaries
SConsumer{ flag !(flag’ Ç:flag’) Æ :C’| flag ! flag’ Æ C’}
Consumer { 1: while (*) {2: while (!flag) {};3: read = data;4: flag = false; }}
Producer {1: while (*) {2: while (flag) {};3: data = newdata();4: flag = true; } }
• Summary: Set of (present state, next state) pairs
Producer {
1: while (*) {
2: while (flag) {};
3: data = newdata();
4: flag = true;
}
Checking Safety [CALVIN]
• [use] Sequential program: Producer+ use BLAST/SLAM/ESC/…
• [verify] Every action of Producer+
is in SProducer
• Where do summaries come from?
Producer+{
1: while (*) {
2: while (flag) {};
3: data = newdata();
4: flag = true;
}
while(*){sConsumer ();}
while(*){sConsumer ();}
while(*){sConsumer ();}
safe
µ
Abstraction & Reachability
• Abstraction gives finite state space• Conservative
– Abstraction safe ) System safe – Too coarse ) spurious counterexample
Initial
Error
Refinement
• Using “spurious” error traces
Refinement
• Using “spurious” error traces– Add information to rule out spurious trace– e.g. Track more variables or predicates
• Repeat reachability– Till safe or real trace is found
Abstraction & Reachability
• Using “spurious” error traces– Add information to rule out spurious trace– e.g. Track more variables or predicates
• Repeat reachability– Till safe or real trace is found
safe
To Summarize
• Nodes labeled by abstract states• Each parent-child pair ! (present, next) pair
– Quantify out local state (e.g. program counter)– Take pairs where global state changes
Reachability Tree’
Producer+{1: while (*) {
2: while (flag) {};
3: data = newdata();
4: flag = true; }
while(*){sConsumer ();}
while(*){sConsumer ();}
while(*){sConsumer ();}
Tying up the threads
; ;
Refine using “spurious” error traces
Not yet the reachable set!
Summarize
Refined System
; ;
safe
Fixpoint
Running TAR on Example
Producer {
1: while (*) {
2: while (flag) {};
3: data = newdata();
4: flag = true; } }
Consumer { 1: while (*) {
2: while (!flag) {};
3: read = data;
4: flag = false;
}}
• Shared variables: data, flag, P, C• Error states: P Æ C• Initial states: : P Æ : C Æ : flag
P´ ´ C
;
Summary: : P Æ : C ! : P’ Æ C’ : P Æ C ! : P’ Æ : C’
Running TAR 1
;
Init: :P Æ :C
Error: P Æ C
Abs: P, C
Reach: : P Æ : C P Æ : C
Reach: : P Æ : C: P Æ C
Summary: : P Æ : C ! P’ Æ : C’ P Æ : C ! : P’Æ : C’
Consumer { 1: while (*) {2: while (!flag) {};3: read = data;4: flag = false; }
}
Producer {1: while (*) {2: while (flag) {};3: data = newdata();4: flag = true; } }
P Æ C P Æ C
P´ ´ C
Summary: C Æ flag ! : C’ Æ flag’: C Æ flag ! : C’ Æ : flag’ ! C’Æ flag
;
Summary:
Running TAR 2
;
Init: :P Æ :CÆ :flag
Error: P Æ C
Abs: P, C, flag
Reach: : P Æ : C Æ : flag P Æ : C Æ : flag
: P Æ : C Æ flag
Reach: : P Æ : C Æ : flag
Summary: : P Æ: flag ! P‘Æ : flag’
! : P’ Æ flag’P Æ : flag ! : P Æ: flag
Consumer { 1: while (*) {2: while (!flag) {};3: read = data;4: flag = false; }
}
Producer {1: while (*) {2: while (flag) {};3: data = newdata();4: flag = true; } }
: P Æ C Æ flag: C Æ flag: C Æ : flag
P´ ´ C
Only change if :flag Only change if flag
: P
Fixpoint
Track flag
:flag flag
;
Summary: flag ! ( flag’ Ç : flag’) Æ : C’ ! flag’ Æ C’
Running TAR 2
;
Reach: P Æ : C Æ : flag
: P
Reach: : P Æ C Æ flag: C
Summary:: flag ! (flag’ Ç : flag’) Æ :P’ ! : flag Æ P’
Consumer { 1: while (*) {2: while (!flag) {};3: read = data;4: flag = false; }
}
Producer {1: while (*) {2: while (flag) {};3: data = newdata();4: flag = true; } }
P´ ´ C
safe
Fixpoint
SUMMARIES LEARNT !
Bells and Whistles
• Havoc Abstractions:– Track only when the environment changes a variable
• Not what new value it changes it to
– For every global x, x denotes states where thread writes x
• Summary: if (x) then x = *
• No explicit global variables– Sharing via pointers that escape
Race Detection w/ Pointers
Producer { p = &buf; while (*) { while (p->flag) {}; p->data = newdata(); p->flag = true; p = p->next; } }
Consumer {
q = &buf; while (*) { while (!q->flag) {}; read = q->data; q->flag = false; q = q->next; }}
data
flag
Conclusions
• The moral …– TAR can check concurrent software– w/o (really) exploring all interleavings
• The devil …– Shared memory via pointers– Explicating local state
• Need to track some local state of “other” threads
– Approximate Counterexample analysis
• Implemented TAR in BLAST– Race checking for drivers (each client is a thread)– Linux/Windows drivers 1-10 Kloc
• Looking for examples and properties …
BLAST
www.eecs.berkeley.edu/~tah/blast/www.eecs.berkeley.edu/~tah/blast/
Berkeley Lazy Abstraction Berkeley Lazy Abstraction Software * ToolSoftware * Tool
safe
Use Summaries (“Assume”)
safe
safe
Verify Summaries (“Guarantee”)
µ µ
safe