Detecting Data Races in Multi-Threaded Programs Eraser A Dynamic - - PowerPoint PPT Presentation

detecting data races in multi threaded programs
SMART_READER_LITE
LIVE PREVIEW

Detecting Data Races in Multi-Threaded Programs Eraser A Dynamic - - PowerPoint PPT Presentation

Detecting Data Races in Multi-Threaded Programs Eraser A Dynamic Data-Race Detector for Multi-Threaded Programs MultiRace An Efficient On-the-Fly Data-Race Detection Tool for Multi-Threaded C++ Programs John C. Linford Slide 1 / 31 Key


slide-1
SLIDE 1

Eraser

A Dynamic Data-Race Detector for Multi-Threaded Programs

MultiRace

An Efficient On-the-Fly Data-Race Detection Tool for Multi-Threaded C++ Programs John C. Linford

Detecting Data Races in Multi-Threaded Programs

Slide 1 / 31

slide-2
SLIDE 2

Key Points

  • 1. Data races are easy to cause and

hard to debug.

  • 2. We can't detect all data races.
  • 3. Detection of feasible races relies on

detection of apparent data races.

  • 4. Data race detection tools are either static or

dynamic (on-the-fly and postmortem).

Slide 2 / 31

slide-3
SLIDE 3

Key Points Cont.

  • 5. Data races can be prevented by following a

locking discipline.

  • 6. Commonly used detection algorithms are

Lockset and DJIT (Happens-Before).

  • 7. Lockset maintains a set of candidate locks

for each shared memory location. If a shared location is accessed when this set is empty, there has been a violation of the locking discipline.

Slide 3 / 31

slide-4
SLIDE 4

Key Points Cont.

8. Lockset is vulnerable to false alarms. 9. DJIT uses a logging mechanism. Every shared memory access is logged to see that it “happens before” prior accesses to the same location.

  • 10. DJIT is dependent on the scheduler and

thread interleaving.

  • 11. Combining happens-before with Lockset

can improve detection accuracy.

Slide 4 / 31

slide-5
SLIDE 5

Data Race Review

  • At least one access is a write,
  • Simultaneous access is not prevented.
  • Example (variable X is global and shared)

Thread 1 Thread 2 X = 2.7 X = 3.1 Z = 2 T = X Two threads access a shared variable

Execution

Slide 5 / 31

slide-6
SLIDE 6

Data Race Demonstration

  • Data races often lead to

unexpected and even nondeterministic behavior

  • The outcome may be

