180 likes | 371 Views
Eraser: A dynamic data race detector for multithreaded programs. S. Savage, M. Burrows, G. Nelson, P. Sobalvarro, and T. Anderson TOCS Nov. 97. Overview. Dynamic data race detection tool – testing paradigm instead of static analysis.
E N D
Eraser: A dynamic data race detector for multithreaded programs S. Savage, M. Burrows, G. Nelson, P. Sobalvarro, and T. Anderson TOCS Nov. 97
Overview • Dynamic data race detection tool – testing paradigm instead of static analysis. • Checks that each shared memory access follows a consistent locking discipline • Data race – when 2 concurrent threads access a shared variable and at least one is a write and the threads use no explicit synchronization to prevent simultaneous access. • Effect will depend on interleaving
Previous work If 2 threads access a shared variable and the accesses are not ordered by happens-before then potential race. lock(mutex) v = v+1; unlock(mutex) Previous Approaches:Lamport’s Happened-Before lock(mutex) v = v+1; unlock(mutex)
Drawbacks of Happened-Before • Difficult to implement efficiently – need per-thread information about access ordering to all shared memory locations. • Highly dependent on scheduler – needs large number of test cases.
Previous work If 2 threads access a shared variable and the accesses are not ordered by happens-before then potential race. Depends on scheduler y=y+1; lock(mutex) v = v+1; unlock(mutex) lock(mutex) v = v+1; unlock(mutex) y=y+1;
Previous work If 2 threads access a shared variable and the accesses are not ordered by happens-before then potential race. Depends on scheduler y=y+1; lock(mutex) v = v+1; unlock(mutex) lock(mutex) v = v+1; unlock(mutex) y=y+1;
Idea in Eraser • Checks that locking discipline is observed. • That the same lock(s) is held whenever the shared data object is accessed. • Infer which locks protect which data items
C(v) – candidate locks for v locks-held(t) – set of locks held by thread t Lock refinement for each v, init C(v) to set of all locks On each access to v by thread t: C(v) = C(v) 3 locks-held(t) If C(v) = {} issue warning Lockset Algorithm
lock(mu1) v=v+1 unlock(mu1) lock(mu2) v=v+1 unlock(mu2) locks-held C(v) {} {mu1, mu2} {mu1} {mu1} {} {mu2} {} {} Example
Initialization without locks Read-shared data(written only during init,read-only afterwards) Reader-writer locking(multiple readers) Don’t start until see a second thread Report only after it becomes write shared Change algorithm to reflect lock types On read of v by t: C(v) = C(v) 3 locks-held(t) On write of v by t: C(v) = C(v) 3 write-locks-held(t) More Sophistication • False Alarms still possible
Per-Location State virgin C(v) updated, races reported wr, 1st thread Sharedmodified wr, new thread exclusive rd, wr, 1st thread wr rd, new thread shared C(v) updated, no race reporting
Implementation • Binary rewriting used • Add instrumentation to call Eraser runtime • Each load and store updates C(v) • Each Acquire and Release call updates locks-held(t) • Calls to storage allocator initializes C(v) • Storage explosion handled by table lookup and use of indexes to represent sets • Shadow word holds index number • Slowdown by factor of 10 to 30x • Will change interleavings
Memory reuse Private locks Benign races if (some_condition) { LOCK m DO if (some_condition) {stuff} END } EraseReuse – resets shadow word to virgin state Lock annotations EraserIgnoreOn()EraserIgnoreOff() Common False Alarms - Annotations
Races inside OS • Using interrupt system to provide mutual exclusion – this implicitly locks everything affected (by interrupt level specified) • Explicitly associate a lock with interrupt level – disabling interrupt is like acquiring that lock • Signal and wait kind of synchronization • V to signal for P which waits -- semaphore not “held” by thread.
Core Loop of Lock-Coupling // ptr->lock.Acquire(); has been done before loop while (next != null & key > next->data) {next->lock.Acquire(); ptr->lock.Release(); ptr=next; next=ptr->next; } 4 6 null 2 8 ptr next