Title: Joint work with Josh Berdine, Byron Cook,
1Thread-modular heap analysis
Alexey Gotsman University of Cambridge
- Joint work with Josh Berdine, Byron Cook,
- and Mooly Sagiv
TexPoint fonts used in EMF. Read the TexPoint
manual before you delete this box.
AAAAAAAAAAAAAAAAAAAA
2Heap analysis for multithreaded programs
Is this a well-formed cyclic doubly-linked list?
3Conventional approach Yahav 2001
- Enumerate interleavings using a sequential heap
analysis
...
...
...
...
State-space explosion
...
4Idea
- Analysis computes resource invariants and local
states - Thread-modularly by analysing one thread at a
time
lock(lk2) ... unlock(lk2) ...
lk1
lk2
5Example
Top-level parallel composition of threads
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y unlock(lk)
...
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext x
unlock(lk) ...
Critical regions
Static locks
LOCK lk init() h new LISTPTR
h-gtnext NULL
Initialisation routine for every data structure
6Example
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y unlock(lk)
...
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext x
unlock(lk) ...
LOCK lk init() h new LISTPTR
h-gtnext NULL
7Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
8Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
9Example
lk
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
10Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
11Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
12Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
13Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
14Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
lk
15Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
- Lock protects the part of the heap reachable from
a set of variables also protected by the lock
entry points - Reasonable guess variables that are accessed
only when the lock is held - Can be determined by correlation analyses
Locksmith, Eraser, ...
lk
16Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
17Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
18Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
19Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
20Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
21Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
22Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
23Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
24Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
25Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
26Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
27Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
28Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
29Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
30Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
31Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
32Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
33Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
34Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
35Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
36Example
thread1() ... lock(lk) x new
LISTPTR x-gtnext h-gtnext h-gtnext
x unlock(lk) ...
thread2() ... lock(lk) y
h-gtnext if (y ! NULL) h-gtnext
y-gtnext delete y
unlock(lk) ...
37Abstract interpretation
38Abstract interpretation with state separation
39Local functions Calcagno 2007
40Abstract interpretation with state separation
- Separation logic-based domains
- Shape graphs
41Soundness
Bonus program is data race free
42Frequently asked questions
43Concurrent separation logic OHearn 2004
precise unambiguously carves out an area of the
heap
44Arent we computing proofs in CSL?
- Resource invariants computed by the analysis
arent precise - Analysiss underlying logic is different from
CSL has no conjunction rule and no precision
restriction - We define the logic and the analysis and prove
them sound together - Can get conjunction rule back if heuristics for
heap splitting are semantically robust
45What about dynamically-allocated locks?
- Unbounded numbers of locks a finite number of
invariants - Abstract domain extended with elements
representing locks with a given invariant - Concurrent separation logic extended
appropriately - Details in APLAS07
- Joint work with Noam Rinetzky
46What about dynamic thread creation?
- Can use algorithms for interprocedural heap
analysis SAS06 - Part of the heap reachable from forks parameters
transferred to the thread - Concurrent separation logic extended
appropriately APLAS07
47What about fine-grained concurrency?
- Thread-modular analysis works well on programs
with coarse-grained synchronisation - Fine-grained synchronisation
- Allow abstract states to describe different views
of the same global heap - Uses conjunction rule to compute transfer
functions - Next talk!
- Apply rely-guarantee reasoning on the shared part
of the heap - Uses RGSep combination of rely-guarantee and
separation logic - Ongoing work by Vafeiadis and Yang
48Thread-modular heap analysis
- Scalable
- unlike enumerating interleavings
- Sound and precise in the presence of deep heap
update - unlike most race-detection analyses
- Handles ownership transfer
- unlike ownership type systems
- Fully automatic
- unlike systems based on VC generation