Sign up & Download
Sign in

RaceTrack : Efficient Detection of Data Race Conditions via

by Tom Rodeheffer, Wei Chen
Computing (2005)

Cite this document (BETA)

Available from portal.acm.org
Page 1
hidden

RaceTrack : Efficient Detection of Data Race Conditions via

RaceTrack: Ef cient Detection of Data Race Conditions via
Adaptive Tracking
Yuan Yu
Microsoft Research
1065 La Avenida Ave.
Mountain View, CA 94043
yuanbyu@microsoft.com
Tom Rodeheffer
Microsoft Research
1065 La Avenida Ave.
Mountain View, CA 94043
tomr@microsoft.com
Wei Chen
Computer Science Division
University of California
Berkeley, CA 94720
wychen@cs.berkeley.edu
ABSTRACT
Bugs due to data races in multithreaded programs often ex-
hibit non-deterministic symptoms and are notoriously dif-
ficult to find. This paper describes RaceTrack, a dynamic
race detection tool that tracks the actions of a program and
reports a warning whenever a suspicious pattern of activity
has been observed. RaceTrack uses a novel hybrid detection
algorithm and employs an adaptive approach that automat-
ically directs more effort to areas that are more suspicious,
thus providing more accurate warnings for much less over-
head. A post-processing step correlates warnings and ranks
code segments based on how strongly they are implicated in
potential data races. We implemented RaceTrack inside the
virtual machine of Microsoft’s Common Language Runtime
(product version v1.1.4322) and monitored several major,
real-world applications directly out-of-the-box, without any
modification. Adaptive tracking resulted in a slowdown ra-
tio of about 3x on memory-intensive programs and typically
much less than 2x on other programs, and a memory ratio
of typically less than 1.2x. Several serious data race bugs
were revealed, some previously unknown.
Categories and Subject Descriptors: D.2.5 [Software
Engineering]: Testing and Debugging—diagnostics, moni-
tors
General Terms: Reliability, Performance.
Keywords: Race detection, virtual machine instrumenta-
tion.
1. INTRODUCTION
A data race occurs in a multithreaded program when two
threads access the same memory location without any inter-
vening synchronization operations, and at least one of the
accesses is a write. Data races almost always indicate a pro-
gramming error and such errors are notoriously difficult to
find and debug, due to the non-deterministic nature of multi-
threaded programming. Since the exact schedule of threads
Permission to make digital or hard copies of all or part of this work for
personal or classroom use is granted without fee provided that copies are
not made or distributed for pro t or commercial advantage and that copies
bear this notice and the full citation on the rst page. To copy otherwise, to
republish, to post on servers or to redistribute to lists, requires prior speci c
permission and/or a fee.
SOSP 05, October 23—26, 2005, Brighton, United Kingdom.
Copyright 2005 ACM 1-59593-079-5/05/0010 ...$5.00.
that trigger a data race is timing sensitive, data races are
difficult to reproduce, even when the program is executed
repeatedly with the same inputs. Furthermore, since a data
race typically results in corrupted shared data structures
rather than an immediate crash, programs may continue
to execute, leading to mysterious failures later in unrelated
code. Automatically finding data races in a program thus is
widely recognized as an important research problem.
1.1 Related Work
Automated tools for race detection generally take either
a static or a dynamic approach. For static race detection,
the most common approach is to employ compile-time anal-
ysis on the program source, reporting all potential races that
could occur in any possible program execution [10, 14, 32].
The primary drawback of this approach is excessive false
positives (reporting a potential data race when none exists),
since the compile-time analysis is often unable to determine
the precise set of possible thread interleavings and thus must
make a conservative estimate. Scaling is also difficult, since
the entire program must be analyzed. Another approach
is to augment the programming language’s type system to
express common synchronization relationships, so that any
well-typed program is guaranteed to be free of data races [2,
11]. This language-level approach eliminates data races alto-
gether, but requires a substantial amount of code annotation
and also restricts the kinds of synchronization that can be
expressed.
For dynamic race detection, the program is executed and
a history of its memory accesses and synchronization oper-
ations is recorded and analyzed. Because the history is in
fact a feasible execution, dynamic detectors typically suffer a
lower false positive rate than static detectors. On the other
hand, since not all possible execution paths are considered,
the dynamic technique is not sound and thus cannot certify
a program to be free of data races. The dynamic technique
also imposes runtime overhead which must be kept within
limits while still providing reasonably accurate race detec-
tion. The post-mortem approach records events during pro-
gram execution and analyzes them later [1], or records only
critical events and then carefully replays the program [5,
27]. This approach is unsuitable for long-running applica-
tions that have extensive interactions with their environ-
ment. The other approach is to record and analyze infor-
mation as efficiently as possible on-the-fly.
Existing analysis techniques used in dynamic race detec-
tors are lockset analysis and happens-before analysis.Lockset-
221
Page 2
hidden
based detectors verify that the program execution conforms
to a locking discipline, a programming methodology that
ensures the absence of data races. Eraser [28], for example,
enforces the locking discipline that every shared variable is
protected by some lock. Basically, each shared variable is
associated with a lockset that keeps track of all common
locks held during accesses, and a warning is issued when the
lockset becomes empty. Later lockset-based detectors [21,
25] refine Eraser’s lockset algorithm with more states and
transitions to reduce the number of false positives.
Happens-before detectors [1, 5, 6, 7, 18, 27, 30] are based
on Lamport’s happens-before relation [15], which combines
program order and synchronization events to establish a
partial temporal ordering on program statements. A data
race occurs when there is no established temporal order-
ing between two conflicting memory accesses—neither ac-
cess “happens before” the other. Compared to the lockset
method, happens-before detection is more general and can
be applied to programs using non-lock-based synchroniza-
tion primitives such as fork/join or signal/wait. Happens-
before also never reports a false positive in the absence of
a data race. However, it is less efficient to implement than
lockset analysis and is much more likely to suffer false neg-
atives (failing to detect a potential race) because of its sen-
sitivity to the particular thread schedule. Many detectors
attempt to get the advantages of both lockset and happens-
before analysis by combining the techniques in some way [13,
22, 24, 33]; in fact, Dinning and Schonberg originated the
idea of lockset-based race detection as an improvement to a
happens-before detector [8].
Dynamic race detectors also vary in the technique used
to monitor program execution. In one approach, the pro-
gram binary is modified to instrument each load and store
instruction that accesses global memory [13, 23, 28]. While
this approach is language independent and requires no pro-
gram source, it also results in high overhead in both time
and space. Using Eraser, for example, applications typically
run10to30timesslowerandashadow word is required for
each word in global memory to store lockset information.
When applied to modern programming languages, binary
instrumentation also suffers from an inability to utilize type
information to generate more accurate reports and reduce
execution overhead. Furthermore, hooks are needed into
the runtime’s memory allocator so that the shadow memory
can correctly reflect the state of newly-allocated memory.
A modern runtime that uses a copying garbage collector
presents even more problems.
Race detectors for modern object-oriented programming
languages have therefore generally adopted a higher-level
approach [6, 21, 22, 24, 25]. These tools modify the source
code, the compiler, intermediate bytecodes, or the virtual
machine in order to instrument memory accesses and syn-
chronization operations. This approach enables race detec-
tors to choose the appropriate detection granularity based
on language-defined data structures, instead of using a fixed-
size detection unit such as a word. For object-oriented lan-
guages, fields are the natural choice for a detection unit, as
each field represents a distinct program variable. However,
since fully monitoring every field often introduces unaccept-
able overhead, many current tools place the detection granu-
larity at the object level, assuming that accesses to different
fields in an object will be protected by the same lock. This
technique reduces overhead significantly, often lowering the
Windows COM+ Services
Common Language Runtime
Base Class Library
Data and XML Classes
ASP.NET Windows Forms
Common Language Specification
VB C++ C# JScript…
Figure 1: The .NET framework
running time to within a factor of two of the original pro-
gram. The performance improvement, however, is achieved
at the expense of detection accuracy, as the coarser detec-
tion unit leads to many false alarms. More advanced tools
provide a mechanism for focusing the analysis. Posniansky
and Schuster provide a parameterized detection granularity:
the program is initially run using a generous detection gran-
ularity of say, 256 bytes, and if potential races are detected
the program can be re-run using a smaller granularity to get
more accuracy [24]. O’Callahan and Choi provide a two-pass
solution: the program is initially run using lockset analysis
to identify problematic fields (“simple mode”) and if any
are detected the program is re-run using a combined lockset
and happens-before analysis for just those fields (“detailed
mode”) [22]. Choi et al. apply compile-time analysis tech-
niques, such as points-to and escape analysis, to determine
which accesses can never participate in data races and thus
do not need to be monitored [4].
1.2 The RaceTrack Approach
In this paper, we present RaceTrack, a practical, on-the-
fly race detection tool for large multithreaded object-oriented
programs on the Microsoft .NET platform. Figure 1 illus-
trates the .NET framework. At the core of the framework
is the Common Language Runtime (CLR) [12], a language-
independent layer that provides a managed execution en-
vironment for applications. Applications written in vari-
ous languages are translated into the Common Intermediate
Language (IL) [9], a stack-based language with memory ac-
cess, arithmetic, and method call instructions and descrip-
tive metadata containing type and version information. As
an application executes, the IL is converted into native ma-
chine code by a just-in-time (JIT) compiler in the CLR. The
CLR also manages the tasks of object allocation, thread cre-
ation, exception handling, and garbage collection.
Like some earlier Java-based race detectors [6, 21], Race-
Track performs instrumentation at the virtual machine level.
RaceTrack uses a modified JIT compiler that emits inlined
RaceTrack calls during native code generation and a modi-
fied garbage collector that allocates space with each object
to store RaceTrack information. Applications run on top of
the RaceTrack-modified runtime, with no user modification
required. Also running on top of the CLR is a vast library
of IL code that is also monitored by the RaceTrack-modified
runtime.
222

Sign up today - FREE

Mendeley saves you time finding and organizing research. Learn more

  • All your research in one place
  • Add and import papers easily
  • Access it anywhere, anytime

Start using Mendeley in seconds!

Already have an account? Sign in

Readership Statistics

14 Readers on Mendeley
by Discipline
 
 
by Academic Status
 
57% Ph.D. Student
 
14% Student (Master)
 
7% Other Professional
by Country
 
29% China
 
21% Germany
 
14% Japan