Download presentation
Presentation is loading. Please wait.
Published byYvette Cayton Modified over 10 years ago
1
Race Directed Random Testing of Concurrent Programs KOUSHIK SEN - UNIVERSITY OF CALIFORNIA, BERKELEY PRESENTED BY – ARTHUR KIYANOVSKI – TECHNION, ISRAEL
2
Goal Verify Data Races Automatically Efficiently No false alarms Being able to reproduce races
3
Background
4
Data Race - Definition Two or more threads access the same memory location concurrently At least one of the accesses is for writing x=1 if (x==1) … Temporally next to each other
5
Data Race – Another Example Thread 2: X=X+1; Thread 1: X=X+1; What “actually happens” in x=x+1? 1.Read x to tmp 2.Add 1 to tmp 3.Write tmp to X
6
Not a Data Race! Thread 2: Lock(L); X=X+1; Unlock(L); Thread 1: Lock(L); X=X+1; Unlock(L);
7
Multithreaded Testing On One CPU Lets say we have 2 threads – blue and red. There is a data race between red 3 and blue 3. Let’s show a way of running them on 1 CPU that can find the same Data Races that running them on 2 CPUs can. 1 2 3 1 2 3 Data Race
8
Once upon a time… Testing concurrent programs
9
The Simple Traditional Way Repeatedly execute the program with the hope that different test executions will result in different interleavings.
10
Advantages Of The Traditional Way Inexpensive compared to sophisticated techniques such as model checking and verification
11
Problems With The Traditional Way Outcome highly dependent on the test environment. Some interleavings may only occur on heavily-loaded test systems. Depends on the underlying operating system for thread scheduling Often ends up executing the same interleaving many times.
12
Simple Randomized Algorithm Simple Scheduler At every state during a concurrent execution –Pick a thread randomly –Execute the next instruction of the thread Slide taken and adapted from the original slides of Koushik Sen for PLDI08
13
Simple Randomized Algorithm Simple Scheduler At every state during a concurrent execution –Pick a thread randomly –Execute the next instruction of the thread Slide taken and adapted from the original slides of Koushik Sen for PLDI08
14
Simple Randomized Algorithm Simple Scheduler At every state during a concurrent execution –Pick a thread randomly –Execute the next instruction of the thread Slide taken and adapted from the original slides of Koushik Sen for PLDI08
15
Simple Randomized Algorithm Simple Scheduler At every state during a concurrent execution –Pick a thread randomly –Execute the next instruction of the thread Slide taken and adapted from the original slides of Koushik Sen for PLDI08
16
Simple Randomized Algorithm Simple Scheduler At every state during a concurrent execution –Pick a thread randomly –Execute the next instruction of the thread Slide taken and adapted from the original slides of Koushik Sen for PLDI08
17
Simple Randomized Algorithm Simple Scheduler At every state during a concurrent execution –Pick a thread randomly –Execute the next instruction of the thread Slide taken and adapted from the original slides of Koushik Sen for PLDI08
18
Problems With Randomized Algorithm Everything is left to chance – Randomized is not good enough for some code structures What are the chances that we randomly stumble upon the data race here? thread2 { x = x+1; } thread1 { for (i=0; i<1,000,000; ++i); x = x+1; } Data Race
19
Program Analysis Techniques Very effective in finding data races Static Analysis - No need to see an actual execution. Dynamic Analysis - Need to see real concurrent execution. BUT Often report many data races that are false warnings Require manual inspection to see if a race is real or not
20
False Positive Example thread2 { 3: if (y == 1) 4: if (x != 1) 5: do something; } thread1 { 1: x = 1; 2: y = 1; } Current Analysis Techniques will report a data race between lines 1 and 7. Initially x = y = 0 Data Race?
21
RaceFuzzer Algorithm – Welcome to the Future
22
First Stage – Find Potential Races Find Potential Candidates For Races Use an existing technique to find a set of pairs of state transitions that could potentially race. At the time of writing the paper an Hybrid Race Detection Algorithm was chosen. But any algorithm that can find races will do.
23
Second Stage – Verify Real Races Key Ideas: Randomized Scheduler Racing statements “wait for each other“ to increase chances to be detected. Remember this example? If only thread2 could wait for the end of the for loop… thread2 { x = x+1; } thread1 { for (i=0; i<1,000,000; ++i); x = x+1; } Data Race
24
RaceFuzzer By Example
25
Definitions Enabled(s) – not waiting for a lock held by another thread Alive(s) – have not terminated execution Execute(s, t) – returns state after executing next statement of t NextStmt(s, t) – next statement that t will execute
26
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Run ERASER: Statement pair (s5,s6) are in race Slide taken and adapted from the original slides of Koushik Sen for PLDI08
27
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Run ERASER: Statement pair (s5,s6) are in race Slide taken and adapted from the original slides of Koushik Sen for PLDI08
28
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); (s5,s6) in race Goal: Create a trace exhibiting the race Slide taken and adapted from the original slides of Koushik Sen for PLDI08
29
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); (s5,s6) in race Goal: Create a trace exhibiting the race Slide taken and adapted from the original slides of Koushik Sen for PLDI08 Execution: s1: g1(); s2: g2(); s3: g3(); s4: g4(); s6: if (o1.f==1) s5: o1.f = 1;
30
Input and Initialization 1: Inputs: the initial state s0, a set of two racing statements RaceSet 2: s := s0 3: postponed := ∅ 4: while Enabled(s) != ∅ do 5: t := a random thread in Enabled(s) \ postponed 6: if NextStmt(s, t) ∈ RaceSet then 7: R := Racing (s, t, postponed) 8: if R != ∅ then /* Actual race detected */ 9: print “ERROR: actual race found” 10: /* Randomly resolve race */ 11: if random boolean then 12: s := Execute(s, t) 13: else 14: postponed := postponed ∪ {t } 15: for all t‘ ∈ R do 16: s := Execute(s, t‘) 17: postponed := postponed \{t’} 18: end for 19: end if 20: else /* Wait for a race to happen */ 21: postponed := postponed ∪ {t} 22: end if 23: else 24: s := Execute(s, t) 25: end if 26: if postponed = Enabled(s) then 27: remove a random element from postponed 28: end if 29: end while 30: if Active(s) != ∅ then 31: print “ERROR: actual deadlock found” 32: end if
31
Input and Initialization Inputs: the initial state s0 a set of two racing statements RaceSet Initialization: 2: s := s0 3: postponed := ∅
32
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Execution: (s5,s6) in race Slide taken and adapted from the original slides of Koushik Sen for PLDI08 Postponed = { }
33
While.. Choose a Random Thread 1: Inputs: the initial state s0, a set of two racing statements RaceSet 2: s := s0 3: postponed := ∅ 4: while Enabled(s) != ∅ do 5: t := a random thread in Enabled(s) \ postponed 6: if NextStmt(s, t) ∈ RaceSet then 7: R := Racing (s, t, postponed) 8: if R != ∅ then /* Actual race detected */ 9: print “ERROR: actual race found” 10: /* Randomly resolve race */ 11: if random boolean then 12: s := Execute(s, t) 13: else 14: postponed := postponed ∪ {t } 15: for all t‘ ∈ R do 16: s := Execute(s, t‘) 17: postponed := postponed \{t’} 18: end for 19: end if 20: else /* Wait for a race to happen */ 21: postponed := postponed ∪ {t} 22: end if 23: else 24: s := Execute(s, t) 25: end if 26: if postponed = Enabled(s) then 27: remove a random element from postponed 28: end if 29: end while 30: if Active(s) != ∅ then 31: print “ERROR: actual deadlock found” 32: end if
34
While.. Choose a Random Thread 4: while Enabled(s) != ∅ do 5: t := a random thread in Enabled(s) \ postponed … 29: end while
35
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Execution: (s5,s6) in race Slide taken and adapted from the original slides of Koushik Sen for PLDI08 Postponed = { }
36
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Execution: (s5,s6) in race Slide taken and adapted from the original slides of Koushik Sen for PLDI08 Postponed = { }
37
Next Statement in a race? 1: Inputs: the initial state s0, a set of two racing statements RaceSet 2: s := s0 3: postponed := ∅ 4: while Enabled(s) != ∅ do 5: t := a random thread in Enabled(s) \ postponed 6: if NextStmt(s, t) ∈ RaceSet then 7: R := Racing (s, t, postponed) 8: if R != ∅ then /* Actual race detected */ 9: print “ERROR: actual race found” 10: /* Randomly resolve race */ 11: if random boolean then 12: s := Execute(s, t) 13: else 14: postponed := postponed ∪ {t } 15: for all t‘ ∈ R do 16: s := Execute(s, t‘) 17: postponed := postponed \{t’} 18: end for 19: end if 20: else /* Wait for a race to happen */ 21: postponed := postponed ∪ {t} 22: end if 23: else 24: s := Execute(s, t) 25: end if 26: if postponed = Enabled(s) then 27: remove a random element from postponed 28: end if 29: end while 30: if Active(s) != ∅ then 31: print “ERROR: actual deadlock found” 32: end if
38
Next Statement in a race? 6: if NextStmt(s, t) ∈ RaceSet then … 23: else 24: s := Execute(s, t) 25: end if
39
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Execution: (s5,s6) in race Slide taken and adapted from the original slides of Koushik Sen for PLDI08 Postponed = { }
40
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); (s5,s6) in race Execution: s1: g1(); Slide taken and adapted from the original slides of Koushik Sen for PLDI08 Postponed = { }
41
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Execution: s1: g1(); (s5,s6) in race Slide taken and adapted from the original slides of Koushik Sen for PLDI08 Postponed = { }
42
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Execution: s1: g1(); (s5,s6) in race Slide taken and adapted from the original slides of Koushik Sen for PLDI08 Postponed = { }
43
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Execution: s1: g1(); (s5,s6) in race Slide taken and adapted from the original slides of Koushik Sen for PLDI08 Postponed = { }
44
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); (s5,s6) in race Execution: s1: g1(); s6: if (o1.f==1) Slide taken and adapted from the original slides of Koushik Sen for PLDI08 Postponed = { }
45
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); (s5,s6) in race Execution: s1: g1(); s6: if (o1.f==1) Slide taken and adapted from the original slides of Koushik Sen for PLDI08 Postponed = { }
46
Actual Data Race? 1: Inputs: the initial state s0, a set of two racing statements RaceSet 2: s := s0 3: postponed := ∅ 4: while Enabled(s) != ∅ do 5: t := a random thread in Enabled(s) \ postponed 6: if NextStmt(s, t) ∈ RaceSet then 7: R := Racing (s, t, postponed) 8: if R != ∅ then /* Actual race detected */ 9: print “ERROR: actual race found” 10: /* Randomly resolve race */ 11: if random boolean then 12: s := Execute(s, t) 13: else 14: postponed := postponed ∪ {t } 15: for all t‘ ∈ R do 16: s := Execute(s, t‘) 17: postponed := postponed \{t’} 18: end for 19: end if 20: else /* Wait for a race to happen */ 21: postponed := postponed ∪ {t} 22: end if 23: else 24: s := Execute(s, t) 25: end if 26: if postponed = Enabled(s) then 27: remove a random element from postponed 28: end if 29: end while 30: if Active(s) != ∅ then 31: print “ERROR: actual deadlock found” 32: end if
47
Actual Data Race? 7: R := Racing (s, t, postponed) 8: if R != ∅ then /* Actual race*/ … 20: else /* Wait for a race*/ 21: postponed := postponed ∪ {t} 22: end if
48
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Execution: s1: g1(); s6: if (o1.f==1) (s5,s6) in race Postponed = { } Slide taken and adapted from the original slides of Koushik Sen for PLDI08
49
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); (s5,s6) in race Execution: s1: g1(); s6: if (o1.f==1) Postponed = { s6: if (o1.f==1) } Slide taken and adapted from the original slides of Koushik Sen for PLDI08
50
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Execution: s1: g1(); (s5,s6) in race Postponed = { s6: if (o1.f==1) } Slide taken and adapted from the original slides of Koushik Sen for PLDI08
51
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Execution: s1: g1(); s2: g2(); (s5,s6) in race Postponed = { s6: if (o1.f==1) } Slide taken and adapted from the original slides of Koushik Sen for PLDI08
52
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Execution: s1: g1(); s2: g2(); (s5,s6) in race Postponed = { s6: if (o1.f==1) } Slide taken and adapted from the original slides of Koushik Sen for PLDI08
53
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Execution: s1: g1(); s2: g2(); (s5,s6) in race Postponed = { s6: if (o1.f==1) } Slide taken and adapted from the original slides of Koushik Sen for PLDI08
54
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); (s5,s6) in race Postponed = { s6: if (o1.f==1) } Execution: s1: g1(); s2: g2(); s3: g3(); Slide taken and adapted from the original slides of Koushik Sen for PLDI08
55
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); (s5,s6) in race Postponed = { s6: if (o1.f==1) } Execution: s1: g1(); s2: g2(); s3: g3(); Slide taken and adapted from the original slides of Koushik Sen for PLDI08
56
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); (s5,s6) in race Postponed = { s6: if (o1.f==1) } Execution: s1: g1(); s2: g2(); s3: g3(); s4: g4(); Slide taken and adapted from the original slides of Koushik Sen for PLDI08
57
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); (s5,s6) in race Postponed = { s6: if (o1.f==1) } Execution: s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: o2.f = 1; Slide taken and adapted from the original slides of Koushik Sen for PLDI08
58
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); (s5,s6) in race Execution: s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: o2.f = 1; Slide taken and adapted from the original slides of Koushik Sen for PLDI08 Postponed = { s6: if (o1.f==1) }
59
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); (s5,s6) in race Race? Execution: s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: o2.f = 1; Slide taken and adapted from the original slides of Koushik Sen for PLDI08 Postponed = { s6: if (o1.f==1) }
60
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); (s5,s6) in race Postponed = { s6: if (o1.f==1) } Race? NO o1.f ≠ o2.f Execution: s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: o2.f = 1; Slide taken and adapted from the original slides of Koushik Sen for PLDI08
61
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); (s5,s6) in race Execution: s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: o2.f = 1; Slide taken and adapted from the original slides of Koushik Sen for PLDI08 Postponed = { s6: if (o1.f==1), s5: o2.f = 1; }
62
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); (s5,s6) in race Postponed = { s6: if (o1.f==1), s5: o2.f = 1; } Execution: s1: g1(); s2: g2(); s3: g3(); s4: g4(); Slide taken and adapted from the original slides of Koushik Sen for PLDI08
63
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); (s5,s6) in race Postponed = { s6: if (o1.f==1), s5: o2.f = 1; } Execution: s1: g1(); s2: g2(); s3: g3(); s4: g4(); Slide taken and adapted from the original slides of Koushik Sen for PLDI08
64
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Execution: s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: o1.f = 1; (s5,s6) in race Postponed = { s6: if (o1.f==1), s5: o2.f = 1; } Slide taken and adapted from the original slides of Koushik Sen for PLDI08
65
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Execution: s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: o1.f = 1; (s5,s6) in race Postponed = { s6: if (o1.f==1), s5: o2.f = 1; } Slide taken and adapted from the original slides of Koushik Sen for PLDI08
66
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); (s5,s6) in race Postponed = { s6: if (o1.f==1), s5: o2.f = 1; } Race? YES o1.f = o1.f Execution: s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: o1.f = 1; Slide taken and adapted from the original slides of Koushik Sen for PLDI08
67
Actual Data Race! 1: Inputs: the initial state s0, a set of two racing statements RaceSet 2: s := s0 3: postponed := ∅ 4: while Enabled(s) != ∅ do 5: t := a random thread in Enabled(s) \ postponed 6: if NextStmt(s, t) ∈ RaceSet then 7: R := Racing (s, t, postponed) 8: if R != ∅ then /* Actual race detected */ 9: print “ERROR: actual race found” 10: /* Randomly resolve race */ 11: if random boolean then 12: s := Execute(s, t) 13: else 14: postponed := postponed ∪ {t } 15: for all t‘ ∈ R do 16: s := Execute(s, t‘) 17: postponed := postponed \{t’} 18: end for 19: end if 20: else /* Wait for a race to happen */ 21: postponed := postponed ∪ {t} 22: end if 23: else 24: s := Execute(s, t) 25: end if 26: if postponed = Enabled(s) then 27: remove a random element from postponed 28: end if 29: end while 30: if Active(s) != ∅ then 31: print “ERROR: actual deadlock found” 32: end if
68
Actual Data Race! 9: print “ERROR: actual race found” 10: /* Randomly resolve race */ 11: if random boolean then 12: s := Execute(s, t) 13: else 14: postponed := postponed ∪ {t } 15: for all t‘ ∈ R do 16: s := Execute(s, t‘) 17: postponed := postponed \{t’} 18: end for 19: end if
69
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); (s5,s6) in race Postponed = { s6: if (o1.f==1), s5: o2.f = 1; } Race? YES o1.f = o1.f Execution: s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: o1.f = 1; Slide taken and adapted from the original slides of Koushik Sen for PLDI08
70
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Execution: s1: g1(); s2: g2(); s3: g3(); s4: g4(); (s5,s6) in race Postponed = { s5: o2.f = 1; } s6: if (o1.f==1) s5: o1.f = 1; Slide taken and adapted from the original slides of Koushik Sen for PLDI08
71
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Execution: s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: o1.f = 1; (s5,s6) in race Slide taken and adapted from the original slides of Koushik Sen for PLDI08 Postponed = { s6: if (o1.f==1), s5: o2.f = 1; }
72
Everybody Is Postponed? 1: Inputs: the initial state s0, a set of two racing statements RaceSet 2: s := s0 3: postponed := ∅ 4: while Enabled(s) != ∅ do 5: t := a random thread in Enabled(s) \ postponed 6: if NextStmt(s, t) ∈ RaceSet then 7: R := Racing (s, t, postponed) 8: if R != ∅ then /* Actual race detected */ 9: print “ERROR: actual race found” 10: /* Randomly resolve race */ 11: if random boolean then 12: s := Execute(s, t) 13: else 14: postponed := postponed ∪ {t } 15: for all t‘ ∈ R do 16: s := Execute(s, t‘) 17: postponed := postponed \{t’} 18: end for 19: end if 20: else /* Wait for a race to happen */ 21: postponed := postponed ∪ {t} 22: end if 23: else 24: s := Execute(s, t) 25: end if 26: if postponed = Enabled(s) then 27: remove a random element from postponed 28: end if 29: end while 30: if Active(s) != ∅ then 31: print “ERROR: actual deadlock found” 32: end if
73
Everybody Is Postponed? 26: if postponed = Enabled(s) then 27: remove a random element from postponed 28: end if
74
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Execution: s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: o1.f = 1; (s5,s6) in race Slide taken and adapted from the original slides of Koushik Sen for PLDI08 Postponed = { s6: if (o1.f==1), s5: o2.f = 1; }
75
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Execution: s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: o1.f = 1; s6: if (o1.f==1) (s5,s6) in race Postponed = { s5: o2.f = 1; } Slide taken and adapted from the original slides of Koushik Sen for PLDI08
76
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Execution: s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: o1.f = 1; s6: if (o1.f==1) s7: ERROR; (s5,s6) in race Postponed = { s5: o2.f = 1; } Slide taken and adapted from the original slides of Koushik Sen for PLDI08
77
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Execution: s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: o1.f = 1; s6: if (o1.f==1) s7: ERROR; s5: o2.f = 1; (s5,s6) in race Postponed = { } Slide taken and adapted from the original slides of Koushik Sen for PLDI08
78
Deadlock? 1: Inputs: the initial state s0, a set of two racing statements RaceSet 2: s := s0 3: postponed := ∅ 4: while Enabled(s) != ∅ do 5: t := a random thread in Enabled(s) \ postponed 6: if NextStmt(s, t) ∈ RaceSet then 7: R := Racing (s, t, postponed) 8: if R != ∅ then /* Actual race detected */ 9: print “ERROR: actual race found” 10: /* Randomly resolve race */ 11: if random boolean then 12: s := Execute(s, t) 13: else 14: postponed := postponed ∪ {t } 15: for all t‘ ∈ R do 16: s := Execute(s, t‘) 17: postponed := postponed \{t’} 18: end for 19: end if 20: else /* Wait for a race to happen */ 21: postponed := postponed ∪ {t} 22: end if 23: else 24: s := Execute(s, t) 25: end if 26: if postponed = Enabled(s) then 27: remove a random element from postponed 28: end if 29: end while 30: if Active(s) != ∅ then 31: print “ERROR: actual deadlock found” 32: end if
79
Deadlock? 30: if Active(s) != ∅ then 31: print “ERROR: actual deadlock found” 32: end if
80
RACEFUZZER using an example Thread1 foo(o1); foo(C x) { s1: g1() s2: g2(); s3: g3(); s4: g4(); s5: x.f = 1; } Thread2 bar(o1); bar(C y) { s6: if (y.f==1) s7: ERROR; } Thread3 foo(o2); Execution: s1: g1(); s2: g2(); s3: g3(); s4: g4(); s5: o1.f = 1; s6: if (o1.f==1) s7: ERROR; s5: o2.f = 1; (s5,s6) in race Postponed = { } Slide taken and adapted from the original slides of Koushik Sen for PLDI08
81
Deterministic Replay There are 3 points of non-determinism in the algorithm: Both are because of calls to a random function. If we save the random function seed before we start running RaceFuzzer, we can later replay the same run over and over using the same seed. 5: t := a random thread in Enabled(s) \ postponed 11: if random boolean then 27: remove a random element from postponed
82
Evaluation
83
RaceFuzzer Limitations Cannot detect all real races in a concurrent program. Depends on the dynamic analysis done in the first stage. Being random in nature, RaceFuzzer may not be able to separate all real races from potential races. However, this did not happen in our experiments with existing benchmarks.
84
Conclusion RaceFuzzer Classifies real Data Races Enables reproduction of races found No false positives! Very efficient Finds some exceptions and Deadlocks as a bonus. 84
85
QUESTIONS? 85
86
False Positive? Thread1 foo(x,y); foo(int x, int y) { s1: x = 1; s2: lock(L); s3: y = 1; s4: unlock(L); } Thread2 bar(x,y); bar(int x, int y) { s6: lock(L); s7: if (y == 1) { s8: if (x != 1) { s9: do something; }} s10: unlock(L); } Slide taken and adapted from the original slides of Koushik Sen for PLDI08 (s1,s8) in race Postponed = { s1: x = 1; } Execution: s6: lock(L); s7: if (y == 1) { s8: if (x != 1) { s9: do something; }} s10: unlock(L); s1: x = 1; s2: lock(L); s3: y = 1; s4: unlock(L); Postponed = {}
87
Hard To Find Data Races? Thread1 foo(x,y); foo(int x) { s1: for (i=0; i<1,000,000; ++i); s2: x = x+1; } Thread2 bar(x,y); bar(int x) { s3: x = x+1; } (s2,s3) in race Postponed = { s3: x = x+1; } Execution: s1: for (i=0; i<1,000,000; ++i); s2: x = x+1;s3: x = x+1; Data Race
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.