dependent on specific execution order (threads' interleaving)

  • Click image to start

Slide 6 / 31

slide-7
SLIDE 7

Data Race Demonstration Cont.

t1 = new Thread() { public void run() { while(t1 != null) { ... shared[0] = shared[0] + 1; ... } ... t2 = new Thread() { public void run() { while(t2 != null) { ... shared[0] = shared[0] + 1; ... } ... int[] shared = new int[1]; Thread t1, t2; public DataRace() { // Initialize and start threads (shown below) }

Slide 7 / 31

slide-8
SLIDE 8

We Can't Detect All Data Races

  • For t threads of n instructions each, the

number of possible orders is about tn*t.

  • All possible inputs would have to be tested.
  • Adding detection code or debugging

information can change the execution schedule.

[Pozniansky & Schuster, 2003]

Slide 8 / 31

slide-9
SLIDE 9

Feasible Data Races

  • Races based on possible behavior of the

program.

  • Actual data races which could manifest in

any execution.

  • Locating feasible races requires a full

analysis of the program's semantics.

  • Exactly locating feasible races is NP-hard

[Pozniansky & Schuster, 2003].

Slide 9 / 31

slide-10
SLIDE 10

Apparent Data Races

  • Approximations of feasible data races based
  • n synchronization behavior in an execution.
  • Easier to detect, but less accurate.
  • Apparent races exist if and only if at least
  • ne feasible race exists.
  • Locating all apparent races is NP-hard

[Pozniansky & Schuster, 2003].

Slide 10 / 31

slide-11
SLIDE 11

Eraser [Savage, Burrows, et al., 1997]

  • On-the-fly tool.
  • Lockset algorithm.
  • Code annotations to flag

special cases.

  • Can be extended to

handle other locking mechanisms (IRQs).

  • Used in industry.
  • Slows applications by a

factor of 10 – 30.

Slide 11 / 31

slide-12
SLIDE 12

The Lockset Algorithm (Simple Form)

Let locks_held(t) be the set of locks held by thread t For each shared memory location v, initialize C(v) to the set of all locks On each access to v by thread t, Set C(v) := C(v) ∩ locks_held(t) If C(v) := {}, then issue a warning

  • Detects races not manifested in one execution.
  • Generates false alarms.

Lockset Refinement

Slide 12 / 31

slide-13
SLIDE 13

Lockset Refinement Example

Program locks_held C(v)

int v; v := 1024; lock(mu1); v := v + 1; unlock(mu1); lock(mu2); v := v + 1; unlock(mu2); {} {mu1} {} {mu2} {} {mu1, mu2} {mu1} {}

Warning!

Slide 13 / 31

slide-14
SLIDE 14

Simple Lockset is too Strict

  • Variables initialized without locks held.
  • Read-shared data read without locks held.
  • Read-write locking mechanisms

(producer / consumer). Lockset will produce false-positives for:

Slide 14 / 31

slide-15
SLIDE 15

Lockset State Diagram

Virgin Exclusive Shared Shared-Modified

wr rd, 2nd thread wr wr, 2nd thread rd / wr, 1st thread rd

Warnings are issued only in the Shared-Modified state

Slide 15 / 31

slide-16
SLIDE 16

Lockset State Example

Program locks_held C(v) State(v)

int v; v := 1024; lock(mu1); v := v + 1; unlock(mu1); lock(mu2); v := v + 1; unlock(mu2); {} {mu1} {} {mu2} {} {mu1, mu2} {mu1} {} Virgin Exclusive Shared Shared-Modified

T1 T2 T1 Race detected correctly

Slide 16 / 31

slide-17
SLIDE 17

The Lockset Algorithm (Extended)

Let locks_held(t) be the set of locks held in any mode by thread t Let write_locks_held(t) be the set of locks held in write mode by thread t For each shared memory location v, initialize C(v) to the set of all locks On each read of v by thread t, Set C(v) := C(v) ∩ locks_held(t) If C(v) = {}, then issue a warning On each write of v by thread t, Set C(v) := C(v) ∩ write_locks_held(t) If C(v) = {}, then issue a warning

Slide 17 / 31

slide-18
SLIDE 18

Unhandled Cases in Eraser

  • Memory reuse
  • Unrecognized thread API
  • Initialization in different thread
  • Benign races

if(fptr == NULL) { lock(fptr_mu); if(fptr == NULL) { fptr = open(filename); } unlock(fptr_mu); }

Slide 18 / 31

slide-19
SLIDE 19

Unhandled Cases in Eraser Cont.

  • Race on and will be missed if executes first

int[] shared = new int[1]; Thread t = new Thread() { public void run() { shared = shared + 1; ... }; ... shared = 512; t.start(); shared = shared + 256; ...

[Seragiotto, 2005]

Slide 19 / 31

slide-20
SLIDE 20

Unhandled Cases in Eraser Cont.

Program State(shared)

Data race is not detected!

int[] shared = new int[1]; shared = 512; t.start(); shared = shared + 256; Thread t = new Thread() { public void run() { shared = shared + 1; ... }; ... Virgin Exclusive Shared Shared-Modified

locks_held C(v)

{} {mu1} {}

Slide 20 / 31

slide-21
SLIDE 21

Unhandled Cases in Eraser Cont.

Data race is detected!

Program State(shared)

int[] shared = new int[1]; shared = 512; t.start(); Thread t = new Thread() { public void run() { shared = shared + 1; ... }; shared = shared + 256; Virgin Exclusive Shared Shared-Modified

locks_held C(v)

{} {mu1} {}

Slide 21 / 31

slide-22
SLIDE 22

Improved Lockset State Diagram [Seragiotto, 2005]

Initialized (Exclusive) Initialized and Read Shared Shared-Modified Initialized and Written Virgin

rd, 2nd thread rd, not 2nd thread wr, any rd / wr, not 2nd thread wr, 2nd thread wr, 2nd thread wr, not 2nd thread first access rd / wr, 1st thread rd, 2nd thread rd, any rd / wr, 2nd thread

Slide 22 / 31

slide-23
SLIDE 23

Implementations: Eraser

  • Maintains hash table of sets of locks.
  • Represents each set of locks with an index.
  • Every shared memory location has shadow

memory containing lockset index and state.

  • Shadow memory is located by adding offset

to shared memory location address.

Slide 23 / 31

slide-24
SLIDE 24

Implementations: Eraser

v Program Memory Shadow Memory &v + Shadow Offset Lockset Index Table mu1 mu2 Lock Vector

Shared memory location v is associated with locks mu1 and mu2 [Savage, Burrows, et al., 2005]

Slide 24 / 31

slide-25
SLIDE 25

Implementations: Ladybug [Seragiotto, 2005]

  • GC Eraser:

– Maintains lock list for threads and variables. – Uses weak references (less memory usage).

  • Fast Eraser:

– Maintains lock list for threads and variables. – Uses strong references (faster).

  • Vanilla Eraser:

– Same as eraser, but keeps hash table of lock

sets already created.

Slide 25 / 31

slide-26
SLIDE 26

Ladybug Demonstration

  • Rewrite class file

– java -cp Ladybug.jar

br.ime.usp.ladybug.LadybugClassRewriter DataRace.class

  • Run modified class

– java -cp Ladybug.jar:. DataRace

  • Races reported as exceptions

br.ime.usp.ladybug.RCException: [line 9] Race condition detected: t2 of DataRace (hash code = 1b67f74) with Thread-0 at br.ime.usp.ladybug.StaticLadybug.warn(StaticLadybug.java:1014) at br.ime.usp.ladybug.eraser.EraserGC.writeField(EraserGC.java:47) ... at DataRace.access$202(DataRace.java:9) at DataRace$1.run(DataRace.java:37)

  • Can also use GUI

Slide 26 / 31

slide-27
SLIDE 27

MultiRace [Pozniansky & Schuster, 2003]

  • On-the-fly tool.
  • Improved Lockset

and DJIT+.

  • Significantly fewer

false alarms than Eraser.

  • Minimal impact on

program speed.

Slide 27 / 31

slide-28
SLIDE 28

DJIT

  • Based on Lamport's Happens-Before

relationship.

  • Detects the first apparent data race when it

actually occurs.

  • Can be extended to detect races after the

first (DJIT+).

  • Dependent on scheduling order.

Slide 28 / 31

slide-29
SLIDE 29

Benefits of Combining Lockset and DJIT

  • Races are in the intersection of warnings.
  • Lockset's insensitivity compensates for

DJIT's sensitivity to thread interleaving.

  • Lockset reduces DJIT execution overhead.
  • Lockset warnings are “ranked” by DJIT.
  • Implementation overhead is minimized.

Slide 29 / 31

slide-30
SLIDE 30

Conclusion

  • 1. Data races are easy to cause and

hard to debug.

  • 2. Data race detection tools are either static or

dynamic (on-the-fly and postmortem).

  • 3. Commonly used detection algorithms are

Lockset and DJIT (Happens-Before).

  • 4. Lockset is vulnerable to false alarms.
  • 5. DJIT is dependent on the scheduler and

thread interleaving.

  • 6. Combining happens-before with Lockset

can improve detection accuracy.

Slide 30 / 31

slide-31
SLIDE 31

References

  • S. Savage, M. Burrows, G. Nelson, P. Sobalvarro, and T.E.
  • Anderson. Eraser: A Dynamic Data Race Detector for

Multithreaded Programs. In ACM Transactions on Computer Systems, 15(4): pp. 391-411, 1997.

  • E. Pozniansky and A. Schuster. Dynamic Data-Race

Detection in Lock-Based Multi-Threaded Programs. In Principles and Practice of Parallel Programming, pp. 170- 190, 2003.

  • E. Pozniansky and A. Schuster. MultiRace: Efficient Data

Race Detection Tool for Multithreaded C++ Programs. 2005. http://dsl.cs.technion.ac.il/projects/multirace/MultiRace.htm.

  • C. Seragiotto. Ladybug: Race Condition Detection in Java.
  • 2005. http://www.par.univie.ac.at/~clovis/ladybug/

Slide 31 / 31