radar: dataflow analysis for concurrent programs using datarace detection ravi chugh, jan voung,...
Post on 21-Dec-2015
237 views
TRANSCRIPT
RADAR: Dataflow Analysis for Concurrent Programs using
Datarace Detection
Ravi Chugh, Jan Voung, Ranjit Jhala, Sorin Lerner{rchugh, jvoung, jhala, lerner} @ cs.ucsd.edu
UC San Diego
Studying Concurrency is Important
• A “counting argument”• > wget
http://pldi2008.cs.ucr.edu/program_schedule.html• > grep –i “concurr” program_schedule.html | wc –l
• 6
Sequential Reasoning is Incorrect
if (p != null) {
use(p);
p = null;
}
p = new_or_die();
p != null
x = compute();
p != null
*p = x;
Sequential Optimization is Incorrect
g = compute();
flag = 1;
flag = 0;
while (flag == 0) { /* spin */ }
use(g);
0
Constant propagation would be incorrect
• Compilers forced to be conservative• Optimization opportunities missed
ConcurrencyAnalysis
RaceDetector
Our Approach
ConcurrentDataflowAnalysis
SequentialDataflowAnalysis
RADAR
RaceDetector
Modular Framework
SequentialNon-NullAnalysis
SequentialConstantAnalysis
SequentialDataflowAnalysis
ConcurrentDataflowAnalysis
RADARConcurrent
Non-NullAnalysis
ConcurrentConstantAnalysis
Modular Framework
RADAR
RaceDetector
SequentialConstantAnalysis
ConcurrentConstantAnalysis
precise scalable
RADAR: Results
• Concurrent non-null analysis
• Scales to:– Apache (~130 KLOC)– OpenSSL (~210 KLOC)– subset of Linux kernel (~830 KLOC)
Example with Locks
lock(l);
if (p != null) {
use(p);
p = null;
}
unlock(l);
lock(l);
p = new_or_die();
x = compute();
*p = x;
unlock(l);
lock(l);
if (p != null) {
use(p);
p = null;
}
unlock(l);
Can this be Optimized?
lock(l);
p = new_or_die();
unlock(l);
x = compute();
lock(l);
*p = x;
unlock(l);
Optimized Version is Race-free
lock(l);
if (p != null) {
use(p);
p = null;
}
unlock(l);
lock(l);
p = new_or_die();
unlock(l);
x = compute();
lock(l);
*p = x;
unlock(l);
lock(l);
if (p != null) {
use(p);
p = null;
}
unlock(l);
Oops…
lock(l);
p = new_or_die(); unlock(l); x = compute();
lock(l);
*p = x;
unlock(l);
lock(l);
p = new_or_die(); p != nullunlock(l); p != nullx = compute(); p != nulllock(l); p != null*p = x; p != nullunlock(l);
Sequential Non-Null Analysis
lock(l);
if (p != null) { p != null use(p); p != null p = null; p != null}
unlock(l);
RADAR on Example
lock(l);
if (p != null) { p != null use(p); p != null p = null; p != null}
unlock(l);
lock(l);
p = new_or_die(); p != nullunlock(l); p != nullx = compute(); p != nulllock(l); p != null*p = x; p != nullunlock(l);
lock(l);
p = new_or_die(); p != nullunlock(l);
x = compute();
lock(l);
*p = x;
unlock(l);
RADAR on Example
Can fact be invalidated by concurrent thread?
Can p be written by a concurrent thread?
lock(l);
p = new_or_die(); p != nullunlock(l);
x = compute();
lock(l);
*p = x;
unlock(l);
RADAR on Example
pseudo-read(p) RaceDetector
Can p be written by a concurrent thread?
Race
No Race
lock(l);
p = new_or_die(); p != nullunlock(l); x = compute();
lock(l);
*p = x;
unlock(l);
RADAR on Example
pseudo-read(p)
Can p be written by a concurrent thread?
Race
No RaceRace
Detector
lock(l);
p = new_or_die(); p != nullunlock(l); p != nullx = compute();
lock(l);
*p = x;
unlock(l);
RADAR on Example
pseudo-read(p)
RaceDetector
Race
No Race
lock(l);
p = new_or_die(); p != nullunlock(l); p != nullx = compute(); p != nulllock(l); p != null*p = x;
unlock(l);
RADAR on Example
UNSAFE
RADAR on Safe Example
lock(l);
p = new_or_die();
p != null
x = compute();
*p = x;
unlock(l);
RaceDetector
Race
No Race
pseudo-read(p)
RADAR on Safe Example
lock(l);
p = new_or_die();
p != null
x = compute();
p != null
*p = x;
unlock(l);
RaceDetector
Race
No Race
pseudo-read(p)
RADAR on Safe Example
lock(l);
p = new_or_die();
p != null
x = compute();
p != null
*p = x;
unlock(l);
SAFE
(1) Round-trip Queries
lock(l);
p = new_or_die(); p != nullunlock(l); p != nullx = compute(); p != nulllock(l); p != null*p = x; p != nullunlock(l);
Possible Race
Allow sequential analysis to run
pseudo-read(p) RaceDetector
Race
No Race
Get superset of (concurrent) facts
pseudo-read(p)
lock(l);
p = new_or_die(); p != nullunlock(l); p != nullx = compute(); p != nulllock(l); p != null*p = x; p != nullunlock(l);
(1) Round-trip Queries
Insert all pseudo-reads at once
pseudo-read(p)
pseudo-read(p)
pseudo-read(p)
pseudo-read(p)
pseudo-read(p)
RaceDetector
Send whole program to race detector
(1) Round-trip Queries
lock(l);
p = new_or_die(); p != nullunlock(l); p != nullx = compute(); p != nulllock(l); p != null*p = x; p != nullunlock(l);
pseudo-read(p)
pseudo-read(p)
pseudo-read(p)
pseudo-read(p)
pseudo-read(p)
Get results back from Race Detector
(1) Round-trip Queries
lock(l);
p = new_or_die(); unlock(l);
x = compute();
lock(l);
*p = x;
unlock(l);
pseudo-read(p)
pseudo-read(p)
pseudo-read(p)
pseudo-read(p)
pseudo-read(p)
Get results back from Race Detector
Rerun analysis using race results
(1) Round-trip Queries
lock(l);
p = new_or_die(); p != nullunlock(l); p != nullx = compute();
lock(l);
*p = x;
unlock(l);
Rerun analysis using race results
(1) Round-trip Queries
lock(l);
p = new_or_die(); p != nullunlock(l); p != nullx = compute(); p != nulllock(l); p != null*p = x;
unlock(l);
UNSAFE
(2) Handling Procedures
Unlock in foo allows interference
lock(l);
if (p != null) {
foo();
*p = 10;
}
unlock(l);
void foo () {
if (*) {
unlock(l);
compute();
lock(l);
}
}
lock(l);
p = null;
unlock(l);
Want to summarize effect of calling foo
(2) Handling Procedures
lock(l);
if (p != null) {
foo();
*p = 10;
}
unlock(l);
void foo () {
if (*) {
unlock(l);
compute();
lock(l);
}
}
lock(l);
p = null;
unlock(l);
lock(l);
if (p != null) {
foo();
*p = 10;
}
unlock(l);
(2) Handling Procedures
pseudo-unlock(l);pseudo-read(p);pseudo-lock(l);
In the caller, RADAR inserts:• pseudo-unlock for every unlock in foo• pseudo-reads
Experiments: Benchmarks
• Apache 2.2.6 (130 KLOC)– worker threads + modules (e.g., caches)
• OpenSSL 0.9.8g (210 KLOC)– model a multi-threaded client
• Linux 2.6.15 (830 KLOC)– subset from RELAY experiments
50
60
70
80
90
100
Apache SSL Linux
Sequential Race Detector+ =
Non-Null Never raceOptimistic
(sequential)
Non-Null
Non-Null
Non-Null Escapes ⇒ race Conservative
50
60
70
80
90
100
Apache SSL Linux
GAP
Sequential Race Detector+ =
Non-Null
Non-Null
Non-Null
Non-Null
Never raceOptimistic
(sequential)
Escapes ⇒ race Conservative
Shared ⇒ race
No locks ⇒ race
50
60
70
80
90
100
Apache SSL Linux
Sequential Race Detector+ =
Non-Null
Non-Null
Non-Null
Non-Null
Optimistic (sequential)
Conservative
Never race
Escapes ⇒ race
Shared ⇒ race
No locks ⇒ race
Sources of Imprecision
• Alias analysis– affects sequential dataflow and race detection
• Lockset-based race analysis– ignores fork, join, condition variables
• RADAR framework– pseudo-read (for non-null fact) races with – “x = NonNullAddress;”
Related Work
• Programming-model-based approaches– [Knoop et al 96], [Grunwald et al 93], …– par-begin / par-end– handles introduction of facts between threads
• Thread-modular– [Owicki et al 76], [Jones 83], [Flanagan et al 03], …– more precise (use environment assumption)– inference not as scalable
Conclusion
RADAR
RaceDetector
SequentialDataflowAnalysis
ConcurrentDataflowAnalysis
precise scalable