










Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
Eraser is a dynamic data race detector for multithreaded programs that uses lockset algorithms to detect potential data races. It assumes lock-based synchronization and checks that all shared-memory accesses follow a consistent locking discipline. The lockset algorithm, its application, and three problematic practices related to data races. Eraser is implemented by automatically instrumenting the program binary with calls to the eraser runtime.
Typology: Papers
1 / 18
This page cannot be seen from the preview
Don't miss anything!











Presented by Scott Fleming
A Paper Presentation for CSE 891 - Formal Methods in Software Development: Reliable Computing With Threads Fall Semester, 2008
Function: Dynamically detects the occurrence of data races in multithreaded programs
Data race: Occurs when ๎ (^) two or more threads concurrently access the same memory location, ๎ (^) at least one of the threads is writing, and ๎ (^) no explicit mechanism is used to prevent the accesses from being simultaneous
Dynamic detection: Detects as program executes ๎ (^) Occurrence of data race depends on what code is executed ๎ (^) Therefore, may depend on thread schedule ๎ (^) May miss potential data races
Producer Consumer
<
q : Queue
empty() : Boolean full() : Boolean push(item : T) pull() : T
q.enqueue(item); for (;;) { if (!buf->full()) buf->push(produce()); }
Assumes: Lock-based synchronization
Approach: Checks that all shared-memory accesses follow a consistent locking discipline
Lock: Primitive synchronization object used for mutual exclusion (also called a mutex ) ๎ (^) States: available or owned (by a thread) ๎ (^) Operations: (atomic) lock and unlock
Locking discipline: Protocol of lock acquisition and release to prevent data races
t1 t2 locks_held(t1) locks_held(t2) C(v) { } { } { l1, l2 } lock(l1) { l1 } ++v { l1 } unlock(l1) { } lock(l2) { l2 } ++v { } unlock(l2) { }
Initialization: Shared variables initialized without locking
Read-shared data: Shared constant variables
Read-write locks: Read-write locks allow multiple readers to access a shared variable, but allow only one writer
Only report races after an initialized variable has been written
Virgin
Shared
Exclusive
Shared- Modified
read/write, 1st thread write
read, new thread
read
write
write, new thread
read/write
t1 t2 locks_held(t1) locks_held(t2) C(v) { } { } { l1 } rdlock(l1) { l1 } rdlock(l1) { l1 } ++v { l1 } unlock(l1) { } read(v) { l1 } unlock(l1) { }
Require that for each variable v , ๎ (^) some lock l protects v , and ๎ (^) l is held in some mode for every read of v
Definition: l protects v if l is held in write mode for every write of v
t1 t2 l_held(t1) l_held(t2) C(v) { } { } { } { } { l1 } { l1 } { l1 } ++v { } unlock(l1) { } read(v) unlock(l1) { } { } { }
wl_held(t1) wl_held(t2)
rdlock(l1) rdlock(l1)
Approach: Automatically instruments program binary with calls to Eraser runtime ๎ (^) memory loads and stores ๎ (^) lock acquires and releases ๎ (^) storage allocators
Warning messages: ๎ (^) Source file and line number where race discovered ๎ (^) Backtrace listing all active stack frames ๎ (^) Thread ID ๎ (^) Memory address ๎ (^) Type of memory access ๎ (^) Register values such as program counter and stack pointer