Beruflich Dokumente
Kultur Dokumente
Figure 1. Representative tools implemented for ROAD RUNNER. Size is measured in lines of code, excluding blank lines and comments.
ROAD RUNNER facilitates composing dynamic analyses. ROAD - 2. T IME: time the overhead of various tools in the chain (for
RUNNER tools can be composed (via command-line configuration) performance debugging);
into a tool chain, where events are dynamically dispatched down 3. C OUNT: count the distribution of events at various points in the
this tool chain until they are handled by the appropriate tool. Thus, chain (to identify which event handlers to optimize); and
each dynamic analysis is essentially a filter over event streams,
and ROAD RUNNER makes it easy to create new analyses via the 4. R ECORD: record an event stream for later replay, to circumvent
composition of simpler analyses. scheduling non-determinism during debugging.
As an illustration, the Eraser algorithm [24] can be expressed in
Note that these tools, once written, can be used in combination with
terms of three simpler analyses: a ThreadLocal analysis, which
any others, thereby avoiding the cross-cutting clutter of inserting
filters out accesses to thread-local data; a ReadOnly analysis,
code to perform these operations in the analysis event handlers.
which filters out accesses to read-only data; and a LockSet analy-
sis, which tracks the set of locks consistently used to protect each ROAD RUNNER facilitates comparing dynamic analyses. Per-
variable and reports a potential race if one of these sets becomes forming controlled comparisons between different dynamic analy-
empty. The following command line configuration composes these ses is quite difficult. Analyses written by different authors are of-
three tools and applies them to the target program Target.class: ten implemented and evaluated for different languages, computing
rrrun -tool=ThreadLocal:ReadOnly:LockSet Target platforms, or virtual machines. Some also change the run time’s
Each of these tools can be independently re-used. For example, virtual machine, whereas others run on an unmodified version.
we can significantly improve the performance of a relatively slow ROAD RUNNER addresses this problem by making it easier to re-
HappensBefore race detector [19] by composing it with the above implement a collection of published algorithms in a uniform frame-
ThreadLocal and ReadOnly filters, so that HappensBefore ana- work, thereby obtaining clear precision and performance compar-
lyzes only shared, mutable memory locations: isons. For example, ROAD RUNNER has been used to implement
and experimentally compare six different dynamic race detection
rrrun -tool=ThreadLocal:ReadOnly:HappensBefore Target algorithms [10], resulting in a deeper understanding of their rela-
As another example, the Atomizer serializability checker must rea- tive strengths. Such controlled experiments are an essential part of
son about locations with potential race conditions, but may ig- the scientific process.
nore race-free locations. Tool composition enables us to write the
Atomizer tool without worrying about race conditions. We simply
prefix Atomizer in the tool chain with any race detector, which 2. ROAD RUNNER API
allows us to easily experiment with analysis configurations, as in: This section outlines the ROAD RUNNER API and describes how to
write tools that monitor the stream of events generated by the tar-
rrrun -tool=ThreadLocal:ReadOnly:LockSet:Atomizer Target get program while maintaining instrumentation state (that is, tool-
rrrun -tool=FastTrack:Atomizer Target
specific shadow information about each thread, lock, and memory
location used by the target). We first focus on implementing a single
ROAD RUNNER facilitates debugging dynamic analyses. ROAD -
tool using this API and will then extend our presentation to include
RUNNER’s pipe-and-filter architecture enables one to insert addi-
tool composition in Section 2.3 below.
tional diagnostic tools into the tool chain to facilitate debugging.
Figure 2 summarizes the core classes in the ROAD RUNNER
The following utility tools have proven particularly useful:
API. Each analysis tool is defined by extending the Tool class. The
1. P RINT: print out the event stream at various places in the tool Tool class defines methods to handle each type of event that may
chain (for correctness debugging); be generated by the target program, including:
Figure 2: Core ROAD RUNNER API We show four representative event handlers (lines 4–7) for thread
creation, lock acquires and releases, and accesses to non-volatile
1 Tool Abstract Class memory.
2 Each event handler method takes a specific subclass of Event.
3 abstract class Tool { These event classes are also described in Figure 2. Before dis-
4 void create (NewThreadEvent e) { } cussing events and event handlers in more detail, we first introduce
5 void acquire (AcquireEvent e) { }
6 void release (ReleaseEvent e) { }
several auxiliary ROAD RUNNER data structures.
7 void access (AccessEvent e) { } Thread and Lock Shadows. The Java Virtual Machine allocates
8 abstract ShadowVar makeShadowVar(AccessEvent e); a Thread object for each thread in the target program. ROAD RUN -
9 }
NER associates a ShadowThread object with each Thread object.
10
11 Events Each ShadowThread object (see Figure 2, line 36) contains a ref-
12
erence to the underlying Thread, a unique integer identifier tid,
13 class Event { and a reference to the ShadowThread for the parent (or forking)
14 ShadowThread thread; thread, if any. Similarly, ROAD RUNNER allocates a corresponding
15 } ShadowLock object (line 45) for every Java object used as a lock.
16 Tools often need to associate tool-specific information with each
17 class NewThreadEvent extends Event { ... } thread and lock. We could just add new fields to the ShadowThread
18
and ShadowLock classes as necessary, but this clearly leads to
19 class AcquireEvent extends Event {
poorly defined abstractions and pollution of our core APIs. Letting
20 AcquireInfo info; // loc
21 ShadowLock lock; tools subclass these classes also leads to problems, since efficiently
22 } implementing tool composition becomes difficult.
23 To permit extensibility while avoiding these problems, we intro-
24 class AccessEvent extends Event { duce the Decoration class (line 57). Essentially, the Decoration
25 ShadowVar shadow; class provides a generic map from Keys to Values. This map can
26 boolean putShadow(ShadowVar newShadow) be implemented as a hash table, but that would not provide ade-
27 } quate performance. Instead, we require the Key to be a subclass
28
of Decoratable. The Decoration map can then store the Value
29 class FieldAccessEvent extends AccessEvent {
for a Key in the Key itself. Specifically, each Decoration has a
30 FieldAccessInfo info; // loc, class/field desc.
31 Object target; // reciever unique small integer, which is used to index into an Object array
32 } declared in the Decoratable superclass. This pattern provides a
33 fast implementation of the get and set methods in Decoration.
34 Thread, Lock, and Variable Shadows The ShadowThread and ShadowLock classes extend the class
35 Decoratable and provide a generic makeDecoration method
36 class ShadowThread extends Decoratable whereby tools can add Decorations for any desired type T to those
37 implements ShadowVar { structures. We illustrate the use of these Decoration fields in the
38 Thread thread; LockSet example below.
39 int tid;
40 ShadowThread parent; Variable Shadows. Tools also need to record information about
41 each memory location used by the target program (that is, each
42 static <T> Decoration<ShadowThread,T> makeDec(T init) static field, instance field, and array element). While Decorations
43 } work well for threads and locks, they are ill-suited for memory
44
locations. There are orders of magnitude more memory locations
45 class ShadowLock extends Decoratable {
than locks or threads, and these memory locations are accessed
46 Object lock;
47
orders of magnitude more frequently.
48 static <T> Decoration<ShadowLock,T> makeDec(T init) Instead, ROAD RUNNER maintains a shadow location corre-
49 } sponding to each memory location, and this shadow location stores
50 a ShadowVar object reference. When a location is first accessed,
51 interface ShadowVar { } the tool’s makeShadowVar method is called to compute the shadow
52 location’s initial value. ShadowVar is an empty interface that sim-
53 Decorations ply serves to annotate types intended to be stored in these shadow
54
locations. The class ShadowThread implements the ShadowVar
55 class Decoratable { ... }
interface because some tools (such as the ThreadLocal tool de-
56
57 class Decoration<Key extends Decoratable,Value> { scribed below) store ShadowThreads in shadow locations.
58 Decoration(Value initial) Events. The Event superclass (line 13) stores a ShadowThread
59 Value get(Key k) object for the thread performing the operation. Subclasses of Event
60 void set(Key k, Value v)
then contain additional information describing that particular kind
61 }
event. For example, AcquireEvent (line 19) contains the source
location of the acquire (in the info field) and a ShadowLock object
describing the object whose lock is being acquired.
• non-volatile memory (field and array) accesses; For each memory access, ROAD RUNNER calls the tool’s access
• volatile memory (field and array) accesses; method, passing an AccessEvent that contains the current value
• lock acquire and release; of the shadow location in the shadow field, as well as a method
• thread creation and start, join, and interrupt operations; putShadow for updating that shadow location (lines 24–27). Ad-
• wait and join operations; and ditional subclasses of AccessEvent, such as FieldAccessEvent
• method entry and exit. (line 29), record details about different types of accesses.
Figure 3: LockSet Tool be running concurrently. Thus, it is important to design tools to
avoid concurrency errors in the event handlers, such as race condi-
61 class Set implements ShadowVar { tions on a tool’s data structures. Different mechanisms may be used
62 static Set empty() to ensure thread-safety:
63 Set add(ShadowLock lock)
64 Set remove(ShadowLock lock) 1. Event Serialization: ROAD RUNNER can be configured to serial-
65 Set intersect(Set other) ize events so that only a single handler is active at a time. While
66 boolean isEmpty() useful for preliminary design and exploration, as well as debug-
67 } ging, this approach incurs a major performance penalty since it
68
essentially removes all concurrency from the target program.
69 class LockSet extends Tool {
70 2. Tool-Internal Concurrency Control: A programmer may add
71 static Decoration<ShadowThread,Set> locksHeld = synchronization to the internal implementation of a tool to
72 ShadowThread.makeDec(Lockset.empty()); provide finer-grained concurrency control.
73
74 void acquire(AcquireEvent e) { 3. Optimistic Concurrency Control for ShadowVars: Tool-internal
75 Set ls = locksHeld.get(e.thread); concurrency control can lead to performance bottlenecks if syn-
76 locksHeld.set(e.thread, ls.add(e.lock)); chronization is performed on “hot paths” through event han-
77 } dlers. For example, acquiring locks to guard against races on
78 shadow locations in the access handler is very expensive, since
79 void release(ReleaseEvent e) { that handler is called for every memory access.
80 Set ls = locksHeld.get(e.thread);
81 locksHeld.set(e.thread, ls.remove(e.lock)); To avoid this scenario, ROAD RUNNER provides an optimistic
82 } concurrency control mechanism for updating shadow locations.
83 The putShadow method of an AccessEvent e performs an
84 ShadowVar makeShadowVar(AccessEvent e) { atomic-compare-and-swap operation: if the current value in the
85 return locksHeld.get(e.thread); shadow location is the same as e.shadow, then this method
86 } replaces the shadow location with its argument and returns true.
87
However, if the shadow location is not the same as e.shadow
88 void access(AccessEvent e) {
(meaning that it was changed by another thread after the event
89 Set ls = (Set)e.shadow;
90 Set held = locksHeld.get(e.thread); object e was initialized), then the method fails and returns false.
91 Set newLs = ls.intersect(held); In this case, ROAD RUNNER also updates e.shadow with the
92 e.putShadow(newLs); current shadow value to facilitate a subsequent retry.
93 if (newLs.isEmpty()) error(); Thus, if two access event handlers attempt to concurrently mod-
94 } ify the same shadow location, only one will succeed, and the
95 }
other can recognize the conflict and reprocess the event. Using
this feature, the access method in LockSet can be optimized
2.1 LockSet Tool Example as follows:
To illustrate the ROAD RUNNER API in more detail, we show how void access(AccessEvent e) {
to implement Eraser’s LockSet analysis on top of ROAD RUNNER. Set held = locksHeld.get(e.thread);
This analysis tracks the locks currently held by each thread and Set newLs;
the set of locks consistently held on all accesses to each memory do {
location. Set ls = (Set)e.shadow;
The Set class in Figure 3 represents a set of ShadowLock newLs = ls.intersect(held);
objects. That class provides methods to create an empty Set, to } while (!e.putShadow(newLs));
add and remove specific ShadowLocks from a Set, to intersect if (newLs.isEmpty()) error();
}
two Sets, and to check for emptiness. Our implementation uses
a functional representation of these sets.
The LockSet class creates a decoration locksHeld to store the 2.3 Tool Composition
locks held by each thread (line 71). This set is initially empty and is
updated by the acquire and release event handlers. (Java locks We now extend the core ROAD RUNNER API to support the tool
are reentrant, but to simplify tool implementations, ROAD RUNNER composition model, which was designed to be easy-to-use and to
does not generate events for re-entrant lock acquires and releases, provide reasonable efficiency. (In many cases, composing small
since they are no-ops.) tools yields analyses that are comparable in performance to a sin-
The LockSet class stores a Set in each shadow location. When gle large tool.) Our implementation reflects the following design
a location is first accessed, the method makeShadowVar initializes choices:
the shadow location with the set of locks held by the accessing 1. We have designed ROAD RUNNER to make sequential, linear
thread. At each memory access, the access event handler retrieves tool composition as efficient as possible, since we have found
the current lock set ls from the shadow location and the set held linear compositions, or tool chains, to be most common. 1
of locks held by the current thread, and computes the intersection
2. Programs often manipulate millions of memory locations. The
of these two sets. The result is stored back in the shadow location
overhead of maintaining a separate shadow memory location
and, if that set is empty, LockSet reports an error.
for each tool is prohibitively expensive. Thus, ROAD RUNNER
only provides a single “shadow location” for each memory
2.2 ROAD RUNNER Synchronization Models
All threads in the target program may generate events. Since the 1 Parallelcomposition (specified on the command-line as ‘-tool=A|B’)
thread triggering an event is also the thread that executes the tool’s is also supported, but it has not been optimized and is more useful for
event handler code, it is possible that multiple event handlers may exploratory work than for high-performance implementations.
location, and each tool should modify that shadow location only Figure 4: Tool Class with Tool Chain Support
if it is the location’s “current owner.” The first tool in the chain
is the initial owner, and ownership passes down the tool chain 103 abstract class Tool {
when the owning tool explicitly notifies the next tool in the 104
for array-intensive programs, and also due to garbage collection While this lightweight mechanism has been sufficient for our pur-
concerns. In particular, we wish to garbage collect real arrays (and poses, aspects [17] provide more general extension mechanisms.
their shadows) once the target program no longer references them.
ROAD RUNNER maintains a three-tier lookup table: Performance. We have found ROAD RUNNER to provide accept-
able performance in practice. Figure 8 shows the average slow-
1. The first tier is a per-thread inline cache for each syntactic array down of five ROAD RUNNER analysis configurations when check-
access, which contains the eight (real-array/shadow-array) pairs ing the programs from the JavaGrande benchmark suite [14] on a
most recently looked up by each thread at that syntactic access. dual quad-core machine running Mac OSX 10.6 and HotSpot 1.6.
2. The second tier is a shared ConcurrentHashMap, called Re- The second column describes the slowdown of the basic ROAD -
cent, which also stores (real-array/shadow-array) pairs. RUNNER framework, with all of the optimizations from this section
turned off. The subsequent columns then show the benefits as each
3. The final tier is a shared WeakHashMap, called Attic. At fixed
additional optimization is turned on. Cumulatively, the optimiza-
intervals, all entries stored in the Recent table are moved into
tions enable these analyses to have slowdowns of less than 10x.
the Attic, to permit garbage collection of real and shadow ar-
This is quite competitive with specialized research prototypes built
rays. (Real arrays referenced only from the Attic, where they
to study individual analyses (e.g., [9, 21, 24]). As reported in ear-
are stored as weak references, can be reclaimed.)
lier papers [10, 11], ROAD RUNNER checkers can scale to systems
The realToShadow procedure first looks in the per-thread inline as large as the Eclipse development environment [7].
cache, then in the Recent table, and finally in the Attic table, stop-
ping as soon as the array is found (and inserting it into the cache and
Recent tables if not already there). To further reduce overhead, the 5. Related Work
ROAD RUNNER instrumentor performs a simple data-flow analysis ROAD RUNNER uses the ASM [3] library to perform rewriting and
to eliminate redundant lookups. instrumentation of the target program’s .class files at load time. A
There are many alternative designs for maintaining the shadow number of other systems provide features comparable to ASM, e.g.,
array map, but this three-level strategy has proven straightforward BCEL [2]. The SOOT framework [26] is similar, but the rewriting is
to implement, efficient, and predictable in behavior. performed on a somewhat higher-level intermediate language of the
ShadowThread Decoration Inlining. Decorations are conve- kind traditionally used for compiler optimizations. ROAD RUNNER
nient, modular, and efficient, but they do introduce extra lev- provides a higher-level and more focused API than these more gen-
els of indirection that can impact performance for heavily-used eral rewriting engines, since ROAD RUNNER analyses are specified
ShadowThread decorations. To reduce this overhead, ROAD RUN - in terms of event stream handling, and not in terms of rewriting op-
NER provides a load-time bytecode rewriting mechanism that can
erations on target program code. Indeed, much of ROAD RUNNER’s
dynamically add additional per-tool fields into the ShadowThread code base is essentially focused on lifting the bytecode-based vir-
class. The following example code illustrates how the LockSet tual machine abstraction to this event-based abstraction level.
tool can use this feature to replace the locksHeld decoration. Sofya [18] is a dynamic program analysis framework that has
The tool simply defines “dummy” accessor and mutator methods similar goals to ROAD RUNNER. A key difference is that Sofya
(ts get locksHeld and ts set locksHeld) of the appropriate runs the target program in its own JVM, which prevents event pro-
types and calls these methods from event handlers: cessing from interfering with program behavior, but introduces ad-
ditional overheads for inter-JVM communication. Sofya provides
class LockSet extends Tool { an Event Description Language to specify which events are of
interest to the analysis, whereas ROAD RUNNER in general com-
static Set ts_get_locksHeld(ShadowThread ts) { municates all events to the analysis back-end, since most analy-
return null;
}
ses (e.g., race detectors) will typically be interested in most or
all events. Thus, ROAD RUNNER is designed to support a high-
static void ts_set_locksHeld(ShadowThread ts, Set s) { bandwidth event stream, which in turn requires an architecture
} where the target program and the analysis run on the same JVM.
CalFuzzer [15] is a framework for “active testing” of concurrent
void acquire(AcquireEvent e) { programs. It performs bytecode rewriting using SOOT and runs
Set held = ts_get_locksHeld(e.thread); in the same memory space as the target program. Each analysis
... provides callback functions to handle memory accesses, synchro-
} nization operations, etc. CalFuzzer appears not to directly support
}
shadow locations for fields and for array elements. Instead, the Cal-
ROAD RUNNER recognizes the special name prefixes (ts get Fuzzer framework passes integer identifiers to the callback func-
and ts set ) at tool load time and inserts a corresponding field tions to identify memory locations and locks. Analyses can then
$rr locksHeld into the ShadowThread class. It then rewrites the allocate their own arrays indexed by these identifiers, but under
dummy accessor and mutator methods to manipulate this new field. this approach shadow state is likely not garbage-collected, which
may be problematic for large benchmarks. CalFuzzer does include [7] The Eclipse programming environment, version 3.4.0. Available at
explicit support for perturbing the scheduler for active testing. http://www.eclipse.org, 2009.
ATOM [25] provides a framework for instrumenting native code [8] T. Elmas, S. Qadeer, and S. Tasiran. Goldilocks: A race and
Alpha programs with callbacks to analysis tools. The instrumenta- transaction-aware Java runtime. In PLDI, pages 245–255, 2007.
tion process permits a flexible choice of which events to instru- [9] C. Flanagan and S. N. Freund. Atomizer: A dynamic atomic-
ment, but does not provide explicit support for shadow state. Some ity checker for multithreaded programs. Sci. Comput. Program.,
ATOM tools, most notably Eraser [24], implement this feature on 71(2):89–109, 2008.
top of ATOM. [10] C. Flanagan and S. N. Freund. FastTrack: efficient and precise dy-
The Valgrind framework [20] supports heavyweight instrumen- namic race detection. In PLDI, pages 121–133, 2009.
tation of binary code programs, where every register has an asso- [11] C. Flanagan and S. N. Freund. Adversarial memory for detecting
ciated shadow register that contains meta-data about the register’s destructive races. In PLDI, 2010.
value. Valgrind works via disassembly-and-resynthesis, perform- [12] C. Flanagan, S. N. Freund, and J. Yi. Velodrome: A sound and
ing the instrumentation on an higher-level intermediate represen- complete dynamic atomicity checker for multithreaded programs. In
tation, somewhat like the SOOT framework discussed above. The PLDI, pages 293–303, 2008.
Valgrind distribution provides a number of analysis tools, including [13] J. Hatcliff, Robby, and M. B. Dwyer. Verifying atomicity specifica-
some that focus on race conditions. In comparison, ROAD RUNNER tions for concurrent object-oriented software using model-checking.
uses a more lightweight copy-and-annotate approach to instrumen- In VMCAI, pages 175–190, 2004.
tation, which is sufficient for our purposes. [14] Java Grande Forum. Java Grande benchmark suite. Available at
http://www.javagrande.org/, 2008.
6. ROAD RUNNER in Practice [15] P. Joshi, M. Naik, C.-S. Park, and K. Sen. Calfuzzer: An extensible
ROAD RUNNER has proven invaluable for building and evaluating active testing framework for concurrent programs. In CAV, pages 675–
analyses. Implementing a first prototype of a new analysis often 681, 2009.
takes a few days rather than the weeks or months required to build [16] P. Joshi, C.-S. Park, K. Sen, and M. Naik. A randomized dynamic
a system from scratch. Much of this improvement comes from the program analysis technique for detecting real deadlocks. In PLDI,
ROAD RUNNER event stream model, which matches the level of pages 110–120, 2009.
abstraction with which we formulate analyses. [17] G. Kiczales, J. Lamping, A. Mendhekar, C. Maeda, C. V. Lopes, J.-M.
In addition, initial versions of ROAD RUNNER analyses can of- Loingtier, and J. Irwin. Aspect-oriented programming. In ECOOP,
ten be applied to large-scale systems such as Eclipse, because pages 220–242, 1997.
ROAD RUNNER deals with and hides many of the complexities in- [18] A. Kinneer, M. B. Dwyer, and G. Rothermel. Sofya: Supporting
volved in scaling to such systems. This scalability and easy experi- rapid development of dynamic program analyses for Java. ICSE
mentation is critical for evaluating and refining new analyses. Companion, pages 51–52, 2007.
Tool composition in ROAD RUNNER has also played a major [19] F. Mattern. Virtual time and global states of distributed systems. In
role in how we design, implement, test, and validate dynamic analy- Workshop on Parallel and Distributed Algorithms, 1988.
ses. It enables us to express complex algorithms as the composition [20] N. Nethercote and J. Seward. Valgrind: A framework for heavyweight
of simpler, modular ones; to reuse analysis components unchanged; dynamic binary instrumentation. In PLDI, pages 89–100, June 2007.
and to insert monitoring and debugging filters into the tool chain [21] R. O’Callahan and J.-D. Choi. Hybrid dynamic data race detection. In
without cluttering the analysis code. PPOPP, pages 167–178, 2003.
The ROAD RUNNER framework is available for download from [22] E. Pozniansky and A. Schuster. MultiRace: Efficient on-the-fly data
race detection in multithreaded C++ programs. Concurrency and
http://www.cs.williams.edu/~freund/rr. Computation: Practice and Experience, 19(3):327–340, 2007.
[23] C. Sadowski, S. N. Freund, and C. Flanagan. SingleTrack: A dynamic
Acknowledgments determinism checker for multithreaded programs. In ESOP, pages
This work was supported in part by the NSF under Grants 0341179, 394–409, 2009.
0341387, 0644130, and 0707885 and by a Sloan Foundation Fel- [24] S. Savage, M. Burrows, G. Nelson, P. Sobalvarro, and T. E. Anderson.
lowship. Ben Wood helped implement array tracking and several Eraser: A dynamic data race detector for multi-threaded programs.
analyses. Jaeheon Yi, Caitlin Sadowski, and Catalin Iordan helped TOCS, 15(4):391–411, 1997.
test and validate the ROAD RUNNER framework. [25] A. Srivastava and A. Eustace. ATOM : A system for building cus-
tomized program analysis tools. In PLDI, pages 196–205, 1994.
References
[26] R. Vallee-Rai, E. Gagnon, L. Hendren, P. Lam, P. Pominville, and
[1] R. Agarwal and S. D. Stoller. Run-time detection of potential dead- V. Sundaresan. Optimizing Java bytecode using the Soot framework:
locks for programs with locks, semaphores, and condition variables. Is it feasible? In Compiler Construction, pages 18–34, 2000.
In PADTAD, pages 51–60, 2006.
[27] C. von Praun and T. Gross. Object race detection. In OOPSLA, pages
[2] Byte Code Engineering Library. http://jakarta.apache.org/bcel/, 70–82, 2001.
2007.
[28] L. Wang and S. D. Stoller. Runtime analysis of atomicity for multi-
[3] E. Bruneton, R. Lenglet, and T. Coupaye. ASM: A code manipulation threaded programs. IEEE Trans. Software Eng., 32(2):93–110, 2006.
tool to implement adaptable systems. In Adaptable and extensible
[29] M. Xu, R. Bodı́k, and M. D. Hill. A serializability violation detector
component systems, 2002.
for shared-memory server programs. In PLDI, pages 1–14, 2005.
[4] J. Burnim and K. Sen. Asserting and checking determinism for
[30] J. Yi, C. Sadowski, and C. Flanagan. SideTrack: generalizing dynamic
multithreaded programs. In FSE, pages 3–12, 2009.
atomicity analysis. In PADTAD, 2009.
[5] J.-D. Choi, K. Lee, A. Loginov, R. O’Callahan, V. Sarkar, and M. Srid-
[31] Y. Yu, T. Rodeheffer, and W. Chen. RaceTrack: Efficient detection of
haran. Efficient and precise datarace detection for multithreaded
data race conditions via adaptive tracking. In SOSP, pages 221–234,
object-oriented programs. In PLDI, pages 258–269, 2002.
2005.
[6] M. Christiaens and K. D. Bosschere. TRaDe: Data Race Detection for
Java. In International Conference on Computational Science, pages
761–770, 2001.