Race Directed Random Testing of Concurrent Programs KOUSHIK SEN - UNIVERSITY OF CALIFORNIA, BERKELEY PRESENTED BY – ARTHUR KIYANOVSKI – TECHNION, ISRAEL.

Slides:



Advertisements
Similar presentations
Dataflow Analysis for Datarace-Free Programs (ESOP 11) Arnab De Joint work with Deepak DSouza and Rupesh Nasre Indian Institute of Science, Bangalore.
Advertisements

On-the-fly Healing of Race Conditions in ARINC-653 Flight Software
Applications of Synchronization Coverage A.Bron,E.Farchi, Y.Magid,Y.Nir,S.Ur Tehila Mayzels 1.
4.4 Page replacement algorithms
Threads Cannot be Implemented As a Library Andrew Hobbs.
A Randomized Dynamic Program Analysis for Detecting Real Deadlocks Pallavi Joshi  Chang-Seo Park  Koushik Sen  Mayur Naik ‡  Par Lab, EECS, UC Berkeley‡
CS 162 Memory Consistency Models. Memory operations are reordered to improve performance Hardware (e.g., store buffer, reorder buffer) Compiler (e.g.,
A Randomized Dynamic Program Analysis for Detecting Real Deadlocks Koushik Sen CS 265.
(C) 2001 Daniel Sorin Correctly Implementing Value Prediction in Microprocessors that Support Multithreading or Multiprocessing Milo M.K. Martin, Daniel.
Silberschatz, Galvin and Gagne ©2007 Operating System Concepts with Java – 7 th Edition, Nov 15, 2006 Chapter 6 (a): Synchronization.
Chapter 6: Process Synchronization
Process Synchronization. Module 6: Process Synchronization Background The Critical-Section Problem Peterson’s Solution Synchronization Hardware Semaphores.
Background for “KISS: Keep It Simple and Sequential” cs264 Ras Bodik spring 2005.
Iterative Context Bounding for Systematic Testing of Multithreaded Programs Madan Musuvathi Shaz Qadeer Microsoft Research.
Concurrency: Threads, Address Spaces, and Processes Sarah Diesburg Operating Systems COP 4610.
Why Concurrency? Allows multiple applications to run at the same time  Analogy: juggling.
Atomicity in Multi-Threaded Programs Prachi Tiwari University of California, Santa Cruz CMPS 203 Programming Languages, Fall 2004.
Concurrency.
Progress Guarantee for Parallel Programs via Bounded Lock-Freedom Erez Petrank – Technion Madanlal Musuvathi- Microsoft Bjarne Steensgaard - Microsoft.
Chapter 2.3 : Interprocess Communication
/ PSWLAB Eraser: A Dynamic Data Race Detector for Multithreaded Programs By Stefan Savage et al 5 th Mar 2008 presented by Hong,Shin Eraser:
LO: We’re learning to understand how computers solve problems!
1 Advanced Computer Programming Concurrency Multithreaded Programs Copyright © Texas Education Agency, 2013.
Operating System Review September 10, 2012Introduction to Computer Security ©2004 Matt Bishop Slide #1-1.
Object Oriented Analysis & Design SDL Threads. Contents 2  Processes  Thread Concepts  Creating threads  Critical sections  Synchronizing threads.
Accelerating Precise Race Detection Using Commercially-Available Hardware Transactional Memory Support Serdar Tasiran Koc University, Istanbul, Turkey.
Scalable Statistical Bug Isolation Authors: B. Liblit, M. Naik, A.X. Zheng, A. Aiken, M. I. Jordan Presented by S. Li.
50.530: Software Engineering Sun Jun SUTD. Week 8: Race Detection.
Games Development 2 Concurrent Programming CO3301 Week 9.
Operating Systems CSE 411 Multi-processor Operating Systems Multi-processor Operating Systems Dec Lecture 30 Instructor: Bhuvan Urgaonkar.
Threaded Programming in Python Adapted from Fundamentals of Python: From First Programs Through Data Structures CPE 401 / 601 Computer Network Systems.
Laboratory - 4.  Threading Concept  Threading in.NET  Multi-Threaded Socket  Example.
Game Maker – Getting Started What is Game Maker?.
1 How will execution time grow with SIZE? int array[SIZE]; int sum = 0; for (int i = 0 ; i < ; ++ i) { for (int j = 0 ; j < SIZE ; ++ j) { sum +=
Memory Consistency Models. Outline Review of multi-threaded program execution on uniprocessor Need for memory consistency models Sequential consistency.
Professor: Shu-Ching Chen TA: Samira Pouyanfar.  An independent stream of instructions that can be scheduled to run  A path of execution int a, b; int.
CS399 New Beginnings Jonathan Walpole. 2 Concurrent Programming & Synchronization Primitives.
Copyright © Curt Hill Concurrent Execution An Overview for Database.
© Janice Regan, CMPT 300, May CMPT 300 Introduction to Operating Systems Operating Systems Processes and Threads.
Probability of Simple Events
HARD: Hardware-Assisted lockset- based Race Detection P.Zhou, R.Teodorescu, Y.Zhou. HPCA’07 Shimin Chen LBA Reading Group Presentation.
Eraser: A dynamic Data Race Detector for Multithreaded Programs Stefan Savage, Michael Burrows, Greg Nelson, Patrick Sobalvarro, Thomas Anderson Presenter:
Soyeon Park, Shan Lu, Yuanyuan Zhou UIUC Reading Group by Theo.
SMP Basics KeyStone Training Multicore Applications Literature Number: SPRPxxx 1.
Flow Control in Imperative Languages. Activity 1 What does the word: ‘Imperative’ mean? 5mins …having CONTROL and ORDER!
MA/CSSE 473 Day 10 Primality Testing. MA/CSSE 473 Day 10 In-class exam: Friday, Sept 28 –You may bring a two-sided 8.5x11 inch piece of paper containing.
Testing Concurrent Programs Sri Teja Basava Arpit Sud CSCI 5535: Fundamentals of Programming Languages University of Colorado at Boulder Spring 2010.
Synchronization Questions answered in this lecture: Why is synchronization necessary? What are race conditions, critical sections, and atomic operations?
Multi-Core CPUs Matt Kuehn. Roadmap ► Intel vs AMD ► Early multi-core processors ► Threads vs Physical Cores ► Multithreading and Multi-core processing.
1 Active Random Testing of Parallel Programs Koushik Sen University of California, Berkeley.
Detecting Data Races in Multi-Threaded Programs
Tutorial 2: Homework 1 and Project 1
Healing Data Races On-The-Fly
Threaded Programming in Python
Threads Cannot Be Implemented As a Library
Effective Data-Race Detection for the Kernel
143a discussion session week 3
Threads and Memory Models Hal Perkins Autumn 2011
Threads and Memory Models Hal Perkins Autumn 2009
Coordination Lecture 5.
cs205: engineering software
- When you approach operating system concepts there might be several confusing terms that may look similar but in fact refer to different concepts:  multiprogramming, multiprocessing, multitasking,
NETWORK PROGRAMMING CNET 441
CS333 Intro to Operating Systems
Relaxed Consistency Finale
50.530: Software Engineering
Eraser: A dynamic data race detector for multithreaded programs
Ch 3.
Learning Objective: to be able to design programs that use iteration.
Presentation transcript:

Race Directed Random Testing of Concurrent Programs KOUSHIK SEN - UNIVERSITY OF CALIFORNIA, BERKELEY PRESENTED BY – ARTHUR KIYANOVSKI – TECHNION, ISRAEL

Goal Verify Data Races  Automatically  Efficiently  No false alarms  Being able to reproduce races

Background

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

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

Not a Data Race! Thread 2: Lock(L); X=X+1; Unlock(L); Thread 1: Lock(L); X=X+1; Unlock(L);

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 Data Race

Once upon a time… Testing concurrent programs

The Simple Traditional Way Repeatedly execute the program with the hope that different test executions will result in different interleavings.

Advantages Of The Traditional Way  Inexpensive compared to sophisticated techniques such as model checking and verification

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.

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

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

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

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

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

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

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

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

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?

RaceFuzzer Algorithm – Welcome to the Future

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.

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

RaceFuzzer By Example

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

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

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

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

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;

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

Input and Initialization Inputs:  the initial state s0  a set of two racing statements RaceSet Initialization: 2: s := s0 3: postponed := ∅

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 = { }

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

While.. Choose a Random Thread 4: while Enabled(s) != ∅ do 5: t := a random thread in Enabled(s) \ postponed … 29: end while

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 = { }

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 = { }

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

Next Statement in a race? 6: if NextStmt(s, t) ∈ RaceSet then … 23: else 24: s := Execute(s, t) 25: end if

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 = { }

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 = { }

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 = { }

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 = { }

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 = { }

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 = { }

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 = { }

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

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

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

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

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

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

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

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

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

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

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

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

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) }

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) }

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

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; }

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

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

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

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

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

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

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

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

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

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; }

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

Everybody Is Postponed? 26: if postponed = Enabled(s) then 27: remove a random element from postponed 28: end if

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; }

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

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

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

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

Deadlock? 30: if Active(s) != ∅ then 31: print “ERROR: actual deadlock found” 32: end if

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

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

Evaluation

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.

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

QUESTIONS? 85

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 = {}

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