Initial import of valgrind 3.6.0.
diff --git a/drd/Makefile.am b/drd/Makefile.am
new file mode 100644
index 0000000..edfd7de
--- /dev/null
+++ b/drd/Makefile.am
@@ -0,0 +1,155 @@
+include $(top_srcdir)/Makefile.tool.am
+
+EXTRA_DIST = docs/drd-manual.xml
+
+#----------------------------------------------------------------------------
+# Headers, flags
+#----------------------------------------------------------------------------
+
+pkginclude_HEADERS = drd.h
+
+noinst_HEADERS =        \
+  drd_barrier.h         \
+  drd_basics.h          \
+  drd_bitmap.c          \
+  drd_bitmap.h          \
+  drd_clientobj.h       \
+  drd_clientreq.h       \
+  drd_cond.h            \
+  drd_error.h           \
+  drd_hb.h              \
+  drd_load_store.h      \
+  drd_malloc_wrappers.h \
+  drd_mutex.h           \
+  drd_rwlock.h          \
+  drd_segment.c         \
+  drd_segment.h         \
+  drd_semaphore.h       \
+  drd_suppression.h     \
+  drd_thread.c          \
+  drd_thread.h          \
+  drd_thread_bitmap.h   \
+  drd_vc.c              \
+  drd_vc.h              \
+  pub_drd_bitmap.h
+
+DRD_CFLAGS =				\
+  @FLAG_UNLIMITED_INLINE_UNIT_GROWTH@	\
+  -O2					\
+  @FLAG_W_EXTRA@			\
+  -Wformat-nonliteral			\
+  -Wno-inline				\
+  -Wno-unused-parameter
+
+#DRD_CFLAGS += -DENABLE_DRD_CONSISTENCY_CHECKS
+
+#----------------------------------------------------------------------------
+# drd-<platform>
+#----------------------------------------------------------------------------
+
+noinst_PROGRAMS  = drd-@VGCONF_ARCH_PRI@-@VGCONF_OS@
+if VGCONF_HAVE_PLATFORM_SEC
+noinst_PROGRAMS += drd-@VGCONF_ARCH_SEC@-@VGCONF_OS@
+endif
+
+DRD_SOURCES_COMMON =    \
+  drd_barrier.c         \
+  drd_bitmap2_node.c    \
+  drd_clientobj.c       \
+  drd_clientreq.c       \
+  drd_cond.c            \
+  drd_cond_initializer.c \
+  drd_error.c           \
+  drd_hb.c              \
+  drd_load_store.c      \
+  drd_main.c            \
+  drd_malloc_wrappers.c \
+  drd_mutex.c           \
+  drd_rwlock.c          \
+  drd_semaphore.c       \
+  drd_suppression.c
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_SOURCES      = \
+	$(DRD_SOURCES_COMMON)
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS     = \
+	$(AM_CPPFLAGS_@VGCONF_PLATFORM_PRI_CAPS@)
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS       = \
+	$(AM_CFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) $(DRD_CFLAGS)
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_DEPENDENCIES = \
+	$(TOOL_DEPENDENCIES_@VGCONF_PLATFORM_PRI_CAPS@)
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LDADD        = \
+	$(TOOL_LDADD_@VGCONF_PLATFORM_PRI_CAPS@)
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LDFLAGS      = \
+	$(TOOL_LDFLAGS_@VGCONF_PLATFORM_PRI_CAPS@)
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LINK = \
+	$(top_builddir)/coregrind/link_tool_exe_@VGCONF_OS@ \
+	@VALT_LOAD_ADDRESS_PRI@ \
+	$(LINK) \
+	$(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) \
+	$(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LDFLAGS)
+
+if VGCONF_HAVE_PLATFORM_SEC
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_SOURCES      = \
+	$(DRD_SOURCES_COMMON)
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS     = \
+	$(AM_CPPFLAGS_@VGCONF_PLATFORM_SEC_CAPS@)
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS       = \
+	$(AM_CFLAGS_@VGCONF_PLATFORM_SEC_CAPS@) $(DRD_CFLAGS)
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_DEPENDENCIES = \
+	$(TOOL_DEPENDENCIES_@VGCONF_PLATFORM_SEC_CAPS@)
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LDADD        = \
+	$(TOOL_LDADD_@VGCONF_PLATFORM_SEC_CAPS@)
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LDFLAGS      = \
+	$(TOOL_LDFLAGS_@VGCONF_PLATFORM_SEC_CAPS@)
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LINK = \
+	$(top_builddir)/coregrind/link_tool_exe_@VGCONF_OS@ \
+	@VALT_LOAD_ADDRESS_SEC@ \
+	$(LINK) \
+	$(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) \
+	$(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LDFLAGS)
+endif
+
+#----------------------------------------------------------------------------
+# vgpreload_drd-<platform>.so
+#----------------------------------------------------------------------------
+
+noinst_PROGRAMS += vgpreload_drd-@VGCONF_ARCH_PRI@-@VGCONF_OS@.so
+if VGCONF_HAVE_PLATFORM_SEC
+noinst_PROGRAMS += vgpreload_drd-@VGCONF_ARCH_SEC@-@VGCONF_OS@.so
+endif
+
+if VGCONF_OS_IS_DARWIN
+noinst_DSYMS = $(noinst_PROGRAMS)
+endif
+
+VGPRELOAD_DRD_SOURCES_COMMON = \
+  drd_pthread_intercepts.c     \
+  drd_qtcore_intercepts.c      \
+  drd_strmem_intercepts.c
+
+vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_SOURCES      = \
+	$(VGPRELOAD_DRD_SOURCES_COMMON)
+vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CPPFLAGS     = \
+	$(AM_CPPFLAGS_@VGCONF_PLATFORM_PRI_CAPS@)
+vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CFLAGS       = \
+	$(AM_CFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) $(AM_CFLAGS_PIC) $(DRD_CFLAGS)
+vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_DEPENDENCIES = \
+	$(LIBREPLACEMALLOC_@VGCONF_PLATFORM_PRI_CAPS@)
+vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_LDFLAGS      = \
+	$(PRELOAD_LDFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) \
+	$(LIBREPLACEMALLOC_LDFLAGS_@VGCONF_PLATFORM_PRI_CAPS@)
+
+if VGCONF_HAVE_PLATFORM_SEC
+vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_SOURCES      = \
+	$(VGPRELOAD_DRD_SOURCES_COMMON)
+vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CPPFLAGS     = \
+	$(AM_CPPFLAGS_@VGCONF_PLATFORM_SEC_CAPS@)
+vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CFLAGS       = \
+	$(AM_CFLAGS_@VGCONF_PLATFORM_SEC_CAPS@) $(AM_CFLAGS_PIC) $(DRD_CFLAGS)
+vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_DEPENDENCIES = \
+	$(LIBREPLACEMALLOC_@VGCONF_PLATFORM_SEC_CAPS@)
+vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_LDFLAGS      = \
+	$(PRELOAD_LDFLAGS_@VGCONF_PLATFORM_SEC_CAPS@) \
+	$(LIBREPLACEMALLOC_LDFLAGS_@VGCONF_PLATFORM_SEC_CAPS@)
+endif
+
diff --git a/drd/Makefile.in b/drd/Makefile.in
new file mode 100644
index 0000000..3eaac57
--- /dev/null
+++ b/drd/Makefile.in
@@ -0,0 +1,1788 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# This file should be included (directly or indirectly) by every
+# Makefile.am that builds programs.  And also the top-level Makefile.am.
+
+#----------------------------------------------------------------------------
+# Global stuff
+#----------------------------------------------------------------------------
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+DIST_COMMON = $(noinst_HEADERS) $(pkginclude_HEADERS) \
+	$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+	$(top_srcdir)/Makefile.all.am $(top_srcdir)/Makefile.tool.am
+noinst_PROGRAMS = drd-@VGCONF_ARCH_PRI@-@VGCONF_OS@$(EXEEXT) \
+	$(am__EXEEXT_1) \
+	vgpreload_drd-@VGCONF_ARCH_PRI@-@VGCONF_OS@.so$(EXEEXT) \
+	$(am__EXEEXT_2)
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@am__append_1 = drd-@VGCONF_ARCH_SEC@-@VGCONF_OS@
+@VGCONF_HAVE_PLATFORM_SEC_FALSE@drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_DEPENDENCIES =
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@am__append_2 = vgpreload_drd-@VGCONF_ARCH_SEC@-@VGCONF_OS@.so
+subdir = drd
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@am__EXEEXT_1 = drd-@VGCONF_ARCH_SEC@-@VGCONF_OS@$(EXEEXT)
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@am__EXEEXT_2 = vgpreload_drd-@VGCONF_ARCH_SEC@-@VGCONF_OS@.so$(EXEEXT)
+PROGRAMS = $(noinst_PROGRAMS)
+am__objects_1 =  \
+	drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_barrier.$(OBJEXT) \
+	drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_bitmap2_node.$(OBJEXT) \
+	drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientobj.$(OBJEXT) \
+	drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientreq.$(OBJEXT) \
+	drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond.$(OBJEXT) \
+	drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond_initializer.$(OBJEXT) \
+	drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_error.$(OBJEXT) \
+	drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_hb.$(OBJEXT) \
+	drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_load_store.$(OBJEXT) \
+	drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_main.$(OBJEXT) \
+	drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_malloc_wrappers.$(OBJEXT) \
+	drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_mutex.$(OBJEXT) \
+	drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_rwlock.$(OBJEXT) \
+	drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_semaphore.$(OBJEXT) \
+	drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_suppression.$(OBJEXT)
+am_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_OBJECTS = $(am__objects_1)
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_OBJECTS =  \
+	$(am_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_OBJECTS)
+am__drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_SOURCES_DIST = drd_barrier.c \
+	drd_bitmap2_node.c drd_clientobj.c drd_clientreq.c drd_cond.c \
+	drd_cond_initializer.c drd_error.c drd_hb.c drd_load_store.c \
+	drd_main.c drd_malloc_wrappers.c drd_mutex.c drd_rwlock.c \
+	drd_semaphore.c drd_suppression.c
+am__objects_2 =  \
+	drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_barrier.$(OBJEXT) \
+	drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_bitmap2_node.$(OBJEXT) \
+	drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientobj.$(OBJEXT) \
+	drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientreq.$(OBJEXT) \
+	drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond.$(OBJEXT) \
+	drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond_initializer.$(OBJEXT) \
+	drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_error.$(OBJEXT) \
+	drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_hb.$(OBJEXT) \
+	drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_load_store.$(OBJEXT) \
+	drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_main.$(OBJEXT) \
+	drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_malloc_wrappers.$(OBJEXT) \
+	drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_mutex.$(OBJEXT) \
+	drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_rwlock.$(OBJEXT) \
+	drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_semaphore.$(OBJEXT) \
+	drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_suppression.$(OBJEXT)
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@am_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_OBJECTS =  \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	$(am__objects_2)
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_OBJECTS =  \
+	$(am_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_OBJECTS)
+am__objects_3 = vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_pthread_intercepts.$(OBJEXT) \
+	vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_qtcore_intercepts.$(OBJEXT) \
+	vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_strmem_intercepts.$(OBJEXT)
+am_vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_OBJECTS =  \
+	$(am__objects_3)
+vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_OBJECTS =  \
+	$(am_vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_OBJECTS)
+vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_LDADD = $(LDADD)
+vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_LINK = $(CCLD) \
+	$(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CFLAGS) \
+	$(CFLAGS) \
+	$(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_LDFLAGS) \
+	$(LDFLAGS) -o $@
+am__vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_SOURCES_DIST =  \
+	drd_pthread_intercepts.c drd_qtcore_intercepts.c \
+	drd_strmem_intercepts.c
+am__objects_4 = vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_pthread_intercepts.$(OBJEXT) \
+	vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_qtcore_intercepts.$(OBJEXT) \
+	vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_strmem_intercepts.$(OBJEXT)
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@am_vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_OBJECTS =  \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	$(am__objects_4)
+vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_OBJECTS =  \
+	$(am_vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_OBJECTS)
+vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_LDADD = $(LDADD)
+vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_LINK = $(CCLD) \
+	$(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CFLAGS) \
+	$(CFLAGS) \
+	$(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_LDFLAGS) \
+	$(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_SOURCES) \
+	$(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_SOURCES) \
+	$(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_SOURCES) \
+	$(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_SOURCES)
+DIST_SOURCES = $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_SOURCES) \
+	$(am__drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_SOURCES_DIST) \
+	$(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_SOURCES) \
+	$(am__vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_SOURCES_DIST)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-dvi-recursive install-exec-recursive \
+	install-html-recursive install-info-recursive \
+	install-pdf-recursive install-ps-recursive install-recursive \
+	installcheck-recursive installdirs-recursive pdf-recursive \
+	ps-recursive uninstall-recursive
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(pkgincludedir)"
+HEADERS = $(noinst_HEADERS) $(pkginclude_HEADERS)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
+  distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+	$(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+	distdir
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+  dir0=`pwd`; \
+  sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+  sed_rest='s,^[^/]*/*,,'; \
+  sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+  sed_butlast='s,/*[^/]*$$,,'; \
+  while test -n "$$dir1"; do \
+    first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+    if test "$$first" != "."; then \
+      if test "$$first" = ".."; then \
+        dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+        dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+      else \
+        first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+        if test "$$first2" = "$$first"; then \
+          dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+        else \
+          dir2="../$$dir2"; \
+        fi; \
+        dir0="$$dir0"/"$$first"; \
+      fi; \
+    fi; \
+    dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+  done; \
+  reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BOOST_CFLAGS = @BOOST_CFLAGS@
+BOOST_LIBS = @BOOST_LIBS@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_SUPP = @DEFAULT_SUPP@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DIFF = @DIFF@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FLAG_FNO_STACK_PROTECTOR = @FLAG_FNO_STACK_PROTECTOR@
+FLAG_M32 = @FLAG_M32@
+FLAG_M64 = @FLAG_M64@
+FLAG_MAIX32 = @FLAG_MAIX32@
+FLAG_MAIX64 = @FLAG_MAIX64@
+FLAG_MMMX = @FLAG_MMMX@
+FLAG_MSSE = @FLAG_MSSE@
+FLAG_NO_BUILD_ID = @FLAG_NO_BUILD_ID@
+FLAG_UNLIMITED_INLINE_UNIT_GROWTH = @FLAG_UNLIMITED_INLINE_UNIT_GROWTH@
+FLAG_W_EXTRA = @FLAG_W_EXTRA@
+FLAG_W_NO_EMPTY_BODY = @FLAG_W_NO_EMPTY_BODY@
+FLAG_W_NO_FORMAT_ZERO_LENGTH = @FLAG_W_NO_FORMAT_ZERO_LENGTH@
+FLAG_W_NO_UNINITIALIZED = @FLAG_W_NO_UNINITIALIZED@
+GDB = @GDB@
+GLIBC_VERSION = @GLIBC_VERSION@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MPI_CC = @MPI_CC@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PREFERRED_STACK_BOUNDARY = @PREFERRED_STACK_BOUNDARY@
+QTCORE_CFLAGS = @QTCORE_CFLAGS@
+QTCORE_LIBS = @QTCORE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VALT_LOAD_ADDRESS_PRI = @VALT_LOAD_ADDRESS_PRI@
+VALT_LOAD_ADDRESS_SEC = @VALT_LOAD_ADDRESS_SEC@
+VERSION = @VERSION@
+VGCONF_ARCH_PRI = @VGCONF_ARCH_PRI@
+VGCONF_ARCH_SEC = @VGCONF_ARCH_SEC@
+VGCONF_OS = @VGCONF_OS@
+VGCONF_PLATFORM_PRI_CAPS = @VGCONF_PLATFORM_PRI_CAPS@
+VGCONF_PLATFORM_SEC_CAPS = @VGCONF_PLATFORM_SEC_CAPS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = . tests
+inplacedir = $(top_builddir)/.in_place
+
+#----------------------------------------------------------------------------
+# Flags
+#----------------------------------------------------------------------------
+
+# Baseline flags for all compilations.  Aim here is to maximise
+# performance and get whatever useful warnings we can out of gcc.
+AM_CFLAGS_BASE = \
+	-O2 -g \
+	-Wall \
+	-Wmissing-prototypes \
+	-Wshadow \
+	-Wpointer-arith \
+	-Wstrict-prototypes \
+	-Wmissing-declarations \
+	@FLAG_W_NO_FORMAT_ZERO_LENGTH@ \
+	-fno-strict-aliasing
+
+@VGCONF_OS_IS_DARWIN_FALSE@AM_CFLAGS_PIC = -fpic -O -g -fno-omit-frame-pointer -fno-strict-aliasing
+
+# These flags are used for building the preload shared objects.
+# The aim is to give reasonable performance but also to have good
+# stack traces, since users often see stack traces extending 
+# into (and through) the preloads.
+@VGCONF_OS_IS_DARWIN_TRUE@AM_CFLAGS_PIC = -dynamic -O -g -fno-omit-frame-pointer -fno-strict-aliasing \
+@VGCONF_OS_IS_DARWIN_TRUE@		-mno-dynamic-no-pic -fpic -fPIC
+
+
+# Flags for specific targets.
+#
+# Nb: the AM_CPPFLAGS_* values are suitable for building tools and auxprogs.
+# For building the core, coregrind/Makefile.am files add some extra things.
+#
+# Also: in newer versions of automake (1.10 onwards?) asm files ending with
+# '.S' are considered "pre-processed" (as opposed to those ending in '.s')
+# and so the CPPFLAGS are passed to the assembler.  But this is not true for
+# older automakes (e.g. 1.8.5, 1.9.6), sigh.  So we include
+# AM_CPPFLAGS_<PLATFORM> in each AM_CCASFLAGS_<PLATFORM> variable.  This
+# means some of the flags are duplicated on systems with newer versions of
+# automake, but this does not really matter and seems hard to avoid.
+AM_CPPFLAGS_@VGCONF_PLATFORM_PRI_CAPS@ = \
+	-I$(top_srcdir) \
+	-I$(top_srcdir)/include \
+	-I$(top_srcdir)/VEX/pub \
+	-DVGA_@VGCONF_ARCH_PRI@=1 \
+	-DVGO_@VGCONF_OS@=1 \
+	-DVGP_@VGCONF_ARCH_PRI@_@VGCONF_OS@=1
+
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@AM_CPPFLAGS_@VGCONF_PLATFORM_SEC_CAPS@ = \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	-I$(top_srcdir) \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	-I$(top_srcdir)/include \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	-I$(top_srcdir)/VEX/pub \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	-DVGA_@VGCONF_ARCH_SEC@=1 \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	-DVGO_@VGCONF_OS@=1 \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	-DVGP_@VGCONF_ARCH_SEC@_@VGCONF_OS@=1
+
+AM_FLAG_M3264_X86_LINUX = @FLAG_M32@
+AM_CFLAGS_X86_LINUX = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY@ \
+			 	$(AM_CFLAGS_BASE)
+
+AM_CCASFLAGS_X86_LINUX = $(AM_CPPFLAGS_X86_LINUX) @FLAG_M32@ -g
+AM_FLAG_M3264_AMD64_LINUX = @FLAG_M64@
+AM_CFLAGS_AMD64_LINUX = @FLAG_M64@ -fomit-frame-pointer \
+				@PREFERRED_STACK_BOUNDARY@ $(AM_CFLAGS_BASE)
+
+AM_CCASFLAGS_AMD64_LINUX = $(AM_CPPFLAGS_AMD64_LINUX) @FLAG_M64@ -g
+AM_FLAG_M3264_PPC32_LINUX = @FLAG_M32@
+AM_CFLAGS_PPC32_LINUX = @FLAG_M32@ $(AM_CFLAGS_BASE)
+AM_CCASFLAGS_PPC32_LINUX = $(AM_CPPFLAGS_PPC32_LINUX) @FLAG_M32@ -g
+AM_FLAG_M3264_PPC64_LINUX = @FLAG_M64@
+AM_CFLAGS_PPC64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
+AM_CCASFLAGS_PPC64_LINUX = $(AM_CPPFLAGS_PPC64_LINUX) @FLAG_M64@ -g
+AM_FLAG_M3264_ARM_LINUX = @FLAG_M32@
+AM_CFLAGS_ARM_LINUX = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY@ \
+			 	$(AM_CFLAGS_BASE) -marm
+
+AM_CCASFLAGS_ARM_LINUX = $(AM_CPPFLAGS_ARM_LINUX) @FLAG_M32@ -marm -g
+AM_FLAG_M3264_PPC32_AIX5 = @FLAG_MAIX32@
+AM_CFLAGS_PPC32_AIX5 = @FLAG_MAIX32@ -mcpu=powerpc $(AM_CFLAGS_BASE)
+AM_CCASFLAGS_PPC32_AIX5 = $(AM_CPPFLAGS_PPC32_AIX5) \
+			    @FLAG_MAIX32@ -mcpu=powerpc -g
+
+AM_FLAG_M3264_PPC64_AIX5 = @FLAG_MAIX64@
+AM_CFLAGS_PPC64_AIX5 = @FLAG_MAIX64@ -mcpu=powerpc64 $(AM_CFLAGS_BASE)
+AM_CCASFLAGS_PPC64_AIX5 = $(AM_CPPFLAGS_PPC64_AIX5) \
+			    @FLAG_MAIX64@ -mcpu=powerpc64 -g
+
+AM_FLAG_M3264_X86_DARWIN = -arch i386
+AM_CFLAGS_X86_DARWIN = $(WERROR) -arch i386 $(AM_CFLAGS_BASE) \
+				-mmacosx-version-min=10.5 \
+				-fno-stack-protector -fno-pic -fno-PIC
+
+AM_CCASFLAGS_X86_DARWIN = $(AM_CPPFLAGS_X86_DARWIN) -arch i386 -g
+AM_FLAG_M3264_AMD64_DARWIN = -arch x86_64
+AM_CFLAGS_AMD64_DARWIN = $(WERROR) -arch x86_64 $(AM_CFLAGS_BASE) \
+			    -mmacosx-version-min=10.5 -fno-stack-protector
+
+AM_CCASFLAGS_AMD64_DARWIN = $(AM_CPPFLAGS_AMD64_DARWIN) -arch x86_64 -g
+
+# Flags for the primary target.  These must be used to build the
+# regtests and performance tests.  In fact, these must be used to
+# build anything which is built only once on a dual-arch build.
+#
+AM_FLAG_M3264_PRI = $(AM_FLAG_M3264_@VGCONF_PLATFORM_PRI_CAPS@)
+AM_CPPFLAGS_PRI = $(AM_CPPFLAGS_@VGCONF_PLATFORM_PRI_CAPS@)
+AM_CFLAGS_PRI = $(AM_CFLAGS_@VGCONF_PLATFORM_PRI_CAPS@)
+AM_CCASFLAGS_PRI = $(AM_CCASFLAGS_@VGCONF_PLATFORM_PRI_CAPS@)
+@VGCONF_HAVE_PLATFORM_SEC_FALSE@AM_FLAG_M3264_SEC = 
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@AM_FLAG_M3264_SEC = $(AM_FLAG_M3264_@VGCONF_PLATFORM_SEC_CAPS@)
+
+# Baseline link flags for making vgpreload shared objects.
+#
+PRELOAD_LDFLAGS_COMMON_LINUX = -nodefaultlibs -shared -Wl,-z,interpose,-z,initfirst
+PRELOAD_LDFLAGS_COMMON_AIX5 = -nodefaultlibs -shared -Wl,-G -Wl,-bnogc
+PRELOAD_LDFLAGS_COMMON_DARWIN = -dynamic -dynamiclib -all_load
+PRELOAD_LDFLAGS_X86_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
+PRELOAD_LDFLAGS_AMD64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
+PRELOAD_LDFLAGS_PPC32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
+PRELOAD_LDFLAGS_PPC64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
+PRELOAD_LDFLAGS_ARM_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
+PRELOAD_LDFLAGS_PPC32_AIX5 = $(PRELOAD_LDFLAGS_COMMON_AIX5)  @FLAG_MAIX32@
+PRELOAD_LDFLAGS_PPC64_AIX5 = $(PRELOAD_LDFLAGS_COMMON_AIX5)  @FLAG_MAIX64@
+PRELOAD_LDFLAGS_X86_DARWIN = $(PRELOAD_LDFLAGS_COMMON_DARWIN) -arch i386
+PRELOAD_LDFLAGS_AMD64_DARWIN = $(PRELOAD_LDFLAGS_COMMON_DARWIN) -arch x86_64
+
+#----------------------------------------------------------------------------
+# <tool>-<platform> stuff
+#----------------------------------------------------------------------------
+TOOL_DEPENDENCIES_@VGCONF_PLATFORM_PRI_CAPS@ = \
+	$(top_builddir)/coregrind/libcoregrind-@VGCONF_ARCH_PRI@-@VGCONF_OS@.a \
+	$(top_builddir)/VEX/libvex-@VGCONF_ARCH_PRI@-@VGCONF_OS@.a
+
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@TOOL_DEPENDENCIES_@VGCONF_PLATFORM_SEC_CAPS@ = \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	$(top_builddir)/coregrind/libcoregrind-@VGCONF_ARCH_SEC@-@VGCONF_OS@.a \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	$(top_builddir)/VEX/libvex-@VGCONF_ARCH_SEC@-@VGCONF_OS@.a
+
+TOOL_LDADD_COMMON = -lgcc
+TOOL_LDADD_@VGCONF_PLATFORM_PRI_CAPS@ = \
+	$(TOOL_DEPENDENCIES_@VGCONF_PLATFORM_PRI_CAPS@) $(TOOL_LDADD_COMMON)
+
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@TOOL_LDADD_@VGCONF_PLATFORM_SEC_CAPS@ = \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	$(TOOL_DEPENDENCIES_@VGCONF_PLATFORM_SEC_CAPS@) $(TOOL_LDADD_COMMON)
+
+
+# -Wl,--build-id=none is needed when linking tools on Linux. Without this
+# flag newer ld versions (2.20 and later) create a .note.gnu.build-id at the
+# default text segment address, which of course means the resulting executable
+# is unusable. So we have to tell ld not to generate that, with --build-id=none.
+TOOL_LDFLAGS_COMMON_LINUX = \
+	-static -nodefaultlibs -nostartfiles -u _start @FLAG_NO_BUILD_ID@
+
+TOOL_LDFLAGS_COMMON_AIX5 = \
+	-static -Wl,-e_start_valgrind
+
+TOOL_LDFLAGS_COMMON_DARWIN = \
+	-nodefaultlibs -nostartfiles -Wl,-u,__start -Wl,-e,__start
+
+TOOL_LDFLAGS_X86_LINUX = \
+	$(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M32@
+
+TOOL_LDFLAGS_AMD64_LINUX = \
+	$(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M64@
+
+TOOL_LDFLAGS_PPC32_LINUX = \
+	$(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M32@
+
+TOOL_LDFLAGS_PPC64_LINUX = \
+	$(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M64@
+
+TOOL_LDFLAGS_ARM_LINUX = \
+	$(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M32@
+
+TOOL_LDFLAGS_PPC32_AIX5 = \
+	$(TOOL_LDFLAGS_COMMON_AIX5) @FLAG_MAIX32@
+
+TOOL_LDFLAGS_PPC64_AIX5 = \
+	$(TOOL_LDFLAGS_COMMON_AIX5) @FLAG_MAIX64@ -Wl,-bbigtoc
+
+TOOL_LDFLAGS_X86_DARWIN = \
+	$(TOOL_LDFLAGS_COMMON_DARWIN) -arch i386
+
+TOOL_LDFLAGS_AMD64_DARWIN = \
+	$(TOOL_LDFLAGS_COMMON_DARWIN) -arch x86_64
+
+
+# NB for 64-bit darwin.  We may want to set -Wl,-pagezero_size to
+# something smaller than the default of 4G, so as to facilitate
+# loading clients who are also linked thusly (currently m_ume.c
+# will fail to load them).  Although such setting is probably
+# better done in link_tool_exe.c.
+#
+#	-Wl,-pagezero_size,0x100000000
+
+#----------------------------------------------------------------------------
+# vgpreload_<tool>-<platform>.a stuff
+#----------------------------------------------------------------------------
+LIBREPLACEMALLOC_X86_LINUX = \
+	$(top_builddir)/coregrind/libreplacemalloc_toolpreload-x86-linux.a
+
+LIBREPLACEMALLOC_AMD64_LINUX = \
+	$(top_builddir)/coregrind/libreplacemalloc_toolpreload-amd64-linux.a
+
+LIBREPLACEMALLOC_PPC32_LINUX = \
+	$(top_builddir)/coregrind/libreplacemalloc_toolpreload-ppc32-linux.a
+
+LIBREPLACEMALLOC_PPC64_LINUX = \
+	$(top_builddir)/coregrind/libreplacemalloc_toolpreload-ppc64-linux.a
+
+LIBREPLACEMALLOC_ARM_LINUX = \
+	$(top_builddir)/coregrind/libreplacemalloc_toolpreload-arm-linux.a
+
+LIBREPLACEMALLOC_PPC32_AIX5 = \
+	$(top_builddir)/coregrind/libreplacemalloc_toolpreload-ppc32-aix5.a
+
+LIBREPLACEMALLOC_PPC64_AIX5 = \
+	$(top_builddir)/coregrind/libreplacemalloc_toolpreload-ppc64-aix5.a
+
+LIBREPLACEMALLOC_X86_DARWIN = \
+	$(top_builddir)/coregrind/libreplacemalloc_toolpreload-x86-darwin.a
+
+LIBREPLACEMALLOC_AMD64_DARWIN = \
+	$(top_builddir)/coregrind/libreplacemalloc_toolpreload-amd64-darwin.a
+
+LIBREPLACEMALLOC_LDFLAGS_X86_LINUX = \
+	-Wl,--whole-archive \
+	$(LIBREPLACEMALLOC_X86_LINUX) \
+	-Wl,--no-whole-archive
+
+LIBREPLACEMALLOC_LDFLAGS_AMD64_LINUX = \
+	-Wl,--whole-archive \
+	$(LIBREPLACEMALLOC_AMD64_LINUX) \
+	-Wl,--no-whole-archive
+
+LIBREPLACEMALLOC_LDFLAGS_PPC32_LINUX = \
+	-Wl,--whole-archive \
+	$(LIBREPLACEMALLOC_PPC32_LINUX) \
+	-Wl,--no-whole-archive
+
+LIBREPLACEMALLOC_LDFLAGS_PPC64_LINUX = \
+	-Wl,--whole-archive \
+	$(LIBREPLACEMALLOC_PPC64_LINUX) \
+	-Wl,--no-whole-archive
+
+LIBREPLACEMALLOC_LDFLAGS_ARM_LINUX = \
+	-Wl,--whole-archive \
+	$(LIBREPLACEMALLOC_ARM_LINUX) \
+	-Wl,--no-whole-archive
+
+LIBREPLACEMALLOC_LDFLAGS_PPC32_AIX5 = \
+	$(LIBREPLACEMALLOC_PPC32_AIX5)
+
+LIBREPLACEMALLOC_LDFLAGS_PPC64_AIX5 = \
+	$(LIBREPLACEMALLOC_PPC64_AIX5)
+
+LIBREPLACEMALLOC_LDFLAGS_X86_DARWIN = \
+	$(LIBREPLACEMALLOC_X86_DARWIN)
+
+LIBREPLACEMALLOC_LDFLAGS_AMD64_DARWIN = \
+	$(LIBREPLACEMALLOC_AMD64_DARWIN)
+
+EXTRA_DIST = docs/drd-manual.xml
+
+#----------------------------------------------------------------------------
+# Headers, flags
+#----------------------------------------------------------------------------
+pkginclude_HEADERS = drd.h
+noinst_HEADERS = \
+  drd_barrier.h         \
+  drd_basics.h          \
+  drd_bitmap.c          \
+  drd_bitmap.h          \
+  drd_clientobj.h       \
+  drd_clientreq.h       \
+  drd_cond.h            \
+  drd_error.h           \
+  drd_hb.h              \
+  drd_load_store.h      \
+  drd_malloc_wrappers.h \
+  drd_mutex.h           \
+  drd_rwlock.h          \
+  drd_segment.c         \
+  drd_segment.h         \
+  drd_semaphore.h       \
+  drd_suppression.h     \
+  drd_thread.c          \
+  drd_thread.h          \
+  drd_thread_bitmap.h   \
+  drd_vc.c              \
+  drd_vc.h              \
+  pub_drd_bitmap.h
+
+DRD_CFLAGS = \
+  @FLAG_UNLIMITED_INLINE_UNIT_GROWTH@	\
+  -O2					\
+  @FLAG_W_EXTRA@			\
+  -Wformat-nonliteral			\
+  -Wno-inline				\
+  -Wno-unused-parameter
+
+DRD_SOURCES_COMMON = \
+  drd_barrier.c         \
+  drd_bitmap2_node.c    \
+  drd_clientobj.c       \
+  drd_clientreq.c       \
+  drd_cond.c            \
+  drd_cond_initializer.c \
+  drd_error.c           \
+  drd_hb.c              \
+  drd_load_store.c      \
+  drd_main.c            \
+  drd_malloc_wrappers.c \
+  drd_mutex.c           \
+  drd_rwlock.c          \
+  drd_semaphore.c       \
+  drd_suppression.c
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_SOURCES = \
+	$(DRD_SOURCES_COMMON)
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS = \
+	$(AM_CPPFLAGS_@VGCONF_PLATFORM_PRI_CAPS@)
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS = \
+	$(AM_CFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) $(DRD_CFLAGS)
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_DEPENDENCIES = \
+	$(TOOL_DEPENDENCIES_@VGCONF_PLATFORM_PRI_CAPS@)
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LDADD = \
+	$(TOOL_LDADD_@VGCONF_PLATFORM_PRI_CAPS@)
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LDFLAGS = \
+	$(TOOL_LDFLAGS_@VGCONF_PLATFORM_PRI_CAPS@)
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LINK = \
+	$(top_builddir)/coregrind/link_tool_exe_@VGCONF_OS@ \
+	@VALT_LOAD_ADDRESS_PRI@ \
+	$(LINK) \
+	$(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) \
+	$(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LDFLAGS)
+
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_SOURCES = \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	$(DRD_SOURCES_COMMON)
+
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS = \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	$(AM_CPPFLAGS_@VGCONF_PLATFORM_SEC_CAPS@)
+
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS = \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	$(AM_CFLAGS_@VGCONF_PLATFORM_SEC_CAPS@) $(DRD_CFLAGS)
+
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_DEPENDENCIES = \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	$(TOOL_DEPENDENCIES_@VGCONF_PLATFORM_SEC_CAPS@)
+
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LDADD = \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	$(TOOL_LDADD_@VGCONF_PLATFORM_SEC_CAPS@)
+
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LDFLAGS = \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	$(TOOL_LDFLAGS_@VGCONF_PLATFORM_SEC_CAPS@)
+
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LINK = \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	$(top_builddir)/coregrind/link_tool_exe_@VGCONF_OS@ \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	@VALT_LOAD_ADDRESS_SEC@ \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	$(LINK) \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	$(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	$(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LDFLAGS)
+
+@VGCONF_OS_IS_DARWIN_TRUE@noinst_DSYMS = $(noinst_PROGRAMS)
+VGPRELOAD_DRD_SOURCES_COMMON = \
+  drd_pthread_intercepts.c     \
+  drd_qtcore_intercepts.c      \
+  drd_strmem_intercepts.c
+
+vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_SOURCES = \
+	$(VGPRELOAD_DRD_SOURCES_COMMON)
+
+vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CPPFLAGS = \
+	$(AM_CPPFLAGS_@VGCONF_PLATFORM_PRI_CAPS@)
+
+vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CFLAGS = \
+	$(AM_CFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) $(AM_CFLAGS_PIC) $(DRD_CFLAGS)
+
+vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_DEPENDENCIES = \
+	$(LIBREPLACEMALLOC_@VGCONF_PLATFORM_PRI_CAPS@)
+
+vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_LDFLAGS = \
+	$(PRELOAD_LDFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) \
+	$(LIBREPLACEMALLOC_LDFLAGS_@VGCONF_PLATFORM_PRI_CAPS@)
+
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_SOURCES = \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	$(VGPRELOAD_DRD_SOURCES_COMMON)
+
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CPPFLAGS = \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	$(AM_CPPFLAGS_@VGCONF_PLATFORM_SEC_CAPS@)
+
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CFLAGS = \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	$(AM_CFLAGS_@VGCONF_PLATFORM_SEC_CAPS@) $(AM_CFLAGS_PIC) $(DRD_CFLAGS)
+
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_DEPENDENCIES = \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	$(LIBREPLACEMALLOC_@VGCONF_PLATFORM_SEC_CAPS@)
+
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_LDFLAGS = \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	$(PRELOAD_LDFLAGS_@VGCONF_PLATFORM_SEC_CAPS@) \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	$(LIBREPLACEMALLOC_LDFLAGS_@VGCONF_PLATFORM_SEC_CAPS@)
+
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.tool.am $(top_srcdir)/Makefile.all.am $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign drd/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign drd/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstPROGRAMS:
+	-test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+drd-@VGCONF_ARCH_PRI@-@VGCONF_OS@$(EXEEXT): $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_OBJECTS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_DEPENDENCIES) 
+	@rm -f drd-@VGCONF_ARCH_PRI@-@VGCONF_OS@$(EXEEXT)
+	$(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LINK) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_OBJECTS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LDADD) $(LIBS)
+drd-@VGCONF_ARCH_SEC@-@VGCONF_OS@$(EXEEXT): $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_OBJECTS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_DEPENDENCIES) 
+	@rm -f drd-@VGCONF_ARCH_SEC@-@VGCONF_OS@$(EXEEXT)
+	$(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LINK) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_OBJECTS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LDADD) $(LIBS)
+vgpreload_drd-@VGCONF_ARCH_PRI@-@VGCONF_OS@.so$(EXEEXT): $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_OBJECTS) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_DEPENDENCIES) 
+	@rm -f vgpreload_drd-@VGCONF_ARCH_PRI@-@VGCONF_OS@.so$(EXEEXT)
+	$(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_LINK) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_OBJECTS) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_LDADD) $(LIBS)
+vgpreload_drd-@VGCONF_ARCH_SEC@-@VGCONF_OS@.so$(EXEEXT): $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_OBJECTS) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_DEPENDENCIES) 
+	@rm -f vgpreload_drd-@VGCONF_ARCH_SEC@-@VGCONF_OS@.so$(EXEEXT)
+	$(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_LINK) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_OBJECTS) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_barrier.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_bitmap2_node.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientobj.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientreq.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond_initializer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_error.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_hb.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_load_store.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_malloc_wrappers.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_mutex.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_rwlock.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_semaphore.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_suppression.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_barrier.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_bitmap2_node.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientobj.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientreq.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond_initializer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_error.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_hb.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_load_store.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_malloc_wrappers.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_mutex.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_rwlock.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_semaphore.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_suppression.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_pthread_intercepts.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_qtcore_intercepts.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_strmem_intercepts.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_pthread_intercepts.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_qtcore_intercepts.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_strmem_intercepts.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_barrier.o: drd_barrier.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_barrier.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_barrier.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_barrier.o `test -f 'drd_barrier.c' || echo '$(srcdir)/'`drd_barrier.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_barrier.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_barrier.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_barrier.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_barrier.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_barrier.o `test -f 'drd_barrier.c' || echo '$(srcdir)/'`drd_barrier.c
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_barrier.obj: drd_barrier.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_barrier.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_barrier.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_barrier.obj `if test -f 'drd_barrier.c'; then $(CYGPATH_W) 'drd_barrier.c'; else $(CYGPATH_W) '$(srcdir)/drd_barrier.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_barrier.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_barrier.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_barrier.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_barrier.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_barrier.obj `if test -f 'drd_barrier.c'; then $(CYGPATH_W) 'drd_barrier.c'; else $(CYGPATH_W) '$(srcdir)/drd_barrier.c'; fi`
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_bitmap2_node.o: drd_bitmap2_node.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_bitmap2_node.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_bitmap2_node.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_bitmap2_node.o `test -f 'drd_bitmap2_node.c' || echo '$(srcdir)/'`drd_bitmap2_node.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_bitmap2_node.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_bitmap2_node.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_bitmap2_node.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_bitmap2_node.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_bitmap2_node.o `test -f 'drd_bitmap2_node.c' || echo '$(srcdir)/'`drd_bitmap2_node.c
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_bitmap2_node.obj: drd_bitmap2_node.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_bitmap2_node.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_bitmap2_node.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_bitmap2_node.obj `if test -f 'drd_bitmap2_node.c'; then $(CYGPATH_W) 'drd_bitmap2_node.c'; else $(CYGPATH_W) '$(srcdir)/drd_bitmap2_node.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_bitmap2_node.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_bitmap2_node.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_bitmap2_node.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_bitmap2_node.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_bitmap2_node.obj `if test -f 'drd_bitmap2_node.c'; then $(CYGPATH_W) 'drd_bitmap2_node.c'; else $(CYGPATH_W) '$(srcdir)/drd_bitmap2_node.c'; fi`
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientobj.o: drd_clientobj.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientobj.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientobj.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientobj.o `test -f 'drd_clientobj.c' || echo '$(srcdir)/'`drd_clientobj.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientobj.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientobj.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_clientobj.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientobj.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientobj.o `test -f 'drd_clientobj.c' || echo '$(srcdir)/'`drd_clientobj.c
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientobj.obj: drd_clientobj.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientobj.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientobj.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientobj.obj `if test -f 'drd_clientobj.c'; then $(CYGPATH_W) 'drd_clientobj.c'; else $(CYGPATH_W) '$(srcdir)/drd_clientobj.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientobj.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientobj.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_clientobj.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientobj.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientobj.obj `if test -f 'drd_clientobj.c'; then $(CYGPATH_W) 'drd_clientobj.c'; else $(CYGPATH_W) '$(srcdir)/drd_clientobj.c'; fi`
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientreq.o: drd_clientreq.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientreq.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientreq.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientreq.o `test -f 'drd_clientreq.c' || echo '$(srcdir)/'`drd_clientreq.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientreq.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientreq.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_clientreq.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientreq.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientreq.o `test -f 'drd_clientreq.c' || echo '$(srcdir)/'`drd_clientreq.c
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientreq.obj: drd_clientreq.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientreq.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientreq.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientreq.obj `if test -f 'drd_clientreq.c'; then $(CYGPATH_W) 'drd_clientreq.c'; else $(CYGPATH_W) '$(srcdir)/drd_clientreq.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientreq.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientreq.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_clientreq.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientreq.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_clientreq.obj `if test -f 'drd_clientreq.c'; then $(CYGPATH_W) 'drd_clientreq.c'; else $(CYGPATH_W) '$(srcdir)/drd_clientreq.c'; fi`
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond.o: drd_cond.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond.o `test -f 'drd_cond.c' || echo '$(srcdir)/'`drd_cond.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_cond.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond.o `test -f 'drd_cond.c' || echo '$(srcdir)/'`drd_cond.c
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond.obj: drd_cond.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond.obj `if test -f 'drd_cond.c'; then $(CYGPATH_W) 'drd_cond.c'; else $(CYGPATH_W) '$(srcdir)/drd_cond.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_cond.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond.obj `if test -f 'drd_cond.c'; then $(CYGPATH_W) 'drd_cond.c'; else $(CYGPATH_W) '$(srcdir)/drd_cond.c'; fi`
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond_initializer.o: drd_cond_initializer.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond_initializer.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond_initializer.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond_initializer.o `test -f 'drd_cond_initializer.c' || echo '$(srcdir)/'`drd_cond_initializer.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond_initializer.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond_initializer.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_cond_initializer.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond_initializer.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond_initializer.o `test -f 'drd_cond_initializer.c' || echo '$(srcdir)/'`drd_cond_initializer.c
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond_initializer.obj: drd_cond_initializer.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond_initializer.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond_initializer.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond_initializer.obj `if test -f 'drd_cond_initializer.c'; then $(CYGPATH_W) 'drd_cond_initializer.c'; else $(CYGPATH_W) '$(srcdir)/drd_cond_initializer.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond_initializer.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond_initializer.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_cond_initializer.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond_initializer.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_cond_initializer.obj `if test -f 'drd_cond_initializer.c'; then $(CYGPATH_W) 'drd_cond_initializer.c'; else $(CYGPATH_W) '$(srcdir)/drd_cond_initializer.c'; fi`
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_error.o: drd_error.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_error.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_error.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_error.o `test -f 'drd_error.c' || echo '$(srcdir)/'`drd_error.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_error.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_error.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_error.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_error.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_error.o `test -f 'drd_error.c' || echo '$(srcdir)/'`drd_error.c
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_error.obj: drd_error.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_error.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_error.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_error.obj `if test -f 'drd_error.c'; then $(CYGPATH_W) 'drd_error.c'; else $(CYGPATH_W) '$(srcdir)/drd_error.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_error.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_error.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_error.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_error.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_error.obj `if test -f 'drd_error.c'; then $(CYGPATH_W) 'drd_error.c'; else $(CYGPATH_W) '$(srcdir)/drd_error.c'; fi`
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_hb.o: drd_hb.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_hb.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_hb.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_hb.o `test -f 'drd_hb.c' || echo '$(srcdir)/'`drd_hb.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_hb.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_hb.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_hb.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_hb.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_hb.o `test -f 'drd_hb.c' || echo '$(srcdir)/'`drd_hb.c
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_hb.obj: drd_hb.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_hb.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_hb.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_hb.obj `if test -f 'drd_hb.c'; then $(CYGPATH_W) 'drd_hb.c'; else $(CYGPATH_W) '$(srcdir)/drd_hb.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_hb.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_hb.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_hb.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_hb.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_hb.obj `if test -f 'drd_hb.c'; then $(CYGPATH_W) 'drd_hb.c'; else $(CYGPATH_W) '$(srcdir)/drd_hb.c'; fi`
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_load_store.o: drd_load_store.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_load_store.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_load_store.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_load_store.o `test -f 'drd_load_store.c' || echo '$(srcdir)/'`drd_load_store.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_load_store.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_load_store.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_load_store.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_load_store.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_load_store.o `test -f 'drd_load_store.c' || echo '$(srcdir)/'`drd_load_store.c
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_load_store.obj: drd_load_store.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_load_store.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_load_store.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_load_store.obj `if test -f 'drd_load_store.c'; then $(CYGPATH_W) 'drd_load_store.c'; else $(CYGPATH_W) '$(srcdir)/drd_load_store.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_load_store.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_load_store.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_load_store.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_load_store.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_load_store.obj `if test -f 'drd_load_store.c'; then $(CYGPATH_W) 'drd_load_store.c'; else $(CYGPATH_W) '$(srcdir)/drd_load_store.c'; fi`
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_main.o: drd_main.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_main.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_main.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_main.o `test -f 'drd_main.c' || echo '$(srcdir)/'`drd_main.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_main.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_main.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_main.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_main.o `test -f 'drd_main.c' || echo '$(srcdir)/'`drd_main.c
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_main.obj: drd_main.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_main.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_main.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_main.obj `if test -f 'drd_main.c'; then $(CYGPATH_W) 'drd_main.c'; else $(CYGPATH_W) '$(srcdir)/drd_main.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_main.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_main.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_main.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_main.obj `if test -f 'drd_main.c'; then $(CYGPATH_W) 'drd_main.c'; else $(CYGPATH_W) '$(srcdir)/drd_main.c'; fi`
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_malloc_wrappers.o: drd_malloc_wrappers.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_malloc_wrappers.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_malloc_wrappers.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_malloc_wrappers.o `test -f 'drd_malloc_wrappers.c' || echo '$(srcdir)/'`drd_malloc_wrappers.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_malloc_wrappers.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_malloc_wrappers.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_malloc_wrappers.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_malloc_wrappers.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_malloc_wrappers.o `test -f 'drd_malloc_wrappers.c' || echo '$(srcdir)/'`drd_malloc_wrappers.c
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_malloc_wrappers.obj: drd_malloc_wrappers.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_malloc_wrappers.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_malloc_wrappers.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_malloc_wrappers.obj `if test -f 'drd_malloc_wrappers.c'; then $(CYGPATH_W) 'drd_malloc_wrappers.c'; else $(CYGPATH_W) '$(srcdir)/drd_malloc_wrappers.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_malloc_wrappers.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_malloc_wrappers.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_malloc_wrappers.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_malloc_wrappers.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_malloc_wrappers.obj `if test -f 'drd_malloc_wrappers.c'; then $(CYGPATH_W) 'drd_malloc_wrappers.c'; else $(CYGPATH_W) '$(srcdir)/drd_malloc_wrappers.c'; fi`
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_mutex.o: drd_mutex.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_mutex.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_mutex.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_mutex.o `test -f 'drd_mutex.c' || echo '$(srcdir)/'`drd_mutex.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_mutex.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_mutex.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_mutex.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_mutex.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_mutex.o `test -f 'drd_mutex.c' || echo '$(srcdir)/'`drd_mutex.c
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_mutex.obj: drd_mutex.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_mutex.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_mutex.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_mutex.obj `if test -f 'drd_mutex.c'; then $(CYGPATH_W) 'drd_mutex.c'; else $(CYGPATH_W) '$(srcdir)/drd_mutex.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_mutex.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_mutex.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_mutex.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_mutex.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_mutex.obj `if test -f 'drd_mutex.c'; then $(CYGPATH_W) 'drd_mutex.c'; else $(CYGPATH_W) '$(srcdir)/drd_mutex.c'; fi`
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_rwlock.o: drd_rwlock.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_rwlock.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_rwlock.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_rwlock.o `test -f 'drd_rwlock.c' || echo '$(srcdir)/'`drd_rwlock.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_rwlock.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_rwlock.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_rwlock.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_rwlock.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_rwlock.o `test -f 'drd_rwlock.c' || echo '$(srcdir)/'`drd_rwlock.c
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_rwlock.obj: drd_rwlock.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_rwlock.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_rwlock.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_rwlock.obj `if test -f 'drd_rwlock.c'; then $(CYGPATH_W) 'drd_rwlock.c'; else $(CYGPATH_W) '$(srcdir)/drd_rwlock.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_rwlock.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_rwlock.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_rwlock.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_rwlock.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_rwlock.obj `if test -f 'drd_rwlock.c'; then $(CYGPATH_W) 'drd_rwlock.c'; else $(CYGPATH_W) '$(srcdir)/drd_rwlock.c'; fi`
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_semaphore.o: drd_semaphore.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_semaphore.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_semaphore.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_semaphore.o `test -f 'drd_semaphore.c' || echo '$(srcdir)/'`drd_semaphore.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_semaphore.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_semaphore.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_semaphore.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_semaphore.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_semaphore.o `test -f 'drd_semaphore.c' || echo '$(srcdir)/'`drd_semaphore.c
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_semaphore.obj: drd_semaphore.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_semaphore.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_semaphore.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_semaphore.obj `if test -f 'drd_semaphore.c'; then $(CYGPATH_W) 'drd_semaphore.c'; else $(CYGPATH_W) '$(srcdir)/drd_semaphore.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_semaphore.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_semaphore.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_semaphore.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_semaphore.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_semaphore.obj `if test -f 'drd_semaphore.c'; then $(CYGPATH_W) 'drd_semaphore.c'; else $(CYGPATH_W) '$(srcdir)/drd_semaphore.c'; fi`
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_suppression.o: drd_suppression.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_suppression.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_suppression.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_suppression.o `test -f 'drd_suppression.c' || echo '$(srcdir)/'`drd_suppression.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_suppression.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_suppression.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_suppression.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_suppression.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_suppression.o `test -f 'drd_suppression.c' || echo '$(srcdir)/'`drd_suppression.c
+
+drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_suppression.obj: drd_suppression.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_suppression.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_suppression.Tpo -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_suppression.obj `if test -f 'drd_suppression.c'; then $(CYGPATH_W) 'drd_suppression.c'; else $(CYGPATH_W) '$(srcdir)/drd_suppression.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_suppression.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_suppression.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_suppression.c' object='drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_suppression.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@-drd_suppression.obj `if test -f 'drd_suppression.c'; then $(CYGPATH_W) 'drd_suppression.c'; else $(CYGPATH_W) '$(srcdir)/drd_suppression.c'; fi`
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_barrier.o: drd_barrier.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_barrier.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_barrier.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_barrier.o `test -f 'drd_barrier.c' || echo '$(srcdir)/'`drd_barrier.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_barrier.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_barrier.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_barrier.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_barrier.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_barrier.o `test -f 'drd_barrier.c' || echo '$(srcdir)/'`drd_barrier.c
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_barrier.obj: drd_barrier.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_barrier.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_barrier.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_barrier.obj `if test -f 'drd_barrier.c'; then $(CYGPATH_W) 'drd_barrier.c'; else $(CYGPATH_W) '$(srcdir)/drd_barrier.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_barrier.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_barrier.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_barrier.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_barrier.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_barrier.obj `if test -f 'drd_barrier.c'; then $(CYGPATH_W) 'drd_barrier.c'; else $(CYGPATH_W) '$(srcdir)/drd_barrier.c'; fi`
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_bitmap2_node.o: drd_bitmap2_node.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_bitmap2_node.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_bitmap2_node.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_bitmap2_node.o `test -f 'drd_bitmap2_node.c' || echo '$(srcdir)/'`drd_bitmap2_node.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_bitmap2_node.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_bitmap2_node.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_bitmap2_node.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_bitmap2_node.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_bitmap2_node.o `test -f 'drd_bitmap2_node.c' || echo '$(srcdir)/'`drd_bitmap2_node.c
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_bitmap2_node.obj: drd_bitmap2_node.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_bitmap2_node.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_bitmap2_node.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_bitmap2_node.obj `if test -f 'drd_bitmap2_node.c'; then $(CYGPATH_W) 'drd_bitmap2_node.c'; else $(CYGPATH_W) '$(srcdir)/drd_bitmap2_node.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_bitmap2_node.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_bitmap2_node.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_bitmap2_node.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_bitmap2_node.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_bitmap2_node.obj `if test -f 'drd_bitmap2_node.c'; then $(CYGPATH_W) 'drd_bitmap2_node.c'; else $(CYGPATH_W) '$(srcdir)/drd_bitmap2_node.c'; fi`
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientobj.o: drd_clientobj.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientobj.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientobj.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientobj.o `test -f 'drd_clientobj.c' || echo '$(srcdir)/'`drd_clientobj.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientobj.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientobj.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_clientobj.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientobj.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientobj.o `test -f 'drd_clientobj.c' || echo '$(srcdir)/'`drd_clientobj.c
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientobj.obj: drd_clientobj.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientobj.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientobj.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientobj.obj `if test -f 'drd_clientobj.c'; then $(CYGPATH_W) 'drd_clientobj.c'; else $(CYGPATH_W) '$(srcdir)/drd_clientobj.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientobj.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientobj.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_clientobj.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientobj.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientobj.obj `if test -f 'drd_clientobj.c'; then $(CYGPATH_W) 'drd_clientobj.c'; else $(CYGPATH_W) '$(srcdir)/drd_clientobj.c'; fi`
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientreq.o: drd_clientreq.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientreq.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientreq.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientreq.o `test -f 'drd_clientreq.c' || echo '$(srcdir)/'`drd_clientreq.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientreq.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientreq.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_clientreq.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientreq.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientreq.o `test -f 'drd_clientreq.c' || echo '$(srcdir)/'`drd_clientreq.c
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientreq.obj: drd_clientreq.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientreq.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientreq.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientreq.obj `if test -f 'drd_clientreq.c'; then $(CYGPATH_W) 'drd_clientreq.c'; else $(CYGPATH_W) '$(srcdir)/drd_clientreq.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientreq.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientreq.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_clientreq.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientreq.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_clientreq.obj `if test -f 'drd_clientreq.c'; then $(CYGPATH_W) 'drd_clientreq.c'; else $(CYGPATH_W) '$(srcdir)/drd_clientreq.c'; fi`
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond.o: drd_cond.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond.o `test -f 'drd_cond.c' || echo '$(srcdir)/'`drd_cond.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_cond.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond.o `test -f 'drd_cond.c' || echo '$(srcdir)/'`drd_cond.c
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond.obj: drd_cond.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond.obj `if test -f 'drd_cond.c'; then $(CYGPATH_W) 'drd_cond.c'; else $(CYGPATH_W) '$(srcdir)/drd_cond.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_cond.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond.obj `if test -f 'drd_cond.c'; then $(CYGPATH_W) 'drd_cond.c'; else $(CYGPATH_W) '$(srcdir)/drd_cond.c'; fi`
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond_initializer.o: drd_cond_initializer.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond_initializer.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond_initializer.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond_initializer.o `test -f 'drd_cond_initializer.c' || echo '$(srcdir)/'`drd_cond_initializer.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond_initializer.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond_initializer.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_cond_initializer.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond_initializer.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond_initializer.o `test -f 'drd_cond_initializer.c' || echo '$(srcdir)/'`drd_cond_initializer.c
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond_initializer.obj: drd_cond_initializer.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond_initializer.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond_initializer.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond_initializer.obj `if test -f 'drd_cond_initializer.c'; then $(CYGPATH_W) 'drd_cond_initializer.c'; else $(CYGPATH_W) '$(srcdir)/drd_cond_initializer.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond_initializer.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond_initializer.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_cond_initializer.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond_initializer.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_cond_initializer.obj `if test -f 'drd_cond_initializer.c'; then $(CYGPATH_W) 'drd_cond_initializer.c'; else $(CYGPATH_W) '$(srcdir)/drd_cond_initializer.c'; fi`
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_error.o: drd_error.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_error.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_error.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_error.o `test -f 'drd_error.c' || echo '$(srcdir)/'`drd_error.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_error.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_error.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_error.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_error.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_error.o `test -f 'drd_error.c' || echo '$(srcdir)/'`drd_error.c
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_error.obj: drd_error.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_error.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_error.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_error.obj `if test -f 'drd_error.c'; then $(CYGPATH_W) 'drd_error.c'; else $(CYGPATH_W) '$(srcdir)/drd_error.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_error.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_error.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_error.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_error.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_error.obj `if test -f 'drd_error.c'; then $(CYGPATH_W) 'drd_error.c'; else $(CYGPATH_W) '$(srcdir)/drd_error.c'; fi`
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_hb.o: drd_hb.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_hb.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_hb.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_hb.o `test -f 'drd_hb.c' || echo '$(srcdir)/'`drd_hb.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_hb.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_hb.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_hb.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_hb.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_hb.o `test -f 'drd_hb.c' || echo '$(srcdir)/'`drd_hb.c
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_hb.obj: drd_hb.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_hb.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_hb.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_hb.obj `if test -f 'drd_hb.c'; then $(CYGPATH_W) 'drd_hb.c'; else $(CYGPATH_W) '$(srcdir)/drd_hb.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_hb.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_hb.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_hb.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_hb.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_hb.obj `if test -f 'drd_hb.c'; then $(CYGPATH_W) 'drd_hb.c'; else $(CYGPATH_W) '$(srcdir)/drd_hb.c'; fi`
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_load_store.o: drd_load_store.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_load_store.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_load_store.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_load_store.o `test -f 'drd_load_store.c' || echo '$(srcdir)/'`drd_load_store.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_load_store.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_load_store.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_load_store.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_load_store.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_load_store.o `test -f 'drd_load_store.c' || echo '$(srcdir)/'`drd_load_store.c
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_load_store.obj: drd_load_store.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_load_store.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_load_store.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_load_store.obj `if test -f 'drd_load_store.c'; then $(CYGPATH_W) 'drd_load_store.c'; else $(CYGPATH_W) '$(srcdir)/drd_load_store.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_load_store.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_load_store.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_load_store.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_load_store.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_load_store.obj `if test -f 'drd_load_store.c'; then $(CYGPATH_W) 'drd_load_store.c'; else $(CYGPATH_W) '$(srcdir)/drd_load_store.c'; fi`
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_main.o: drd_main.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_main.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_main.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_main.o `test -f 'drd_main.c' || echo '$(srcdir)/'`drd_main.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_main.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_main.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_main.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_main.o `test -f 'drd_main.c' || echo '$(srcdir)/'`drd_main.c
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_main.obj: drd_main.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_main.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_main.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_main.obj `if test -f 'drd_main.c'; then $(CYGPATH_W) 'drd_main.c'; else $(CYGPATH_W) '$(srcdir)/drd_main.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_main.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_main.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_main.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_main.obj `if test -f 'drd_main.c'; then $(CYGPATH_W) 'drd_main.c'; else $(CYGPATH_W) '$(srcdir)/drd_main.c'; fi`
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_malloc_wrappers.o: drd_malloc_wrappers.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_malloc_wrappers.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_malloc_wrappers.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_malloc_wrappers.o `test -f 'drd_malloc_wrappers.c' || echo '$(srcdir)/'`drd_malloc_wrappers.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_malloc_wrappers.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_malloc_wrappers.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_malloc_wrappers.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_malloc_wrappers.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_malloc_wrappers.o `test -f 'drd_malloc_wrappers.c' || echo '$(srcdir)/'`drd_malloc_wrappers.c
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_malloc_wrappers.obj: drd_malloc_wrappers.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_malloc_wrappers.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_malloc_wrappers.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_malloc_wrappers.obj `if test -f 'drd_malloc_wrappers.c'; then $(CYGPATH_W) 'drd_malloc_wrappers.c'; else $(CYGPATH_W) '$(srcdir)/drd_malloc_wrappers.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_malloc_wrappers.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_malloc_wrappers.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_malloc_wrappers.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_malloc_wrappers.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_malloc_wrappers.obj `if test -f 'drd_malloc_wrappers.c'; then $(CYGPATH_W) 'drd_malloc_wrappers.c'; else $(CYGPATH_W) '$(srcdir)/drd_malloc_wrappers.c'; fi`
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_mutex.o: drd_mutex.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_mutex.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_mutex.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_mutex.o `test -f 'drd_mutex.c' || echo '$(srcdir)/'`drd_mutex.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_mutex.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_mutex.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_mutex.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_mutex.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_mutex.o `test -f 'drd_mutex.c' || echo '$(srcdir)/'`drd_mutex.c
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_mutex.obj: drd_mutex.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_mutex.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_mutex.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_mutex.obj `if test -f 'drd_mutex.c'; then $(CYGPATH_W) 'drd_mutex.c'; else $(CYGPATH_W) '$(srcdir)/drd_mutex.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_mutex.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_mutex.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_mutex.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_mutex.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_mutex.obj `if test -f 'drd_mutex.c'; then $(CYGPATH_W) 'drd_mutex.c'; else $(CYGPATH_W) '$(srcdir)/drd_mutex.c'; fi`
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_rwlock.o: drd_rwlock.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_rwlock.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_rwlock.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_rwlock.o `test -f 'drd_rwlock.c' || echo '$(srcdir)/'`drd_rwlock.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_rwlock.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_rwlock.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_rwlock.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_rwlock.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_rwlock.o `test -f 'drd_rwlock.c' || echo '$(srcdir)/'`drd_rwlock.c
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_rwlock.obj: drd_rwlock.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_rwlock.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_rwlock.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_rwlock.obj `if test -f 'drd_rwlock.c'; then $(CYGPATH_W) 'drd_rwlock.c'; else $(CYGPATH_W) '$(srcdir)/drd_rwlock.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_rwlock.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_rwlock.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_rwlock.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_rwlock.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_rwlock.obj `if test -f 'drd_rwlock.c'; then $(CYGPATH_W) 'drd_rwlock.c'; else $(CYGPATH_W) '$(srcdir)/drd_rwlock.c'; fi`
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_semaphore.o: drd_semaphore.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_semaphore.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_semaphore.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_semaphore.o `test -f 'drd_semaphore.c' || echo '$(srcdir)/'`drd_semaphore.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_semaphore.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_semaphore.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_semaphore.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_semaphore.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_semaphore.o `test -f 'drd_semaphore.c' || echo '$(srcdir)/'`drd_semaphore.c
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_semaphore.obj: drd_semaphore.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_semaphore.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_semaphore.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_semaphore.obj `if test -f 'drd_semaphore.c'; then $(CYGPATH_W) 'drd_semaphore.c'; else $(CYGPATH_W) '$(srcdir)/drd_semaphore.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_semaphore.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_semaphore.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_semaphore.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_semaphore.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_semaphore.obj `if test -f 'drd_semaphore.c'; then $(CYGPATH_W) 'drd_semaphore.c'; else $(CYGPATH_W) '$(srcdir)/drd_semaphore.c'; fi`
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_suppression.o: drd_suppression.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_suppression.o -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_suppression.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_suppression.o `test -f 'drd_suppression.c' || echo '$(srcdir)/'`drd_suppression.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_suppression.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_suppression.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_suppression.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_suppression.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_suppression.o `test -f 'drd_suppression.c' || echo '$(srcdir)/'`drd_suppression.c
+
+drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_suppression.obj: drd_suppression.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -MT drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_suppression.obj -MD -MP -MF $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_suppression.Tpo -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_suppression.obj `if test -f 'drd_suppression.c'; then $(CYGPATH_W) 'drd_suppression.c'; else $(CYGPATH_W) '$(srcdir)/drd_suppression.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_suppression.Tpo $(DEPDIR)/drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_suppression.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_suppression.c' object='drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_suppression.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS) $(CPPFLAGS) $(drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) $(CFLAGS) -c -o drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@-drd_suppression.obj `if test -f 'drd_suppression.c'; then $(CYGPATH_W) 'drd_suppression.c'; else $(CYGPATH_W) '$(srcdir)/drd_suppression.c'; fi`
+
+vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_pthread_intercepts.o: drd_pthread_intercepts.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -MT vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_pthread_intercepts.o -MD -MP -MF $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_pthread_intercepts.Tpo -c -o vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_pthread_intercepts.o `test -f 'drd_pthread_intercepts.c' || echo '$(srcdir)/'`drd_pthread_intercepts.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_pthread_intercepts.Tpo $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_pthread_intercepts.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_pthread_intercepts.c' object='vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_pthread_intercepts.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -c -o vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_pthread_intercepts.o `test -f 'drd_pthread_intercepts.c' || echo '$(srcdir)/'`drd_pthread_intercepts.c
+
+vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_pthread_intercepts.obj: drd_pthread_intercepts.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -MT vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_pthread_intercepts.obj -MD -MP -MF $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_pthread_intercepts.Tpo -c -o vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_pthread_intercepts.obj `if test -f 'drd_pthread_intercepts.c'; then $(CYGPATH_W) 'drd_pthread_intercepts.c'; else $(CYGPATH_W) '$(srcdir)/drd_pthread_intercepts.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_pthread_intercepts.Tpo $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_pthread_intercepts.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_pthread_intercepts.c' object='vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_pthread_intercepts.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -c -o vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_pthread_intercepts.obj `if test -f 'drd_pthread_intercepts.c'; then $(CYGPATH_W) 'drd_pthread_intercepts.c'; else $(CYGPATH_W) '$(srcdir)/drd_pthread_intercepts.c'; fi`
+
+vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_qtcore_intercepts.o: drd_qtcore_intercepts.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -MT vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_qtcore_intercepts.o -MD -MP -MF $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_qtcore_intercepts.Tpo -c -o vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_qtcore_intercepts.o `test -f 'drd_qtcore_intercepts.c' || echo '$(srcdir)/'`drd_qtcore_intercepts.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_qtcore_intercepts.Tpo $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_qtcore_intercepts.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_qtcore_intercepts.c' object='vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_qtcore_intercepts.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -c -o vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_qtcore_intercepts.o `test -f 'drd_qtcore_intercepts.c' || echo '$(srcdir)/'`drd_qtcore_intercepts.c
+
+vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_qtcore_intercepts.obj: drd_qtcore_intercepts.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -MT vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_qtcore_intercepts.obj -MD -MP -MF $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_qtcore_intercepts.Tpo -c -o vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_qtcore_intercepts.obj `if test -f 'drd_qtcore_intercepts.c'; then $(CYGPATH_W) 'drd_qtcore_intercepts.c'; else $(CYGPATH_W) '$(srcdir)/drd_qtcore_intercepts.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_qtcore_intercepts.Tpo $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_qtcore_intercepts.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_qtcore_intercepts.c' object='vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_qtcore_intercepts.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -c -o vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_qtcore_intercepts.obj `if test -f 'drd_qtcore_intercepts.c'; then $(CYGPATH_W) 'drd_qtcore_intercepts.c'; else $(CYGPATH_W) '$(srcdir)/drd_qtcore_intercepts.c'; fi`
+
+vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_strmem_intercepts.o: drd_strmem_intercepts.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -MT vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_strmem_intercepts.o -MD -MP -MF $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_strmem_intercepts.Tpo -c -o vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_strmem_intercepts.o `test -f 'drd_strmem_intercepts.c' || echo '$(srcdir)/'`drd_strmem_intercepts.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_strmem_intercepts.Tpo $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_strmem_intercepts.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_strmem_intercepts.c' object='vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_strmem_intercepts.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -c -o vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_strmem_intercepts.o `test -f 'drd_strmem_intercepts.c' || echo '$(srcdir)/'`drd_strmem_intercepts.c
+
+vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_strmem_intercepts.obj: drd_strmem_intercepts.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -MT vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_strmem_intercepts.obj -MD -MP -MF $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_strmem_intercepts.Tpo -c -o vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_strmem_intercepts.obj `if test -f 'drd_strmem_intercepts.c'; then $(CYGPATH_W) 'drd_strmem_intercepts.c'; else $(CYGPATH_W) '$(srcdir)/drd_strmem_intercepts.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_strmem_intercepts.Tpo $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_strmem_intercepts.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_strmem_intercepts.c' object='vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_strmem_intercepts.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -c -o vgpreload_drd_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so-drd_strmem_intercepts.obj `if test -f 'drd_strmem_intercepts.c'; then $(CYGPATH_W) 'drd_strmem_intercepts.c'; else $(CYGPATH_W) '$(srcdir)/drd_strmem_intercepts.c'; fi`
+
+vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_pthread_intercepts.o: drd_pthread_intercepts.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -MT vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_pthread_intercepts.o -MD -MP -MF $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_pthread_intercepts.Tpo -c -o vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_pthread_intercepts.o `test -f 'drd_pthread_intercepts.c' || echo '$(srcdir)/'`drd_pthread_intercepts.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_pthread_intercepts.Tpo $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_pthread_intercepts.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_pthread_intercepts.c' object='vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_pthread_intercepts.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -c -o vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_pthread_intercepts.o `test -f 'drd_pthread_intercepts.c' || echo '$(srcdir)/'`drd_pthread_intercepts.c
+
+vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_pthread_intercepts.obj: drd_pthread_intercepts.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -MT vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_pthread_intercepts.obj -MD -MP -MF $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_pthread_intercepts.Tpo -c -o vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_pthread_intercepts.obj `if test -f 'drd_pthread_intercepts.c'; then $(CYGPATH_W) 'drd_pthread_intercepts.c'; else $(CYGPATH_W) '$(srcdir)/drd_pthread_intercepts.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_pthread_intercepts.Tpo $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_pthread_intercepts.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_pthread_intercepts.c' object='vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_pthread_intercepts.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -c -o vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_pthread_intercepts.obj `if test -f 'drd_pthread_intercepts.c'; then $(CYGPATH_W) 'drd_pthread_intercepts.c'; else $(CYGPATH_W) '$(srcdir)/drd_pthread_intercepts.c'; fi`
+
+vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_qtcore_intercepts.o: drd_qtcore_intercepts.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -MT vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_qtcore_intercepts.o -MD -MP -MF $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_qtcore_intercepts.Tpo -c -o vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_qtcore_intercepts.o `test -f 'drd_qtcore_intercepts.c' || echo '$(srcdir)/'`drd_qtcore_intercepts.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_qtcore_intercepts.Tpo $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_qtcore_intercepts.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_qtcore_intercepts.c' object='vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_qtcore_intercepts.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -c -o vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_qtcore_intercepts.o `test -f 'drd_qtcore_intercepts.c' || echo '$(srcdir)/'`drd_qtcore_intercepts.c
+
+vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_qtcore_intercepts.obj: drd_qtcore_intercepts.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -MT vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_qtcore_intercepts.obj -MD -MP -MF $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_qtcore_intercepts.Tpo -c -o vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_qtcore_intercepts.obj `if test -f 'drd_qtcore_intercepts.c'; then $(CYGPATH_W) 'drd_qtcore_intercepts.c'; else $(CYGPATH_W) '$(srcdir)/drd_qtcore_intercepts.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_qtcore_intercepts.Tpo $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_qtcore_intercepts.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_qtcore_intercepts.c' object='vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_qtcore_intercepts.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -c -o vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_qtcore_intercepts.obj `if test -f 'drd_qtcore_intercepts.c'; then $(CYGPATH_W) 'drd_qtcore_intercepts.c'; else $(CYGPATH_W) '$(srcdir)/drd_qtcore_intercepts.c'; fi`
+
+vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_strmem_intercepts.o: drd_strmem_intercepts.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -MT vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_strmem_intercepts.o -MD -MP -MF $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_strmem_intercepts.Tpo -c -o vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_strmem_intercepts.o `test -f 'drd_strmem_intercepts.c' || echo '$(srcdir)/'`drd_strmem_intercepts.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_strmem_intercepts.Tpo $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_strmem_intercepts.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_strmem_intercepts.c' object='vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_strmem_intercepts.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -c -o vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_strmem_intercepts.o `test -f 'drd_strmem_intercepts.c' || echo '$(srcdir)/'`drd_strmem_intercepts.c
+
+vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_strmem_intercepts.obj: drd_strmem_intercepts.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -MT vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_strmem_intercepts.obj -MD -MP -MF $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_strmem_intercepts.Tpo -c -o vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_strmem_intercepts.obj `if test -f 'drd_strmem_intercepts.c'; then $(CYGPATH_W) 'drd_strmem_intercepts.c'; else $(CYGPATH_W) '$(srcdir)/drd_strmem_intercepts.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_strmem_intercepts.Tpo $(DEPDIR)/vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_strmem_intercepts.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='drd_strmem_intercepts.c' object='vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_strmem_intercepts.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CPPFLAGS) $(CPPFLAGS) $(vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CFLAGS) $(CFLAGS) -c -o vgpreload_drd_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so-drd_strmem_intercepts.obj `if test -f 'drd_strmem_intercepts.c'; then $(CYGPATH_W) 'drd_strmem_intercepts.c'; else $(CYGPATH_W) '$(srcdir)/drd_strmem_intercepts.c'; fi`
+install-pkgincludeHEADERS: $(pkginclude_HEADERS)
+	@$(NORMAL_INSTALL)
+	test -z "$(pkgincludedir)" || $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)"
+	@list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
+	for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; \
+	done | $(am__base_list) | \
+	while read files; do \
+	  echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \
+	  $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \
+	done
+
+uninstall-pkgincludeHEADERS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
+	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+	test -n "$$files" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(pkgincludedir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(pkgincludedir)" && rm -f $$files
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@fail= failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+	@fail= failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	set x; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+	@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d "$(distdir)/$$subdir" \
+	    || $(MKDIR_P) "$(distdir)/$$subdir" \
+	    || exit 1; \
+	  fi; \
+	done
+	@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+	    $(am__relativize); \
+	    new_distdir=$$reldir; \
+	    dir1=$$subdir; dir2="$(top_distdir)"; \
+	    $(am__relativize); \
+	    new_top_distdir=$$reldir; \
+	    echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+	    echo "     am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+	    ($(am__cd) $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$new_top_distdir" \
+	        distdir="$$new_distdir" \
+		am__remove_distdir=: \
+		am__skip_length_check=: \
+		am__skip_mode_fix=: \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(PROGRAMS) $(HEADERS) all-local
+installdirs: installdirs-recursive
+installdirs-am:
+	for dir in "$(DESTDIR)$(pkgincludedir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-local clean-noinstPROGRAMS \
+	mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-pkgincludeHEADERS
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am: install-exec-local
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-pkgincludeHEADERS
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+	install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+	all all-am all-local check check-am clean clean-generic \
+	clean-local clean-noinstPROGRAMS ctags ctags-recursive \
+	distclean distclean-compile distclean-generic distclean-tags \
+	distdir dvi dvi-am html html-am info info-am install \
+	install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-exec-local \
+	install-html install-html-am install-info install-info-am \
+	install-man install-pdf install-pdf-am \
+	install-pkgincludeHEADERS install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	installdirs-am maintainer-clean maintainer-clean-generic \
+	mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \
+	ps ps-am tags tags-recursive uninstall uninstall-am \
+	uninstall-pkgincludeHEADERS
+
+
+# This used to be required when Vex had a handwritten Makefile.  It
+# shouldn't be needed any more, though.
+
+#----------------------------------------------------------------------------
+# noinst_PROGRAMS and noinst_DSYMS targets
+#----------------------------------------------------------------------------
+
+# On Darwin, for a program 'p', the DWARF debug info is stored in the
+# directory 'p.dSYM'.  This must be generated after the executable is
+# created, with 'dsymutil p'.  We could redefine LINK with a script that
+# executes 'dsymutil' after linking, but that's a pain.  Instead we use this
+# hook so that every time "make check" is run, we subsequently invoke
+# 'dsymutil' on all the executables that lack a .dSYM directory, or that are
+# newer than their corresponding .dSYM directory.
+build-noinst_DSYMS: $(noinst_DSYMS)
+	for f in $(noinst_DSYMS); do \
+	  if [ ! -e $$f.dSYM  -o  $$f -nt $$f.dSYM ] ; then \
+	      echo "dsymutil $$f"; \
+	      dsymutil $$f; \
+	  fi; \
+	done
+
+# This is used by coregrind/Makefile.am and Makefile.tool.am for doing
+# "in-place" installs.  It copies $(noinst_PROGRAMS) into $inplacedir.
+# It needs to be depended on by an 'all-local' rule.
+inplace-noinst_PROGRAMS: $(noinst_PROGRAMS)
+	mkdir -p $(inplacedir); \
+	for f in $(noinst_PROGRAMS) ; do \
+	  rm -f $(inplacedir)/$$f; \
+	  ln -f -s ../$(subdir)/$$f $(inplacedir); \
+	done
+
+# Similar to inplace-noinst_PROGRAMS
+inplace-noinst_DSYMS: build-noinst_DSYMS
+	mkdir -p $(inplacedir); \
+	for f in $(noinst_DSYMS); do \
+	  rm -f $(inplacedir)/$$f.dSYM; \
+	  ln -f -s ../$(subdir)/$$f.dSYM $(inplacedir); \
+	done
+
+# This is used by coregrind/Makefile.am and by <tool>/Makefile.am for doing
+# "make install".  It copies $(noinst_PROGRAMS) into $prefix/lib/valgrind/.
+# It needs to be depended on by an 'install-exec-local' rule.
+install-noinst_PROGRAMS: $(noinst_PROGRAMS)
+	$(mkinstalldirs) $(DESTDIR)$(pkglibdir); \
+	for f in $(noinst_PROGRAMS); do \
+	  $(INSTALL_PROGRAM) $$f $(DESTDIR)$(pkglibdir); \
+	done
+
+# Similar to install-noinst_PROGRAMS.
+# Nb: we don't use $(INSTALL_PROGRAM) here because it doesn't work with
+# directories.  XXX: not sure whether the resulting permissions will be
+# correct when using 'cp -R'...
+install-noinst_DSYMS: build-noinst_DSYMS
+	$(mkinstalldirs) $(DESTDIR)$(pkglibdir); \
+	for f in $(noinst_DSYMS); do \
+	  cp -R $$f.dSYM $(DESTDIR)$(pkglibdir); \
+	done
+
+# This needs to be depended on by a 'clean-local' rule.
+clean-noinst_DSYMS:
+	for f in $(noinst_DSYMS); do \
+	  rm -rf $$f.dSYM; \
+	done
+
+#----------------------------------------------------------------------------
+# General stuff
+#----------------------------------------------------------------------------
+
+all-local: inplace-noinst_PROGRAMS inplace-noinst_DSYMS
+
+clean-local: clean-noinst_DSYMS
+
+install-exec-local: install-noinst_PROGRAMS install-noinst_DSYMS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/drd/docs/drd-manual.xml b/drd/docs/drd-manual.xml
new file mode 100644
index 0000000..b1e77ca
--- /dev/null
+++ b/drd/docs/drd-manual.xml
@@ -0,0 +1,1745 @@
+<?xml version="1.0"?> <!-- -*- sgml -*- -->
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+  "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+[ <!ENTITY % vg-entities SYSTEM "../../docs/xml/vg-entities.xml"> %vg-entities; ]>
+
+
+<chapter id="drd-manual" xreflabel="DRD: a thread error detector">
+  <title>DRD: a thread error detector</title>
+
+<para>To use this tool, you must specify
+<option>--tool=drd</option>
+on the Valgrind command line.</para>
+
+
+<sect1 id="drd-manual.overview" xreflabel="Overview">
+<title>Overview</title>
+
+<para>
+DRD is a Valgrind tool for detecting errors in multithreaded C and C++
+programs. The tool works for any program that uses the POSIX threading
+primitives or that uses threading concepts built on top of the POSIX threading
+primitives.
+</para>
+
+<sect2 id="drd-manual.mt-progr-models" xreflabel="MT-progr-models">
+<title>Multithreaded Programming Paradigms</title>
+
+<para>
+There are two possible reasons for using multithreading in a program:
+<itemizedlist>
+  <listitem>
+    <para>
+      To model concurrent activities. Assigning one thread to each activity
+      can be a great simplification compared to multiplexing the states of
+      multiple activities in a single thread. This is why most server software
+      and embedded software is multithreaded.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      To use multiple CPU cores simultaneously for speeding up
+      computations. This is why many High Performance Computing (HPC)
+      applications are multithreaded.
+    </para>
+  </listitem>
+</itemizedlist>
+</para>
+
+<para>
+Multithreaded programs can use one or more of the following programming
+paradigms. Which paradigm is appropriate depends e.g. on the application type.
+Some examples of multithreaded programming paradigms are:
+<itemizedlist>
+  <listitem>
+    <para>
+      Locking. Data that is shared over threads is protected from concurrent
+      accesses via locking. E.g. the POSIX threads library, the Qt library
+      and the Boost.Thread library support this paradigm directly.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      Message passing. No data is shared between threads, but threads exchange
+      data by passing messages to each other. Examples of implementations of
+      the message passing paradigm are MPI and CORBA.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      Automatic parallelization. A compiler converts a sequential program into
+      a multithreaded program. The original program may or may not contain
+      parallelization hints. One example of such parallelization hints is the
+      OpenMP standard. In this standard a set of directives are defined which
+      tell a compiler how to parallelize a C, C++ or Fortran program. OpenMP
+      is well suited for computational intensive applications. As an example,
+      an open source image processing software package is using OpenMP to
+      maximize performance on systems with multiple CPU
+      cores. GCC supports the
+      OpenMP standard from version 4.2.0 on.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      Software Transactional Memory (STM). Any data that is shared between
+      threads is updated via transactions. After each transaction it is
+      verified whether there were any conflicting transactions. If there were
+      conflicts, the transaction is aborted, otherwise it is committed. This
+      is a so-called optimistic approach. There is a prototype of the Intel C++
+      Compiler available that supports STM. Research about the addition of
+      STM support to GCC is ongoing.
+    </para>
+  </listitem>
+</itemizedlist>
+</para>
+
+<para>
+DRD supports any combination of multithreaded programming paradigms as
+long as the implementation of these paradigms is based on the POSIX
+threads primitives. DRD however does not support programs that use
+e.g. Linux' futexes directly. Attempts to analyze such programs with
+DRD will cause DRD to report many false positives.
+</para>
+
+</sect2>
+
+
+<sect2 id="drd-manual.pthreads-model" xreflabel="Pthreads-model">
+<title>POSIX Threads Programming Model</title>
+
+<para>
+POSIX threads, also known as Pthreads, is the most widely available
+threading library on Unix systems.
+</para>
+
+<para>
+The POSIX threads programming model is based on the following abstractions:
+<itemizedlist>
+  <listitem>
+    <para>
+      A shared address space. All threads running within the same
+      process share the same address space. All data, whether shared or
+      not, is identified by its address.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      Regular load and store operations, which allow to read values
+      from or to write values to the memory shared by all threads
+      running in the same process.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      Atomic store and load-modify-store operations. While these are
+      not mentioned in the POSIX threads standard, most
+      microprocessors support atomic memory operations.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      Threads. Each thread represents a concurrent activity.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      Synchronization objects and operations on these synchronization
+      objects. The following types of synchronization objects have been
+      defined in the POSIX threads standard: mutexes, condition variables,
+      semaphores, reader-writer synchronization objects, barriers and
+      spinlocks.
+    </para>
+  </listitem>
+</itemizedlist>
+</para>
+
+<para>
+Which source code statements generate which memory accesses depends on
+the <emphasis>memory model</emphasis> of the programming language being
+used. There is not yet a definitive memory model for the C and C++
+languages. For a draft memory model, see also the document
+<ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2338.html">
+WG21/N2338: Concurrency memory model compiler consequences</ulink>.
+</para>
+
+<para>
+For more information about POSIX threads, see also the Single UNIX
+Specification version 3, also known as
+<ulink url="http://www.opengroup.org/onlinepubs/000095399/idx/threads.html">
+IEEE Std 1003.1</ulink>.
+</para>
+
+</sect2>
+
+
+<sect2 id="drd-manual.mt-problems" xreflabel="MT-Problems">
+<title>Multithreaded Programming Problems</title>
+
+<para>
+Depending on which multithreading paradigm is being used in a program,
+one or more of the following problems can occur:
+<itemizedlist>
+  <listitem>
+    <para>
+      Data races. One or more threads access the same memory location without
+      sufficient locking. Most but not all data races are programming errors
+      and are the cause of subtle and hard-to-find bugs.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      Lock contention. One thread blocks the progress of one or more other
+      threads by holding a lock too long.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      Improper use of the POSIX threads API. Most implementations of the POSIX
+      threads API have been optimized for runtime speed. Such implementations
+      will not complain on certain errors, e.g. when a mutex is being unlocked
+      by another thread than the thread that obtained a lock on the mutex.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      Deadlock. A deadlock occurs when two or more threads wait for
+      each other indefinitely.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      False sharing. If threads that run on different processor cores
+      access different variables located in the same cache line
+      frequently, this will slow down the involved threads a lot due
+      to frequent exchange of cache lines.
+    </para>
+  </listitem>
+</itemizedlist>
+</para>
+
+<para>
+Although the likelihood of the occurrence of data races can be reduced
+through a disciplined programming style, a tool for automatic
+detection of data races is a necessity when developing multithreaded
+software. DRD can detect these, as well as lock contention and
+improper use of the POSIX threads API.
+</para>
+
+</sect2>
+
+
+<sect2 id="drd-manual.data-race-detection" xreflabel="data-race-detection">
+<title>Data Race Detection</title>
+
+<para>
+The result of load and store operations performed by a multithreaded program
+depends on the order in which memory operations are performed. This order is
+determined by:
+<orderedlist>
+  <listitem>
+    <para>
+      All memory operations performed by the same thread are performed in
+      <emphasis>program order</emphasis>, that is, the order determined by the
+      program source code and the results of previous load operations.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      Synchronization operations determine certain ordering constraints on
+      memory operations performed by different threads. These ordering
+      constraints are called the <emphasis>synchronization order</emphasis>.
+    </para>
+  </listitem>
+</orderedlist>
+The combination of program order and synchronization order is called the
+<emphasis>happens-before relationship</emphasis>. This concept was first
+defined by S. Adve et al in the paper <emphasis>Detecting data races on weak
+memory systems</emphasis>, ACM SIGARCH Computer Architecture News, v.19 n.3,
+p.234-243, May 1991.
+</para>
+
+<para>
+Two memory operations <emphasis>conflict</emphasis> if both operations are
+performed by different threads, refer to the same memory location and at least
+one of them is a store operation.
+</para>
+
+<para>
+A multithreaded program is <emphasis>data-race free</emphasis> if all
+conflicting memory accesses are ordered by synchronization
+operations.
+</para>
+
+<para>
+A well known way to ensure that a multithreaded program is data-race
+free is to ensure that a locking discipline is followed. It is e.g.
+possible to associate a mutex with each shared data item, and to hold
+a lock on the associated mutex while the shared data is accessed.
+</para>
+
+<para>
+All programs that follow a locking discipline are data-race free, but not all
+data-race free programs follow a locking discipline. There exist multithreaded
+programs where access to shared data is arbitrated via condition variables,
+semaphores or barriers. As an example, a certain class of HPC applications
+consists of a sequence of computation steps separated in time by barriers, and
+where these barriers are the only means of synchronization. Although there are
+many conflicting memory accesses in such applications and although such
+applications do not make use mutexes, most of these applications do not
+contain data races.
+</para>
+
+<para>
+There exist two different approaches for verifying the correctness of
+multithreaded programs at runtime. The approach of the so-called Eraser
+algorithm is to verify whether all shared memory accesses follow a consistent
+locking strategy. And the happens-before data race detectors verify directly
+whether all interthread memory accesses are ordered by synchronization
+operations. While the last approach is more complex to implement, and while it
+is more sensitive to OS scheduling, it is a general approach that works for
+all classes of multithreaded programs. An important advantage of
+happens-before data race detectors is that these do not report any false
+positives.
+</para>
+
+<para>
+DRD is based on the happens-before algorithm.
+</para>
+
+</sect2>
+
+
+</sect1>
+
+
+<sect1 id="drd-manual.using-drd" xreflabel="Using DRD">
+<title>Using DRD</title>
+
+<sect2 id="drd-manual.options" xreflabel="DRD Command-line Options">
+<title>DRD Command-line Options</title>
+
+<para>The following command-line options are available for controlling the
+behavior of the DRD tool itself:</para>
+
+<!-- start of xi:include in the manpage -->
+<variablelist id="drd.opts.list">
+  <varlistentry>
+    <term>
+      <option><![CDATA[--check-stack-var=<yes|no> [default: no]]]></option>
+    </term>
+    <listitem>
+      <para>
+        Controls whether DRD detects data races on stack
+        variables. Verifying stack variables is disabled by default because
+        most programs do not share stack variables over threads.
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+      <option><![CDATA[--exclusive-threshold=<n> [default: off]]]></option>
+    </term>
+    <listitem>
+      <para>
+        Print an error message if any mutex or writer lock has been
+        held longer than the time specified in milliseconds. This
+        option enables the detection of lock contention.
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+      <option>
+        <![CDATA[--first-race-only=<yes|no> [default: no]]]>
+      </option>
+    </term>
+    <listitem>
+      <para>
+        Whether to report only the first data race that has been detected on a
+        memory location or all data races that have been detected on a memory
+        location.
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+      <option>
+        <![CDATA[--free-is-write=<yes|no> [default: no]]]>
+      </option>
+    </term>
+    <listitem>
+      <para>
+        Whether to report accessing freed memory as a race. Helps to detect
+        memory accesses that occur after memory has been freed but might cause
+        DRD to run slightly slower.
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+      <option>
+        <![CDATA[--report-signal-unlocked=<yes|no> [default: yes]]]>
+      </option>
+    </term>
+    <listitem>
+      <para>
+        Whether to report calls to
+        <function>pthread_cond_signal</function> and
+        <function>pthread_cond_broadcast</function> where the mutex
+        associated with the signal through
+        <function>pthread_cond_wait</function> or
+        <function>pthread_cond_timed_wait</function>is not locked at
+        the time the signal is sent.  Sending a signal without holding
+        a lock on the associated mutex is a common programming error
+        which can cause subtle race conditions and unpredictable
+        behavior. There exist some uncommon synchronization patterns
+        however where it is safe to send a signal without holding a
+        lock on the associated mutex.
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+      <option><![CDATA[--segment-merging=<yes|no> [default: yes]]]></option>
+    </term>
+    <listitem>
+      <para>
+        Controls segment merging. Segment merging is an algorithm to
+        limit memory usage of the data race detection
+        algorithm. Disabling segment merging may improve the accuracy
+        of the so-called 'other segments' displayed in race reports
+        but can also trigger an out of memory error.
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+      <option><![CDATA[--segment-merging-interval=<n> [default: 10]]]></option>
+    </term>
+    <listitem>
+      <para>
+        Perform segment merging only after the specified number of new
+        segments have been created. This is an advanced configuration option
+        that allows to choose whether to minimize DRD's memory usage by
+        choosing a low value or to let DRD run faster by choosing a slightly
+        higher value. The optimal value for this parameter depends on the
+        program being analyzed. The default value works well for most programs.
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+      <option><![CDATA[--shared-threshold=<n> [default: off]]]></option>
+    </term>
+    <listitem>
+      <para>
+        Print an error message if a reader lock has been held longer
+        than the specified time (in milliseconds). This option enables
+        the detection of lock contention.
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+      <option><![CDATA[--show-confl-seg=<yes|no> [default: yes]]]></option>
+    </term>
+    <listitem>
+      <para>
+         Show conflicting segments in race reports. Since this
+         information can help to find the cause of a data race, this
+         option is enabled by default. Disabling this option makes the
+         output of DRD more compact.
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+      <option><![CDATA[--show-stack-usage=<yes|no> [default: no]]]></option>
+    </term>
+    <listitem>
+      <para>
+        Print stack usage at thread exit time. When a program creates a large
+        number of threads it becomes important to limit the amount of virtual
+        memory allocated for thread stacks. This option makes it possible to
+        observe how much stack memory has been used by each thread of the the
+        client program. Note: the DRD tool itself allocates some temporary
+        data on the client thread stack. The space necessary for this
+        temporary data must be allocated by the client program when it
+        allocates stack memory, but is not included in stack usage reported by
+        DRD.
+      </para>
+    </listitem>
+  </varlistentry>
+</variablelist>
+<!-- end of xi:include in the manpage -->
+
+<!-- start of xi:include in the manpage -->
+<para>
+The following options are available for monitoring the behavior of the
+client program:
+</para>
+
+<variablelist id="drd.debugopts.list">
+  <varlistentry>
+    <term>
+      <option><![CDATA[--trace-addr=<address> [default: none]]]></option>
+    </term>
+    <listitem>
+      <para>
+        Trace all load and store activity for the specified
+        address. This option may be specified more than once.
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+      <option><![CDATA[--trace-alloc=<yes|no> [default: no]]]></option>
+    </term>
+    <listitem>
+      <para>
+        Trace all memory allocations and deallocations. May produce a huge
+        amount of output.
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+      <option><![CDATA[--trace-barrier=<yes|no> [default: no]]]></option>
+    </term>
+    <listitem>
+      <para>
+        Trace all barrier activity.
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+      <option><![CDATA[--trace-cond=<yes|no> [default: no]]]></option>
+    </term>
+    <listitem>
+      <para>
+        Trace all condition variable activity.
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+      <option><![CDATA[--trace-fork-join=<yes|no> [default: no]]]></option>
+    </term>
+    <listitem>
+      <para>
+        Trace all thread creation and all thread termination events.
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+      <option><![CDATA[--trace-mutex=<yes|no> [default: no]]]></option>
+    </term>
+    <listitem>
+      <para>
+        Trace all mutex activity.
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+      <option><![CDATA[--trace-rwlock=<yes|no> [default: no]]]></option>
+    </term>
+    <listitem>
+      <para>
+         Trace all reader-writer lock activity.
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+      <option><![CDATA[--trace-semaphore=<yes|no> [default: no]]]></option>
+    </term>
+    <listitem>
+      <para>
+        Trace all semaphore activity.
+      </para>
+    </listitem>
+  </varlistentry>
+</variablelist>
+<!-- end of xi:include in the manpage -->
+
+</sect2>
+
+
+<sect2 id="drd-manual.data-races" xreflabel="Data Races">
+<title>Detected Errors: Data Races</title>
+
+<para>
+DRD prints a message every time it detects a data race. Please keep
+the following in mind when interpreting DRD's output:
+<itemizedlist>
+  <listitem>
+    <para>
+      Every thread is assigned a <emphasis>thread ID</emphasis> by the DRD
+      tool. A thread ID is a number. Thread ID's start at one and are never
+      recycled.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The term <emphasis>segment</emphasis> refers to a consecutive
+      sequence of load, store and synchronization operations, all
+      issued by the same thread. A segment always starts and ends at a
+      synchronization operation. Data race analysis is performed
+      between segments instead of between individual load and store
+      operations because of performance reasons.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      There are always at least two memory accesses involved in a data
+      race. Memory accesses involved in a data race are called
+      <emphasis>conflicting memory accesses</emphasis>. DRD prints a
+      report for each memory access that conflicts with a past memory
+      access.
+    </para>
+  </listitem>
+</itemizedlist>
+</para>
+
+<para>
+Below you can find an example of a message printed by DRD when it
+detects a data race:
+</para>
+<programlisting><![CDATA[
+$ valgrind --tool=drd --read-var-info=yes drd/tests/rwlock_race
+...
+==9466== Thread 3:
+==9466== Conflicting load by thread 3 at 0x006020b8 size 4
+==9466==    at 0x400B6C: thread_func (rwlock_race.c:29)
+==9466==    by 0x4C291DF: vg_thread_wrapper (drd_pthread_intercepts.c:186)
+==9466==    by 0x4E3403F: start_thread (in /lib64/libpthread-2.8.so)
+==9466==    by 0x53250CC: clone (in /lib64/libc-2.8.so)
+==9466== Location 0x6020b8 is 0 bytes inside local var "s_racy"
+==9466== declared at rwlock_race.c:18, in frame #0 of thread 3
+==9466== Other segment start (thread 2)
+==9466==    at 0x4C2847D: pthread_rwlock_rdlock* (drd_pthread_intercepts.c:813)
+==9466==    by 0x400B6B: thread_func (rwlock_race.c:28)
+==9466==    by 0x4C291DF: vg_thread_wrapper (drd_pthread_intercepts.c:186)
+==9466==    by 0x4E3403F: start_thread (in /lib64/libpthread-2.8.so)
+==9466==    by 0x53250CC: clone (in /lib64/libc-2.8.so)
+==9466== Other segment end (thread 2)
+==9466==    at 0x4C28B54: pthread_rwlock_unlock* (drd_pthread_intercepts.c:912)
+==9466==    by 0x400B84: thread_func (rwlock_race.c:30)
+==9466==    by 0x4C291DF: vg_thread_wrapper (drd_pthread_intercepts.c:186)
+==9466==    by 0x4E3403F: start_thread (in /lib64/libpthread-2.8.so)
+==9466==    by 0x53250CC: clone (in /lib64/libc-2.8.so)
+...
+]]></programlisting>
+
+<para>
+The above report has the following meaning:
+<itemizedlist>
+  <listitem>
+    <para>
+      The number in the column on the left is the process ID of the
+      process being analyzed by DRD.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The first line ("Thread 3") tells you the thread ID for
+      the thread in which context the data race has been detected.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The next line tells which kind of operation was performed (load or
+      store) and by which thread. On the same line the start address and the
+      number of bytes involved in the conflicting access are also displayed.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      Next, the call stack of the conflicting access is displayed. If
+      your program has been compiled with debug information
+      (<option>-g</option>), this call stack will include file names and
+      line numbers. The two
+      bottommost frames in this call stack (<function>clone</function>
+      and <function>start_thread</function>) show how the NPTL starts
+      a thread. The third frame
+      (<function>vg_thread_wrapper</function>) is added by DRD. The
+      fourth frame (<function>thread_func</function>) is the first
+      interesting line because it shows the thread entry point, that
+      is the function that has been passed as the third argument to
+      <function>pthread_create</function>.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      Next, the allocation context for the conflicting address is
+      displayed. For dynamically allocated data the allocation call
+      stack is shown. For static variables and stack variables the
+      allocation context is only shown when the option
+      <option>--read-var-info=yes</option> has been
+      specified. Otherwise DRD will print <computeroutput>Allocation
+      context: unknown</computeroutput>.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      A conflicting access involves at least two memory accesses. For
+      one of these accesses an exact call stack is displayed, and for
+      the other accesses an approximate call stack is displayed,
+      namely the start and the end of the segments of the other
+      accesses. This information can be interpreted as follows:
+      <orderedlist>
+        <listitem>
+          <para>
+            Start at the bottom of both call stacks, and count the
+            number stack frames with identical function name, file
+            name and line number. In the above example the three
+            bottommost frames are identical
+            (<function>clone</function>,
+            <function>start_thread</function> and
+            <function>vg_thread_wrapper</function>).
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+            The next higher stack frame in both call stacks now tells
+            you between in which source code region the other memory
+            access happened. The above output tells that the other
+            memory access involved in the data race happened between
+            source code lines 28 and 30 in file
+            <computeroutput>rwlock_race.c</computeroutput>.
+          </para>
+        </listitem>
+      </orderedlist>
+    </para>
+  </listitem>
+</itemizedlist>
+</para>
+
+</sect2>
+
+
+<sect2 id="drd-manual.lock-contention" xreflabel="Lock Contention">
+<title>Detected Errors: Lock Contention</title>
+
+<para>
+Threads must be able to make progress without being blocked for too long by
+other threads. Sometimes a thread has to wait until a mutex or reader-writer
+synchronization object is unlocked by another thread. This is called
+<emphasis>lock contention</emphasis>.
+</para>
+
+<para>
+Lock contention causes delays. Such delays should be as short as
+possible. The two command line options
+<literal>--exclusive-threshold=&lt;n&gt;</literal> and
+<literal>--shared-threshold=&lt;n&gt;</literal> make it possible to
+detect excessive lock contention by making DRD report any lock that
+has been held longer than the specified threshold. An example:
+</para>
+<programlisting><![CDATA[
+$ valgrind --tool=drd --exclusive-threshold=10 drd/tests/hold_lock -i 500
+...
+==10668== Acquired at:
+==10668==    at 0x4C267C8: pthread_mutex_lock (drd_pthread_intercepts.c:395)
+==10668==    by 0x400D92: main (hold_lock.c:51)
+==10668== Lock on mutex 0x7fefffd50 was held during 503 ms (threshold: 10 ms).
+==10668==    at 0x4C26ADA: pthread_mutex_unlock (drd_pthread_intercepts.c:441)
+==10668==    by 0x400DB5: main (hold_lock.c:55)
+...
+]]></programlisting>
+
+<para>
+The <literal>hold_lock</literal> test program holds a lock as long as
+specified by the <literal>-i</literal> (interval) argument. The DRD
+output reports that the lock acquired at line 51 in source file
+<literal>hold_lock.c</literal> and released at line 55 was held during
+503 ms, while a threshold of 10 ms was specified to DRD.
+</para>
+
+</sect2>
+
+
+<sect2 id="drd-manual.api-checks" xreflabel="API Checks">
+<title>Detected Errors: Misuse of the POSIX threads API</title>
+
+<para>
+  DRD is able to detect and report the following misuses of the POSIX
+  threads API:
+  <itemizedlist>
+    <listitem>
+      <para>
+        Passing the address of one type of synchronization object
+        (e.g. a mutex) to a POSIX API call that expects a pointer to
+        another type of synchronization object (e.g. a condition
+        variable).
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        Attempts to unlock a mutex that has not been locked.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        Attempts to unlock a mutex that was locked by another thread.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        Attempts to lock a mutex of type
+        <literal>PTHREAD_MUTEX_NORMAL</literal> or a spinlock
+        recursively.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        Destruction or deallocation of a locked mutex.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        Sending a signal to a condition variable while no lock is held
+        on the mutex associated with the condition variable.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        Calling <function>pthread_cond_wait</function> on a mutex
+        that is not locked, that is locked by another thread or that
+        has been locked recursively.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        Associating two different mutexes with a condition variable
+        through <function>pthread_cond_wait</function>.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        Destruction or deallocation of a condition variable that is
+        being waited upon.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        Destruction or deallocation of a locked reader-writer synchronization
+        object.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        Attempts to unlock a reader-writer synchronization object that was not
+        locked by the calling thread.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        Attempts to recursively lock a reader-writer synchronization object
+        exclusively.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        Attempts to pass the address of a user-defined reader-writer
+        synchronization object to a POSIX threads function.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        Attempts to pass the address of a POSIX reader-writer synchronization
+        object to one of the annotations for user-defined reader-writer
+        synchronization objects.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        Reinitialization of a mutex, condition variable, reader-writer
+        lock, semaphore or barrier.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        Destruction or deallocation of a semaphore or barrier that is
+        being waited upon.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        Missing synchronization between barrier wait and barrier destruction.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        Exiting a thread without first unlocking the spinlocks, mutexes or
+        reader-writer synchronization objects that were locked by that thread.
+      </para>
+    </listitem>
+    <listitem>
+      <para>
+        Passing an invalid thread ID to <function>pthread_join</function>
+        or <function>pthread_cancel</function>.
+      </para>
+    </listitem>
+  </itemizedlist>
+</para>
+
+</sect2>
+
+
+<sect2 id="drd-manual.clientreqs" xreflabel="Client requests">
+<title>Client Requests</title>
+
+<para>
+Just as for other Valgrind tools it is possible to let a client program
+interact with the DRD tool through client requests. In addition to the
+client requests several macros have been defined that allow to use the
+client requests in a convenient way.
+</para>
+
+<para>
+The interface between client programs and the DRD tool is defined in
+the header file <literal>&lt;valgrind/drd.h&gt;</literal>. The
+available macros and client requests are:
+<itemizedlist>
+  <listitem>
+    <para>
+      The macro <literal>DRD_GET_VALGRIND_THREADID</literal> and the
+      corresponding client
+      request <varname>VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID</varname>.
+      Query the thread ID that has been assigned by the Valgrind core to the
+      thread executing this client request. Valgrind's thread ID's start at
+      one and are recycled in case a thread stops.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>DRD_GET_DRD_THREADID</literal> and the corresponding
+      client request <varname>VG_USERREQ__DRD_GET_DRD_THREAD_ID</varname>.
+      Query the thread ID that has been assigned by DRD to the thread
+      executing this client request. These are the thread ID's reported by DRD
+      in data race reports and in trace messages. DRD's thread ID's start at
+      one and are never recycled.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macros <literal>DRD_IGNORE_VAR(x)</literal>,
+      <literal>ANNOTATE_TRACE_MEMORY(&amp;x)</literal> and the corresponding
+      client request <varname>VG_USERREQ__DRD_START_SUPPRESSION</varname>. Some
+      applications contain intentional races. There exist e.g. applications
+      where the same value is assigned to a shared variable from two different
+      threads. It may be more convenient to suppress such races than to solve
+      these. This client request allows to suppress such races.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>DRD_STOP_IGNORING_VAR(x)</literal> and the
+      corresponding client request
+      <varname>VG_USERREQ__DRD_FINISH_SUPPRESSION</varname>. Tell DRD
+      to no longer ignore data races for the address range that was suppressed
+      either via the macro <literal>DRD_IGNORE_VAR(x)</literal> or via the
+      client request <varname>VG_USERREQ__DRD_START_SUPPRESSION</varname>.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>DRD_TRACE_VAR(x)</literal>. Trace all load and store
+      activity for the address range starting at <literal>&amp;x</literal> and
+      occupying <literal>sizeof(x)</literal> bytes. When DRD reports a data
+      race on a specified variable, and it's not immediately clear which
+      source code statements triggered the conflicting accesses, it can be
+      very helpful to trace all activity on the offending memory location.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_TRACE_MEMORY(&amp;x)</literal>. Trace all
+      load and store activity that touches at least the single byte at the
+      address <literal>&amp;x</literal>.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The client request <varname>VG_USERREQ__DRD_START_TRACE_ADDR</varname>,
+      which allows to trace all load and store activity for the specified
+      address range.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The client
+      request <varname>VG_USERREQ__DRD_STOP_TRACE_ADDR</varname>. Do no longer
+      trace load and store activity for the specified address range.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_HAPPENS_BEFORE(addr)</literal> tells DRD to
+      insert a mark. Insert this macro just after an access to the variable at
+      the specified address has been performed.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_HAPPENS_AFTER(addr)</literal> tells DRD that
+      the next access to the variable at the specified address should be
+      considered to have happened after the access just before the latest
+      <literal>ANNOTATE_HAPPENS_BEFORE(addr)</literal> annotation that
+      references the same variable. The purpose of these two macros is to tell
+      DRD about the order of inter-thread memory accesses implemented via
+      atomic memory operations. See
+      also <literal>drd/tests/annotate_smart_pointer.cpp</literal> for an
+      example.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_RWLOCK_CREATE(rwlock)</literal> tells DRD
+      that the object at address <literal>rwlock</literal> is a
+      reader-writer synchronization object that is not a
+      <literal>pthread_rwlock_t</literal> synchronization object.  See
+      also <literal>drd/tests/annotate_rwlock.c</literal> for an example.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_RWLOCK_DESTROY(rwlock)</literal> tells DRD
+      that the reader-writer synchronization object at
+      address <literal>rwlock</literal> has been destroyed.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_WRITERLOCK_ACQUIRED(rwlock)</literal> tells
+      DRD that a writer lock has been acquired on the reader-writer
+      synchronization object at address <literal>rwlock</literal>.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_READERLOCK_ACQUIRED(rwlock)</literal> tells
+      DRD that a reader lock has been acquired on the reader-writer
+      synchronization object at address <literal>rwlock</literal>.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_RWLOCK_ACQUIRED(rwlock, is_w)</literal>
+      tells DRD that a writer lock (when <literal>is_w != 0</literal>) or that
+      a reader lock (when <literal>is_w == 0</literal>) has been acquired on
+      the reader-writer synchronization object at
+      address <literal>rwlock</literal>.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_WRITERLOCK_RELEASED(rwlock)</literal> tells
+      DRD that a writer lock has been released on the reader-writer
+      synchronization object at address <literal>rwlock</literal>.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_READERLOCK_RELEASED(rwlock)</literal> tells
+      DRD that a reader lock has been released on the reader-writer
+      synchronization object at address <literal>rwlock</literal>.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_RWLOCK_RELEASED(rwlock, is_w)</literal>
+      tells DRD that a writer lock (when <literal>is_w != 0</literal>) or that
+      a reader lock (when <literal>is_w == 0</literal>) has been released on
+      the reader-writer synchronization object at
+      address <literal>rwlock</literal>.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_BARRIER_INIT(barrier, count,
+      reinitialization_allowed)</literal> tells DRD that a new barrier object
+      at the address <literal>barrier</literal> has been initialized,
+      that <literal>count</literal> threads participate in each barrier and
+      also whether or not barrier reinitialization without intervening
+      destruction should be reported as an error. See
+      also <literal>drd/tests/annotate_barrier.c</literal> for an example.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_BARRIER_DESTROY(barrier)</literal>
+      tells DRD that a barrier object is about to be destroyed.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_BARRIER_WAIT_BEFORE(barrier)</literal>
+      tells DRD that waiting for a barrier will start.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_BARRIER_WAIT_AFTER(barrier)</literal>
+      tells DRD that waiting for a barrier has finished.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_BENIGN_RACE_SIZED(addr, size,
+      descr)</literal> tells DRD that any races detected on the specified
+      address are benign and hence should not be
+      reported. The <literal>descr</literal> argument is ignored but can be
+      used to document why data races on <literal>addr</literal> are benign.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_BENIGN_RACE_STATIC(var, descr)</literal>
+      tells DRD that any races detected on the specified static variable are
+      benign and hence should not be reported. The <literal>descr</literal>
+      argument is ignored but can be used to document why data races
+      on <literal>var</literal> are benign. Note: this macro can only be
+      used in C++ programs and not in C programs.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_IGNORE_READS_BEGIN</literal> tells
+      DRD to ignore all memory loads performed by the current thread.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_IGNORE_READS_END</literal> tells
+      DRD to stop ignoring the memory loads performed by the current thread.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_IGNORE_WRITES_BEGIN</literal> tells
+      DRD to ignore all memory stores performed by the current thread.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_IGNORE_WRITES_END</literal> tells
+      DRD to stop ignoring the memory stores performed by the current thread.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN</literal> tells
+      DRD to ignore all memory accesses performed by the current thread.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_IGNORE_READS_AND_WRITES_END</literal> tells
+      DRD to stop ignoring the memory accesses performed by the current thread.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_NEW_MEMORY(addr, size)</literal> tells
+      DRD that the specified memory range has been allocated by a custom
+      memory allocator in the client program and that the client program
+      will start using this memory range.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macro <literal>ANNOTATE_THREAD_NAME(name)</literal> tells DRD to
+      associate the specified name with the current thread and to include this
+      name in the error messages printed by DRD.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The macros <literal>VALGRIND_MALLOCLIKE_BLOCK</literal> and
+      <literal>VALGRIND_FREELIKE_BLOCK</literal> from the Valgrind core are
+      implemented;  they are described in 
+      <xref linkend="manual-core-adv.clientreq"/>.
+    </para>
+  </listitem>
+</itemizedlist>
+</para>
+
+<para>
+Note: if you compiled Valgrind yourself, the header file
+<literal>&lt;valgrind/drd.h&gt;</literal> will have been installed in
+the directory <literal>/usr/include</literal> by the command
+<literal>make install</literal>. If you obtained Valgrind by
+installing it as a package however, you will probably have to install
+another package with a name like <literal>valgrind-devel</literal>
+before Valgrind's header files are available.
+</para>
+
+</sect2>
+
+
+<sect2 id="drd-manual.gnome" xreflabel="GNOME">
+<title>Debugging GNOME Programs</title>
+
+<para>
+GNOME applications use the threading primitives provided by the
+<computeroutput>glib</computeroutput> and
+<computeroutput>gthread</computeroutput> libraries. These libraries
+are built on top of POSIX threads, and hence are directly supported by
+DRD. Please keep in mind that you have to call
+<function>g_thread_init</function> before creating any threads, or
+DRD will report several data races on glib functions. See also the
+<ulink
+url="http://library.gnome.org/devel/glib/stable/glib-Threads.html">GLib
+Reference Manual</ulink> for more information about
+<function>g_thread_init</function>.
+</para>
+
+<para>
+One of the many facilities provided by the <literal>glib</literal>
+library is a block allocator, called <literal>g_slice</literal>. You
+have to disable this block allocator when using DRD by adding the
+following to the shell environment variables:
+<literal>G_SLICE=always-malloc</literal>. See also the <ulink
+url="http://library.gnome.org/devel/glib/stable/glib-Memory-Slices.html">GLib
+Reference Manual</ulink> for more information.
+</para>
+
+</sect2>
+
+
+<sect2 id="drd-manual.qt" xreflabel="Qt">
+<title>Debugging Qt Programs</title>
+
+<para>
+The Qt library is the GUI library used by the KDE project.  Currently
+there are two versions of the Qt library in use: Qt3 by KDE 3 and Qt4
+by KDE 4. If possible, use Qt4 instead of Qt3. Qt3 is no longer
+supported, and there are known problems with multithreading support in
+Qt3. As an example, using QString objects in more than one thread will
+trigger race reports (this has been confirmed by Trolltech -- see also
+Trolltech task <ulink
+url="http://trolltech.com/developer/task-tracker/index_html">#206152</ulink>).
+</para>
+
+<para>
+Qt4 applications are supported by DRD, but only if the
+<literal>libqt4-debuginfo</literal> package has been installed. Some
+of the synchronization and threading primitives in Qt4 bypass the
+POSIX threads library, and DRD can only intercept these if symbol
+information for the Qt4 library is available. DRD won't tell you if it
+has not been able to load the Qt4 debug information, but a huge number
+of data races will be reported on data protected via
+<literal>QMutex</literal> objects.
+</para>
+
+</sect2>
+
+
+<sect2 id="drd-manual.boost.thread" xreflabel="Boost.Thread">
+<title>Debugging Boost.Thread Programs</title>
+
+<para>
+The Boost.Thread library is the threading library included with the
+cross-platform Boost Libraries. This threading library is an early
+implementation of the upcoming C++0x threading library.
+</para>
+
+<para>
+Applications that use the Boost.Thread library should run fine under DRD.
+</para>
+
+<para>
+More information about Boost.Thread can be found here:
+<itemizedlist>
+  <listitem>
+    <para>
+      Anthony Williams, <ulink
+      url="http://www.boost.org/doc/libs/1_37_0/doc/html/thread.html">Boost.Thread</ulink>
+      Library Documentation, Boost website, 2007.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      Anthony Williams, <ulink
+      url="http://www.ddj.com/cpp/211600441">What's New in Boost
+      Threads?</ulink>, Recent changes to the Boost Thread library,
+      Dr. Dobbs Magazine, October 2008.
+    </para>
+  </listitem>
+</itemizedlist>
+</para>
+
+</sect2>
+
+
+<sect2 id="drd-manual.openmp" xreflabel="OpenMP">
+<title>Debugging OpenMP Programs</title>
+
+<para>
+OpenMP stands for <emphasis>Open Multi-Processing</emphasis>. The OpenMP
+standard consists of a set of compiler directives for C, C++ and Fortran
+programs that allows a compiler to transform a sequential program into a
+parallel program. OpenMP is well suited for HPC applications and allows to
+work at a higher level compared to direct use of the POSIX threads API. While
+OpenMP ensures that the POSIX API is used correctly, OpenMP programs can still
+contain data races. So it definitely makes sense to verify OpenMP programs
+with a thread checking tool.
+</para>
+
+<para>
+DRD supports OpenMP shared-memory programs generated by GCC. GCC
+supports OpenMP since version 4.2.0.  GCC's runtime support
+for OpenMP programs is provided by a library called
+<literal>libgomp</literal>. The synchronization primitives implemented
+in this library use Linux' futex system call directly, unless the
+library has been configured with the
+<literal>--disable-linux-futex</literal> option. DRD only supports
+libgomp libraries that have been configured with this option and in
+which symbol information is present. For most Linux distributions this
+means that you will have to recompile GCC. See also the script
+<literal>drd/scripts/download-and-build-gcc</literal> in the
+Valgrind source tree for an example of how to compile GCC. You will
+also have to make sure that the newly compiled
+<literal>libgomp.so</literal> library is loaded when OpenMP programs
+are started. This is possible by adding a line similar to the
+following to your shell startup script:
+</para>
+<programlisting><![CDATA[
+export LD_LIBRARY_PATH=~/gcc-4.4.0/lib64:~/gcc-4.4.0/lib:
+]]></programlisting>
+
+<para>
+As an example, the test OpenMP test program
+<literal>drd/tests/omp_matinv</literal> triggers a data race
+when the option -r has been specified on the command line. The data
+race is triggered by the following code:
+</para>
+<programlisting><![CDATA[
+#pragma omp parallel for private(j)
+for (j = 0; j < rows; j++)
+{
+  if (i != j)
+  {
+    const elem_t factor = a[j * cols + i];
+    for (k = 0; k < cols; k++)
+    {
+      a[j * cols + k] -= a[i * cols + k] * factor;
+    }
+  }
+}
+]]></programlisting>
+
+<para>
+The above code is racy because the variable <literal>k</literal> has
+not been declared private. DRD will print the following error message
+for the above code:
+</para>
+<programlisting><![CDATA[
+$ valgrind --tool=drd --check-stack-var=yes --read-var-info=yes drd/tests/omp_matinv 3 -t 2 -r
+...
+Conflicting store by thread 1/1 at 0x7fefffbc4 size 4
+   at 0x4014A0: gj.omp_fn.0 (omp_matinv.c:203)
+   by 0x401211: gj (omp_matinv.c:159)
+   by 0x40166A: invert_matrix (omp_matinv.c:238)
+   by 0x4019B4: main (omp_matinv.c:316)
+Location 0x7fefffbc4 is 0 bytes inside local var "k"
+declared at omp_matinv.c:160, in frame #0 of thread 1
+...
+]]></programlisting>
+<para>
+In the above output the function name <function>gj.omp_fn.0</function>
+has been generated by GCC from the function name
+<function>gj</function>. The allocation context information shows that the
+data race has been caused by modifying the variable <literal>k</literal>.
+</para>
+
+<para>
+Note: for GCC versions before 4.4.0, no allocation context information is
+shown. With these GCC versions the most usable information in the above output
+is the source file name and the line number where the data race has been
+detected (<literal>omp_matinv.c:203</literal>).
+</para>
+
+<para>
+For more information about OpenMP, see also 
+<ulink url="http://openmp.org/">openmp.org</ulink>.
+</para>
+
+</sect2>
+
+
+<sect2 id="drd-manual.cust-mem-alloc" xreflabel="Custom Memory Allocators">
+<title>DRD and Custom Memory Allocators</title>
+
+<para>
+DRD tracks all memory allocation events that happen via the
+standard memory allocation and deallocation functions
+(<function>malloc</function>, <function>free</function>,
+<function>new</function> and <function>delete</function>), via entry
+and exit of stack frames or that have been annotated with Valgrind's
+memory pool client requests. DRD uses memory allocation and deallocation
+information for two purposes:
+<itemizedlist>
+  <listitem>
+    <para>
+      To know where the scope ends of POSIX objects that have not been
+      destroyed explicitly. It is e.g. not required by the POSIX
+      threads standard to call
+      <function>pthread_mutex_destroy</function> before freeing the
+      memory in which a mutex object resides.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      To know where the scope of variables ends. If e.g. heap memory
+      has been used by one thread, that thread frees that memory, and
+      another thread allocates and starts using that memory, no data
+      races must be reported for that memory.
+    </para>
+  </listitem>
+</itemizedlist>
+</para>
+
+<para>
+It is essential for correct operation of DRD that the tool knows about
+memory allocation and deallocation events. When analyzing a client program
+with DRD that uses a custom memory allocator, either instrument the custom
+memory allocator with the <literal>VALGRIND_MALLOCLIKE_BLOCK</literal>
+and <literal>VALGRIND_FREELIKE_BLOCK</literal> macros or disable the
+custom memory allocator.
+</para>
+
+<para>
+As an example, the GNU libstdc++ library can be configured
+to use standard memory allocation functions instead of memory pools by
+setting the environment variable
+<literal>GLIBCXX_FORCE_NEW</literal>. For more information, see also
+the <ulink
+url="http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt04ch11.html">libstdc++
+manual</ulink>.
+</para>
+
+</sect2>
+
+
+<sect2 id="drd-manual.drd-versus-memcheck" xreflabel="DRD Versus Memcheck">
+<title>DRD Versus Memcheck</title>
+
+<para>
+It is essential for correct operation of DRD that there are no memory
+errors such as dangling pointers in the client program. Which means that
+it is a good idea to make sure that your program is Memcheck-clean
+before you analyze it with DRD. It is possible however that some of
+the Memcheck reports are caused by data races. In this case it makes
+sense to run DRD before Memcheck.
+</para>
+
+<para>
+So which tool should be run first? In case both DRD and Memcheck
+complain about a program, a possible approach is to run both tools
+alternatingly and to fix as many errors as possible after each run of
+each tool until none of the two tools prints any more error messages.
+</para>
+
+</sect2>
+
+
+<sect2 id="drd-manual.resource-requirements" xreflabel="Resource Requirements">
+<title>Resource Requirements</title>
+
+<para>
+The requirements of DRD with regard to heap and stack memory and the
+effect on the execution time of client programs are as follows:
+<itemizedlist>
+  <listitem>
+    <para>
+      When running a program under DRD with default DRD options,
+      between 1.1 and 3.6 times more memory will be needed compared to
+      a native run of the client program. More memory will be needed
+      if loading debug information has been enabled
+      (<literal>--read-var-info=yes</literal>).
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      DRD allocates some of its temporary data structures on the stack
+      of the client program threads. This amount of data is limited to
+      1 - 2 KB. Make sure that thread stacks are sufficiently large.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      Most applications will run between 20 and 50 times slower under
+      DRD than a native single-threaded run. The slowdown will be most
+      noticeable for applications which perform frequent mutex lock /
+      unlock operations.
+    </para>
+  </listitem>
+</itemizedlist>
+</para>
+
+</sect2>
+
+
+<sect2 id="drd-manual.effective-use" xreflabel="Effective Use">
+<title>Hints and Tips for Effective Use of DRD</title>
+
+<para>
+The following information may be helpful when using DRD:
+<itemizedlist>
+  <listitem>
+    <para>
+      Make sure that debug information is present in the executable
+      being analyzed, such that DRD can print function name and line
+      number information in stack traces. Most compilers can be told
+      to include debug information via compiler option
+      <option>-g</option>.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      Compile with option <option>-O1</option> instead of
+      <option>-O0</option>. This will reduce the amount of generated
+      code, may reduce the amount of debug info and will speed up
+      DRD's processing of the client program. For more information,
+      see also <xref linkend="manual-core.started"/>.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      If DRD reports any errors on libraries that are part of your
+      Linux distribution like e.g. <literal>libc.so</literal> or
+      <literal>libstdc++.so</literal>, installing the debug packages
+      for these libraries will make the output of DRD a lot more
+      detailed.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      When using C++, do not send output from more than one thread to
+      <literal>std::cout</literal>. Doing so would not only
+      generate multiple data race reports, it could also result in
+      output from several threads getting mixed up.  Either use
+      <function>printf</function> or do the following:
+      <orderedlist>
+        <listitem>
+          <para>Derive a class from <literal>std::ostreambuf</literal>
+          and let that class send output line by line to
+          <literal>stdout</literal>. This will avoid that individual
+          lines of text produced by different threads get mixed
+          up.</para>
+        </listitem>
+        <listitem>
+          <para>Create one instance of <literal>std::ostream</literal>
+          for each thread. This makes stream formatting settings
+          thread-local. Pass a per-thread instance of the class
+          derived from <literal>std::ostreambuf</literal> to the
+          constructor of each instance. </para>
+        </listitem>
+        <listitem>
+          <para>Let each thread send its output to its own instance of
+          <literal>std::ostream</literal> instead of
+          <literal>std::cout</literal>.</para>
+        </listitem>
+      </orderedlist>
+    </para>
+  </listitem>
+</itemizedlist>
+</para>
+
+</sect2>
+
+
+</sect1>
+
+
+<sect1 id="drd-manual.Pthreads" xreflabel="Pthreads">
+<title>Using the POSIX Threads API Effectively</title>
+
+<sect2 id="drd-manual.mutex-types" xreflabel="mutex-types">
+<title>Mutex types</title>
+
+<para>
+The Single UNIX Specification version two defines the following four
+mutex types (see also the documentation of <ulink
+url="http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_mutexattr_settype.html"><function>pthread_mutexattr_settype</function></ulink>):
+<itemizedlist>
+  <listitem>
+    <para>
+      <emphasis>normal</emphasis>, which means that no error checking
+      is performed, and that the mutex is non-recursive.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      <emphasis>error checking</emphasis>, which means that the mutex
+      is non-recursive and that error checking is performed.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      <emphasis>recursive</emphasis>, which means that a mutex may be
+      locked recursively.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      <emphasis>default</emphasis>, which means that error checking
+      behavior is undefined, and that the behavior for recursive
+      locking is also undefined. Or: portable code must neither
+      trigger error conditions through the Pthreads API nor attempt to
+      lock a mutex of default type recursively.
+    </para>
+  </listitem>
+</itemizedlist>
+</para>
+
+<para>
+In complex applications it is not always clear from beforehand which
+mutex will be locked recursively and which mutex will not be locked
+recursively. Attempts lock a non-recursive mutex recursively will
+result in race conditions that are very hard to find without a thread
+checking tool. So either use the error checking mutex type and
+consistently check the return value of Pthread API mutex calls, or use
+the recursive mutex type.
+</para>
+
+</sect2>
+
+<sect2 id="drd-manual.condvar" xreflabel="condition-variables">
+<title>Condition variables</title>
+
+<para>
+A condition variable allows one thread to wake up one or more other
+threads. Condition variables are often used to notify one or more
+threads about state changes of shared data. Unfortunately it is very
+easy to introduce race conditions by using condition variables as the
+only means of state information propagation. A better approach is to
+let threads poll for changes of a state variable that is protected by
+a mutex, and to use condition variables only as a thread wakeup
+mechanism. See also the source file
+<computeroutput>drd/tests/monitor_example.cpp</computeroutput> for an
+example of how to implement this concept in C++. The monitor concept
+used in this example is a well known and very useful concept -- see
+also Wikipedia for more information about the <ulink
+url="http://en.wikipedia.org/wiki/Monitor_(synchronization)">monitor</ulink>
+concept.
+</para>
+
+</sect2>
+
+<sect2 id="drd-manual.pctw" xreflabel="pthread_cond_timedwait">
+<title>pthread_cond_timedwait and timeouts</title>
+
+<para>
+Historically the function
+<function>pthread_cond_timedwait</function> only allowed the
+specification of an absolute timeout, that is a timeout independent of
+the time when this function was called. However, almost every call to
+this function expresses a relative timeout. This typically happens by
+passing the sum of
+<computeroutput>clock_gettime(CLOCK_REALTIME)</computeroutput> and a
+relative timeout as the third argument. This approach is incorrect
+since forward or backward clock adjustments by e.g. ntpd will affect
+the timeout. A more reliable approach is as follows:
+<itemizedlist>
+  <listitem>
+    <para>
+      When initializing a condition variable through
+      <function>pthread_cond_init</function>, specify that the timeout of
+      <function>pthread_cond_timedwait</function> will use the clock
+      <literal>CLOCK_MONOTONIC</literal> instead of
+      <literal>CLOCK_REALTIME</literal>. You can do this via
+      <computeroutput>pthread_condattr_setclock(...,
+      CLOCK_MONOTONIC)</computeroutput>.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      When calling <function>pthread_cond_timedwait</function>, pass
+      the sum of
+      <computeroutput>clock_gettime(CLOCK_MONOTONIC)</computeroutput>
+      and a relative timeout as the third argument.
+    </para>
+  </listitem>
+</itemizedlist>
+See also
+<computeroutput>drd/tests/monitor_example.cpp</computeroutput> for an
+example.
+</para>
+
+</sect2>
+
+</sect1>
+
+
+<sect1 id="drd-manual.limitations" xreflabel="Limitations">
+<title>Limitations</title>
+
+<para>DRD currently has the following limitations:</para>
+
+<itemizedlist>
+  <listitem>
+    <para>
+      DRD, just like Memcheck, will refuse to start on Linux
+      distributions where all symbol information has been removed from
+      <filename>ld.so</filename>. This is e.g. the case for the PPC editions
+      of openSUSE and Gentoo. You will have to install the glibc debuginfo
+      package on these platforms before you can use DRD. See also openSUSE
+      bug <ulink url="http://bugzilla.novell.com/show_bug.cgi?id=396197">
+      396197</ulink> and Gentoo bug <ulink
+      url="http://bugs.gentoo.org/214065">214065</ulink>.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      With gcc 4.4.3 and before, DRD may report data races on the C++
+      class <literal>std::string</literal> in a multithreaded program. This is
+      a know <literal>libstdc++</literal> issue -- see also GCC bug
+      <ulink url="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40518">40518</ulink>
+      for more information.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      When address tracing is enabled, no information on atomic stores
+      will be displayed.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      If you compile the DRD source code yourself, you need GCC 3.0 or
+      later. GCC 2.95 is not supported.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      Of the two POSIX threads implementations for Linux, only the
+      NPTL (Native POSIX Thread Library) is supported. The older
+      LinuxThreads library is not supported.
+    </para>
+  </listitem>
+</itemizedlist>
+
+</sect1>
+
+
+<sect1 id="drd-manual.feedback" xreflabel="Feedback">
+<title>Feedback</title>
+
+<para>
+If you have any comments, suggestions, feedback or bug reports about
+DRD, feel free to either post a message on the Valgrind users mailing
+list or to file a bug report. See also <ulink
+url="&vg-url;">&vg-url;</ulink> for more information.
+</para>
+
+</sect1>
+
+
+</chapter>
diff --git a/drd/drd.h b/drd/drd.h
new file mode 100644
index 0000000..370ef92
--- /dev/null
+++ b/drd/drd.h
@@ -0,0 +1,480 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+
+/*
+  ----------------------------------------------------------------
+
+  Notice that the following BSD-style license applies to this one
+  file (drd.h) only.  The rest of Valgrind is licensed under the
+  terms of the GNU General Public License, version 2, unless
+  otherwise indicated.  See the COPYING file in the source
+  distribution for details.
+
+  ----------------------------------------------------------------
+
+  This file is part of DRD, a Valgrind tool for verification of
+  multithreaded programs.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must
+  not claim that you wrote the original software.  If you use this
+  software in a product, an acknowledgment in the product
+  documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+  not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote
+  products derived from this software without specific prior written
+  permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  ----------------------------------------------------------------
+
+  Notice that the above BSD-style license applies to this one file
+  (drd.h) only.  The entire rest of Valgrind is licensed under
+  the terms of the GNU General Public License, version 2.  See the
+  COPYING file in the source distribution for details.
+
+  ----------------------------------------------------------------
+*/
+
+#ifndef __VALGRIND_DRD_H
+#define __VALGRIND_DRD_H
+
+
+#include "valgrind.h"
+
+
+/** Obtain the thread ID assigned by Valgrind's core. */
+#define DRD_GET_VALGRIND_THREADID                                             \
+   VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID, \
+                                   0, 0, 0, 0, 0)
+
+/** Obtain the thread ID assigned by DRD. */
+#define DRD_GET_DRD_THREADID                                              \
+   VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__DRD_GET_DRD_THREAD_ID,  \
+                                   0, 0, 0, 0, 0)
+
+
+/** Tell DRD not to complain about data races for the specified variable. */
+#define DRD_IGNORE_VAR(x) ANNOTATE_BENIGN_RACE_SIZED(&(x), sizeof(x), "")
+
+/** Tell DRD to no longer ignore data races for the specified variable. */
+#define DRD_STOP_IGNORING_VAR(x)                                           \
+   VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__DRD_FINISH_SUPPRESSION,  \
+                                   &(x), sizeof(x), 0, 0, 0)
+
+/**
+ * Tell DRD to trace all memory accesses on the specified variable.
+ * until the memory that was allocated for the variable is freed.
+ */
+#define DRD_TRACE_VAR(x)                                                 \
+   VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__DRD_START_TRACE_ADDR,  \
+                                   &(x), sizeof(x), 0, 0, 0)
+
+/**
+ * @defgroup RaceDetectionAnnotations Data race detection annotations.
+ *
+ * @see See also the source file <a href="http://code.google.com/p/data-race-test/source/browse/trunk/dynamic_annotations/dynamic_annotations.h</a>
+
+ * in the ThreadSanitizer project.
+ */
+/*@{*/
+
+/**
+ * Tell DRD to insert a happens-before mark. addr is the address of an object
+ * that is not a pthread synchronization object.
+ */
+#define ANNOTATE_HAPPENS_BEFORE(addr)                                        \
+   VALGRIND_DO_CLIENT_REQUEST_EXPR(0,                                        \
+                                   VG_USERREQ__DRD_ANNOTATE_HAPPENS_BEFORE,  \
+                                   addr, 0, 0, 0, 0)
+
+/**
+ * Tell DRD that the memory accesses executed after this annotation will
+ * happen after all memory accesses performed before all preceding
+ * ANNOTATE_HAPPENS_BEFORE(addr). addr is the address of an object that is not
+ * a pthread synchronization object. Inserting a happens-after annotation
+ * before any other thread has passed by a happens-before annotation for the
+ * same address is an error.
+ */
+#define ANNOTATE_HAPPENS_AFTER(addr)                                        \
+   VALGRIND_DO_CLIENT_REQUEST_EXPR(0,                                       \
+                                   VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER,  \
+                                   addr, 0, 0, 0, 0)
+
+/**
+ * Tell DRD that waiting on the condition variable at address cv has succeeded
+ * and a lock on the mutex at address mtx is now held. Since DRD always inserts
+ * a happens before relation between the pthread_cond_signal() or
+ * pthread_cond_broadcast() call that wakes up a pthread_cond_wait() or
+ * pthread_cond_timedwait() call and the woken up thread, this macro has been
+ * defined such that it has no effect.
+ */
+#define ANNOTATE_CONDVAR_LOCK_WAIT(cv, mtx) do { } while(0)
+
+/**
+ * Tell DRD that the condition variable at address cv is about to be signaled.
+ */
+#define ANNOTATE_CONDVAR_SIGNAL(cv) do { } while(0)
+
+/**
+ * Tell DRD that the condition variable at address cv is about to be signaled.
+ */
+#define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) do { } while(0)
+
+/**
+ * Tell DRD that waiting on condition variable at address cv succeeded and that
+ * the memory operations performed after this annotation should be considered
+ * to happen after the matching ANNOTATE_CONDVAR_SIGNAL(cv). Since this is the
+ * default behavior of DRD, this macro and the macro above have been defined
+ * such that they have no effect.
+ */
+#define ANNOTATE_CONDVAR_WAIT(cv) do { } while(0)
+
+/**
+ * Tell DRD to consider the memory operations that happened before a mutex
+ * unlock event and after the subsequent mutex lock event on the same mutex as
+ * ordered. This is how DRD always behaves, so this macro has been defined
+ * such that it has no effect.
+ */
+#define ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mtx) do { } while(0)
+
+/** Deprecated -- don't use this annotation. */
+#define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mtx) do { } while(0)
+
+/**
+ * Tell DRD to handle the specified memory range like a pure happens-before
+ * detector would do. Since this is how DRD always behaves, this annotation
+ * has been defined such that it has no effect.
+ */
+#define ANNOTATE_PUBLISH_MEMORY_RANGE(addr, size) do { } while(0)
+
+/** Deprecated -- don't use this annotation. */
+#define ANNOTATE_UNPUBLISH_MEMORY_RANGE(addr, size) do { } while(0)
+
+/** Deprecated -- don't use this annotation. */
+#define ANNOTATE_SWAP_MEMORY_RANGE(addr, size) do { } while(0)
+
+/** Tell DRD that a reader-writer lock object has been initialized. */
+#define ANNOTATE_RWLOCK_CREATE(rwlock)                                      \
+   VALGRIND_DO_CLIENT_REQUEST_EXPR(0,                                       \
+                                   VG_USERREQ__DRD_ANNOTATE_RWLOCK_CREATE,  \
+                                   rwlock, 0, 0, 0, 0);
+
+/** Tell DRD that a reader-writer lock object has been destroyed. */
+#define ANNOTATE_RWLOCK_DESTROY(rwlock)                                      \
+   VALGRIND_DO_CLIENT_REQUEST_EXPR(0,                                        \
+                                   VG_USERREQ__DRD_ANNOTATE_RWLOCK_DESTROY,  \
+                                   rwlock, 0, 0, 0, 0);
+
+/**
+ * Tell DRD that a reader-writer lock has been acquired. is_w == 1 means that
+ * a write lock has been obtained, is_w == 0 means that a read lock has been
+ * obtained.
+ */
+#define ANNOTATE_RWLOCK_ACQUIRED(rwlock, is_w)                                \
+   VALGRIND_DO_CLIENT_REQUEST_EXPR(0,                                         \
+                                   VG_USERREQ__DRD_ANNOTATE_RWLOCK_ACQUIRED,  \
+                                   rwlock, is_w, 0, 0, 0)
+
+/**
+ * Tell DRD that a reader lock has been acquired on a reader-writer
+ * synchronization object.
+ */
+#define ANNOTATE_READERLOCK_ACQUIRED(rwlock) ANNOTATE_RWLOCK_ACQUIRED(rwlock, 0)
+
+/**
+ * Tell DRD that a writer lock has been acquired on a reader-writer
+ * synchronization object.
+ */
+#define ANNOTATE_WRITERLOCK_ACQUIRED(rwlock) ANNOTATE_RWLOCK_ACQUIRED(rwlock, 1)
+
+/**
+ * Tell DRD that a reader-writer lock is about to be released. is_w == 1 means
+ * that a write lock is about to be released, is_w == 0 means that a read lock
+ * is about to be released.
+ */
+#define ANNOTATE_RWLOCK_RELEASED(rwlock, is_w)                               \
+   VALGRIND_DO_CLIENT_REQUEST_EXPR(0,                                        \
+                                   VG_USERREQ__DRD_ANNOTATE_RWLOCK_RELEASED, \
+                                   rwlock, is_w, 0, 0, 0);
+
+/**
+ * Tell DRD that a reader lock is about to be released.
+ */
+#define ANNOTATE_READERLOCK_RELEASED(rwlock) ANNOTATE_RWLOCK_RELEASED(rwlock, 0)
+
+/**
+ * Tell DRD that a writer lock is about to be released.
+ */
+#define ANNOTATE_WRITERLOCK_RELEASED(rwlock) ANNOTATE_RWLOCK_RELEASED(rwlock, 1)
+
+/*
+ * Report that a barrier has been initialized with a given barrier count.  The
+ * third argument specifies whether or not reinitialization is allowed, that
+ * is, whether or not it is allowed to call barrier_init() several times
+ * without calling barrier_destroy().
+ */
+#define ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed)  \
+   VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__DRD_ANNOTATION_UNIMP,  \
+                                   "ANNOTATE_BARRIER_INIT", barrier,     \
+                                   count, reinitialization_allowed, 0)
+
+/* Report that a barrier has been destroyed. */
+#define ANNOTATE_BARRIER_DESTROY(barrier)	                             \
+   VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__DRD_ANNOTATION_UNIMP,  \
+                                   "ANNOTATE_BARRIER_DESTROY",           \
+                                   barrier, 0, 0, 0)
+
+/* Report that the calling thread is about to start waiting for a barrier. */
+#define ANNOTATE_BARRIER_WAIT_BEFORE(barrier)		                     \
+   VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__DRD_ANNOTATION_UNIMP,  \
+                                   "ANNOTATE_BARRIER_WAIT_BEFORE",       \
+                                   barrier, 0, 0, 0)
+
+/* Report that the calling thread has just finished waiting for a barrier. */
+#define ANNOTATE_BARRIER_WAIT_AFTER(barrier)	                         \
+   VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__DRD_ANNOTATION_UNIMP,  \
+                                   "ANNOTATE_BARRIER_WAIT_AFTER",        \
+                                   barrier, 0, 0, 0)
+
+/**
+ * Tell DRD that a FIFO queue has been created. The abbreviation PCQ stands for
+ * <em>producer-consumer</em>.
+ */
+#define ANNOTATE_PCQ_CREATE(pcq) do { } while(0)
+
+/** Tell DRD that a FIFO queue has been destroyed. */
+#define ANNOTATE_PCQ_DESTROY(pcq) do { } while(0)
+
+/**
+ * Tell DRD that an element has been added to the FIFO queue at address pcq.
+ */
+#define ANNOTATE_PCQ_PUT(pcq) do { } while(0)
+
+/**
+ * Tell DRD that an element has been removed from the FIFO queue at address pcq,
+ * and that DRD should insert a happens-before relationship between the memory
+ * accesses that occurred before the corresponding ANNOTATE_PCQ_PUT(pcq)
+ * annotation and the memory accesses after this annotation. Correspondence
+ * between PUT and GET annotations happens in FIFO order. Since locking
+ * of the queue is needed anyway to add elements to or to remove elements from
+ * the queue, for DRD all four FIFO annotations are defined as no-ops.
+ */
+#define ANNOTATE_PCQ_GET(pcq) do { } while(0)
+
+/**
+ * Tell DRD that data races at the specified address are expected and must not
+ * be reported.
+ */
+#define ANNOTATE_BENIGN_RACE(addr, descr) \
+   ANNOTATE_BENIGN_RACE_SIZED(addr, sizeof(*addr), descr)
+
+/* Same as ANNOTATE_BENIGN_RACE(addr, descr), but applies to
+   the memory range [addr, addr + size). */
+#define ANNOTATE_BENIGN_RACE_SIZED(addr, size, descr)	                  \
+   VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__DRD_START_SUPPRESSION,  \
+                                   addr, size, 0, 0, 0)
+
+/** Tell DRD to ignore all reads performed by the current thread. */
+#define ANNOTATE_IGNORE_READS_BEGIN()                                \
+   VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__DRD_RECORD_LOADS,  \
+                                   0, 0, 0, 0, 0);
+
+
+/** Tell DRD to no longer ignore the reads performed by the current thread. */
+#define ANNOTATE_IGNORE_READS_END()                                  \
+   VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__DRD_RECORD_LOADS,  \
+                                   1, 0, 0, 0, 0);
+
+/** Tell DRD to ignore all writes performed by the current thread. */
+#define ANNOTATE_IGNORE_WRITES_BEGIN()                                \
+   VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__DRD_RECORD_STORES,  \
+                                   0, 0, 0, 0, 0)
+
+/** Tell DRD to no longer ignore the writes performed by the current thread. */
+#define ANNOTATE_IGNORE_WRITES_END()                                  \
+   VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__DRD_RECORD_STORES,  \
+                                   1, 0, 0, 0, 0)
+
+/** Tell DRD to ignore all memory accesses performed by the current thread. */
+#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
+   do { ANNOTATE_IGNORE_READS_BEGIN(); ANNOTATE_IGNORE_WRITES_BEGIN(); } while(0)
+
+/**
+ * Tell DRD to no longer ignore the memory accesses performed by the current
+ * thread.
+ */
+#define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
+   do { ANNOTATE_IGNORE_READS_END(); ANNOTATE_IGNORE_WRITES_END(); } while(0)
+
+/**
+ * Tell DRD that size bytes starting at addr has been allocated by a custom
+ * memory allocator.
+ */
+#define ANNOTATE_NEW_MEMORY(addr, size)                              \
+   VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__DRD_CLEAN_MEMORY,  \
+                                   addr, size, 0, 0, 0)
+
+/** Ask DRD to report every access to the specified address. */
+#define ANNOTATE_TRACE_MEMORY(addr) DRD_TRACE_VAR(*(char*)(addr))
+
+/**
+ * Tell DRD to assign the specified name to the current thread. This name will
+ * be used in error messages printed by DRD.
+ */
+#define ANNOTATE_THREAD_NAME(name)                                      \
+   VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__DRD_SET_THREAD_NAME,  \
+                                   name, 0, 0, 0, 0)
+
+/*@}*/
+
+
+/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
+   This enum comprises an ABI exported by Valgrind to programs
+   which use client requests.  DO NOT CHANGE THE ORDER OF THESE
+   ENTRIES, NOR DELETE ANY -- add new ones at the end.
+*/
+enum {
+   /* Ask the DRD tool to discard all information about memory accesses   */
+   /* and client objects for the specified range. This client request is  */
+   /* binary compatible with the similarly named Helgrind client request. */
+   VG_USERREQ__DRD_CLEAN_MEMORY = VG_USERREQ_TOOL_BASE('H','G'),
+   /* args: Addr, SizeT. */
+
+   /* Ask the DRD tool the thread ID assigned by Valgrind. */
+   VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID = VG_USERREQ_TOOL_BASE('D','R'),
+   /* args: none. */
+   /* Ask the DRD tool the thread ID assigned by DRD. */
+   VG_USERREQ__DRD_GET_DRD_THREAD_ID,
+   /* args: none. */
+
+   /* To tell the DRD tool to suppress data race detection on the */
+   /* specified address range. */
+   VG_USERREQ__DRD_START_SUPPRESSION,
+   /* args: start address, size in bytes */
+   /* To tell the DRD tool no longer to suppress data race detection on */
+   /* the specified address range. */
+   VG_USERREQ__DRD_FINISH_SUPPRESSION,
+   /* args: start address, size in bytes */
+
+   /* To ask the DRD tool to trace all accesses to the specified range. */
+   VG_USERREQ__DRD_START_TRACE_ADDR,
+   /* args: Addr, SizeT. */
+   /* To ask the DRD tool to stop tracing accesses to the specified range. */
+   VG_USERREQ__DRD_STOP_TRACE_ADDR,
+   /* args: Addr, SizeT. */
+
+   /* Tell DRD whether or not to record memory loads in the calling thread. */
+   VG_USERREQ__DRD_RECORD_LOADS,
+   /* args: Bool. */
+   /* Tell DRD whether or not to record memory stores in the calling thread. */
+   VG_USERREQ__DRD_RECORD_STORES,
+   /* args: Bool. */
+
+   /* Set the name of the thread that performs this client request. */
+   VG_USERREQ__DRD_SET_THREAD_NAME,
+   /* args: null-terminated character string. */
+
+   /* Tell DRD that a DRD annotation has not yet been implemented. */
+   VG_USERREQ__DRD_ANNOTATION_UNIMP,
+   /* args: Char*. */
+
+   /* Tell DRD that a user-defined reader-writer synchronization object
+    * has been created. */
+   VG_USERREQ__DRD_ANNOTATE_RWLOCK_CREATE
+      = VG_USERREQ_TOOL_BASE('H','G') + 256 + 14,
+   /* args: Addr. */
+   /* Tell DRD that a user-defined reader-writer synchronization object
+    * is about to be destroyed. */
+   VG_USERREQ__DRD_ANNOTATE_RWLOCK_DESTROY
+      = VG_USERREQ_TOOL_BASE('H','G') + 256 + 15,
+   /* args: Addr. */
+   /* Tell DRD that a lock on a user-defined reader-writer synchronization
+    * object has been acquired. */
+   VG_USERREQ__DRD_ANNOTATE_RWLOCK_ACQUIRED
+      = VG_USERREQ_TOOL_BASE('H','G') + 256 + 17,
+   /* args: Addr, Int is_rw. */
+   /* Tell DRD that a lock on a user-defined reader-writer synchronization
+    * object is about to be released. */
+   VG_USERREQ__DRD_ANNOTATE_RWLOCK_RELEASED
+      = VG_USERREQ_TOOL_BASE('H','G') + 256 + 18,
+   /* args: Addr, Int is_rw. */
+
+   /* Tell DRD that a Helgrind annotation has not yet been implemented. */
+   VG_USERREQ__HELGRIND_ANNOTATION_UNIMP
+      = VG_USERREQ_TOOL_BASE('H','G') + 256 + 32,
+   /* args: Char*. */
+
+   /* Tell DRD to insert a happens-before annotation. */
+   VG_USERREQ__DRD_ANNOTATE_HAPPENS_BEFORE
+      = VG_USERREQ_TOOL_BASE('H','G') + 256 + 33,
+   /* args: Addr. */
+   /* Tell DRD to insert a happens-after annotation. */
+   VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER
+      = VG_USERREQ_TOOL_BASE('H','G') + 256 + 34,
+   /* args: Addr. */
+
+};
+
+
+/**
+ * @addtogroup RaceDetectionAnnotations
+ */
+/*@{*/
+
+#ifdef __cplusplus
+/* ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racy reads.
+
+   Instead of doing
+   ANNOTATE_IGNORE_READS_BEGIN();
+   ... = x;
+   ANNOTATE_IGNORE_READS_END();
+   one can use
+   ... = ANNOTATE_UNPROTECTED_READ(x); */
+template <typename T>
+inline T ANNOTATE_UNPROTECTED_READ(const volatile T& x) {
+   ANNOTATE_IGNORE_READS_BEGIN();
+   const T result = x;
+   ANNOTATE_IGNORE_READS_END();
+   return result;
+}
+/* Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable. */
+#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description)		\
+   namespace {								\
+      static class static_var##_annotator				\
+      {									\
+      public:								\
+	 static_var##_annotator()					\
+	 {								\
+	    ANNOTATE_BENIGN_RACE_SIZED(&static_var, sizeof(static_var),	\
+				       #static_var ": " description);	\
+	 }								\
+      } the_##static_var##_annotator;					\
+   }
+#endif
+
+/*@}*/
+
+#endif /* __VALGRIND_DRD_H */
diff --git a/drd/drd_barrier.c b/drd/drd_barrier.c
new file mode 100644
index 0000000..a565511
--- /dev/null
+++ b/drd/drd_barrier.c
@@ -0,0 +1,566 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#include "drd_barrier.h"
+#include "drd_clientobj.h"
+#include "drd_error.h"
+#include "drd_suppression.h"
+#include "pub_tool_errormgr.h"    // VG_(maybe_record_error)()
+#include "pub_tool_libcassert.h"  // tl_assert()
+#include "pub_tool_libcprint.h"   // VG_(printf)()
+#include "pub_tool_machine.h"     // VG_(get_IP)()
+#include "pub_tool_mallocfree.h"  // VG_(malloc)(), VG_(free)()
+#include "pub_tool_oset.h"
+#include "pub_tool_threadstate.h" // VG_(get_running_tid)()
+
+
+/* Type definitions. */
+
+/** Information associated with one thread participating in a barrier. */
+struct barrier_thread_info
+{
+   UWord       tid;           // A DrdThreadId declared as UWord because
+                              // this member variable is the key of an OSet.
+   Word        iteration;     // iteration of last pthread_barrier_wait()
+                              // call thread tid participated in.
+   Segment*    sg[2];         // Segments of the last two
+                              // pthread_barrier() calls by thread tid.
+   ExeContext* wait_call_ctxt;// call stack for *_barrier_wait() call.
+   Segment*    post_wait_sg;  // Segment created after *_barrier_wait() finished
+};
+
+
+/* Local functions. */
+
+static void barrier_cleanup(struct barrier_info* p);
+static void barrier_delete_thread(struct barrier_info* const p,
+                                  const DrdThreadId tid);
+static const char* barrier_get_typename(struct barrier_info* const p);
+static const char* barrier_type_name(const BarrierT bt);
+static
+void barrier_report_wait_delete_race(const struct barrier_info* const p,
+                                     const struct barrier_thread_info* const q);
+
+
+/* Local variables. */
+
+static Bool  s_trace_barrier = False;
+static ULong s_barrier_segment_creation_count;
+
+
+/* Function definitions. */
+
+void DRD_(barrier_set_trace)(const Bool trace_barrier)
+{
+   s_trace_barrier = trace_barrier;
+}
+
+/**
+ * Initialize the structure *p with the specified thread ID and iteration
+ * information.
+ */
+static
+void DRD_(barrier_thread_initialize)(struct barrier_thread_info* const p,
+                                     const DrdThreadId tid,
+                                     const Word iteration)
+{
+   p->tid            = tid;
+   p->iteration      = iteration;
+   p->sg[0]          = 0;
+   p->sg[1]          = 0;
+   p->wait_call_ctxt = 0;
+   p->post_wait_sg   = 0;
+}
+
+/**
+ * Deallocate the memory that is owned by members of
+ * struct barrier_thread_info.
+ */
+static void DRD_(barrier_thread_destroy)(struct barrier_thread_info* const p)
+{
+   tl_assert(p);
+   DRD_(sg_put)(p->sg[0]);
+   DRD_(sg_put)(p->sg[1]);
+   DRD_(sg_put)(p->post_wait_sg);
+}
+
+/**
+ * Initialize the structure *p with the specified client-side barrier address,
+ * barrier object size and number of participants in each barrier.
+ */
+static
+void DRD_(barrier_initialize)(struct barrier_info* const p,
+                              const Addr barrier,
+                              const BarrierT barrier_type,
+                              const Word count)
+{
+   tl_assert(barrier != 0);
+   tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier);
+   tl_assert(p->a1 == barrier);
+
+   p->cleanup           = (void(*)(DrdClientobj*))barrier_cleanup;
+   p->delete_thread
+      = (void(*)(DrdClientobj*, DrdThreadId))barrier_delete_thread;
+   p->barrier_type      = barrier_type;
+   p->count             = count;
+   p->pre_iteration     = 0;
+   p->post_iteration    = 0;
+   p->pre_waiters_left  = count;
+   p->post_waiters_left = count;
+
+   tl_assert(sizeof(((struct barrier_thread_info*)0)->tid) == sizeof(Word));
+   tl_assert(sizeof(((struct barrier_thread_info*)0)->tid)
+             >= sizeof(DrdThreadId));
+   p->oset = VG_(OSetGen_Create)(0, 0, VG_(malloc), "drd.barrier.bi.1",
+                                 VG_(free));
+}
+
+/**
+ * Deallocate the memory owned by the struct barrier_info object and also
+ * all the nodes in the OSet p->oset.
+ *
+ * Called by clientobj_destroy().
+ */
+static void barrier_cleanup(struct barrier_info* p)
+{
+   struct barrier_thread_info* q;
+   Segment* latest_sg = 0;
+
+   tl_assert(p);
+
+   if (p->pre_waiters_left != p->count)
+   {
+      BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              BarrierErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "Destruction of barrier that is being waited"
+                              " upon",
+                              &bei);
+   }
+
+   DRD_(thread_get_latest_segment)(&latest_sg, DRD_(thread_get_running_tid)());
+   tl_assert(latest_sg);
+
+   VG_(OSetGen_ResetIter)(p->oset);
+   for ( ; (q = VG_(OSetGen_Next)(p->oset)) != 0; )
+   {
+      if (q->post_wait_sg
+          && ! DRD_(vc_lte)(&q->post_wait_sg->vc, &latest_sg->vc))
+      {
+         barrier_report_wait_delete_race(p, q);
+      }
+
+      DRD_(barrier_thread_destroy)(q);
+   }
+   VG_(OSetGen_Destroy)(p->oset);
+
+   DRD_(sg_put)(latest_sg);
+}
+
+/**
+ * Look up the client-side barrier address barrier in s_barrier[]. If not
+ * found, add it.
+ */
+static
+struct barrier_info*
+DRD_(barrier_get_or_allocate)(const Addr barrier,
+                              const BarrierT barrier_type, const Word count)
+{
+   struct barrier_info *p;
+
+   tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier);
+
+   tl_assert(offsetof(DrdClientobj, barrier) == 0);
+   p = &(DRD_(clientobj_get)(barrier, ClientBarrier)->barrier);
+   if (p == 0)
+   {
+      p = &(DRD_(clientobj_add)(barrier, ClientBarrier)->barrier);
+      DRD_(barrier_initialize)(p, barrier, barrier_type, count);
+   }
+   return p;
+}
+
+/**
+ * Look up the address of the information associated with the client-side
+ * barrier object.
+ */
+static struct barrier_info* DRD_(barrier_get)(const Addr barrier)
+{
+   tl_assert(offsetof(DrdClientobj, barrier) == 0);
+   return &(DRD_(clientobj_get)(barrier, ClientBarrier)->barrier);
+}
+
+/**
+ * Initialize a barrier with client address barrier, client size size, and
+ * where count threads participate in each barrier.
+ *
+ * Called before pthread_barrier_init().
+ */
+void DRD_(barrier_init)(const Addr barrier,
+                        const BarrierT barrier_type, const Word count,
+                        const Bool reinitialization)
+{
+   struct barrier_info* p;
+
+   tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier);
+
+   if (count == 0)
+   {
+      BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), barrier, 0, 0 };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              BarrierErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "pthread_barrier_init: 'count' argument is zero",
+                              &bei);
+   }
+
+   if (! reinitialization && barrier_type == pthread_barrier)
+   {
+      p = DRD_(barrier_get)(barrier);
+      if (p)
+      {
+         BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), barrier, 0, 0 };
+         VG_(maybe_record_error)(VG_(get_running_tid)(),
+                                 BarrierErr,
+                                 VG_(get_IP)(VG_(get_running_tid)()),
+                                 "Barrier reinitialization",
+                                 &bei);
+      }
+   }
+   p = DRD_(barrier_get_or_allocate)(barrier, barrier_type, count);
+
+   if (s_trace_barrier)
+   {
+      if (reinitialization)
+      {
+         VG_(message)(Vg_UserMsg,
+                      "[%d] barrier_reinit    %s 0x%lx count %ld -> %ld\n",
+                      DRD_(thread_get_running_tid)(),
+                      barrier_get_typename(p),
+                      barrier,
+                      p->count,
+                      count);
+      }
+      else
+      {
+         VG_(message)(Vg_UserMsg,
+                      "[%d] barrier_init      %s 0x%lx\n",
+                      DRD_(thread_get_running_tid)(),
+                      barrier_get_typename(p),
+                      barrier);
+      }
+   }
+
+   if (reinitialization && p->count != count)
+   {
+      if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count)
+      {
+         BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 };
+         VG_(maybe_record_error)(VG_(get_running_tid)(),
+                                 BarrierErr,
+                                 VG_(get_IP)(VG_(get_running_tid)()),
+                                 "Reinitialization of barrier with active"
+                                 " waiters",
+                                 &bei);
+      }
+      p->count = count;
+   }
+}
+
+/** Called after pthread_barrier_destroy() / gomp_barrier_destroy(). */
+void DRD_(barrier_destroy)(const Addr barrier, const BarrierT barrier_type)
+{
+   struct barrier_info* p;
+
+   p = DRD_(barrier_get)(barrier);
+
+   if (s_trace_barrier)
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] barrier_destroy   %s 0x%lx\n",
+                   DRD_(thread_get_running_tid)(),
+                   barrier_get_typename(p),
+                   barrier);
+   }
+
+   if (p == 0)
+   {
+      GenericErrInfo GEI = {
+	 .tid = DRD_(thread_get_running_tid)(),
+	 .addr = barrier,
+      };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              GenericErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "Not a barrier",
+                              &GEI);
+      return;
+   }
+
+   if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count)
+   {
+      BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              BarrierErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "Destruction of a barrier with active waiters",
+                              &bei);
+   }
+
+   DRD_(clientobj_remove)(p->a1, ClientBarrier);
+}
+
+/** Called before pthread_barrier_wait() / gomp_barrier_wait(). */
+void DRD_(barrier_pre_wait)(const DrdThreadId tid, const Addr barrier,
+                            const BarrierT barrier_type)
+{
+   struct barrier_info* p;
+   struct barrier_thread_info* q;
+   const UWord word_tid = tid;
+
+   p = DRD_(barrier_get)(barrier);
+   if (p == 0 && barrier_type == gomp_barrier)
+   {
+      /*
+       * gomp_barrier_wait() call has been intercepted but gomp_barrier_init()
+       * not. The only cause I know of that can trigger this is that libgomp.so
+       * has been compiled with --enable-linux-futex.
+       */
+      VG_(message)(Vg_UserMsg, "\n");
+      VG_(message)(Vg_UserMsg,
+                   "Please verify whether gcc has been configured"
+                   " with option --disable-linux-futex.\n");
+      VG_(message)(Vg_UserMsg,
+                   "See also the section about OpenMP in the DRD manual.\n");
+      VG_(message)(Vg_UserMsg, "\n");
+   }
+   tl_assert(p);
+
+   if (s_trace_barrier)
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] barrier_pre_wait  %s 0x%lx iteration %ld\n",
+                   DRD_(thread_get_running_tid)(),
+                   barrier_get_typename(p),
+                   barrier,
+                   p->pre_iteration);
+   }
+
+   /* Allocate the per-thread data structure if necessary. */
+   q = VG_(OSetGen_Lookup)(p->oset, &word_tid);
+   if (q == 0)
+   {
+      q = VG_(OSetGen_AllocNode)(p->oset, sizeof(*q));
+      DRD_(barrier_thread_initialize)(q, tid, p->pre_iteration);
+      VG_(OSetGen_Insert)(p->oset, q);
+      tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q);
+   }
+
+   /* Record *_barrier_wait() call context. */
+   q->wait_call_ctxt = VG_(record_ExeContext)(VG_(get_running_tid)(), 0);
+
+   /*
+    * Store a pointer to the latest segment of the current thread in the
+    * per-thread data structure.
+    */
+   DRD_(thread_get_latest_segment)(&q->sg[p->pre_iteration], tid);
+
+   /*
+    * If the same number of threads as the barrier count indicates have
+    * called the pre *_barrier_wait() wrapper, toggle p->pre_iteration and
+    * reset the p->pre_waiters_left counter.
+    */
+   if (--p->pre_waiters_left <= 0)
+   {
+      p->pre_iteration    = 1 - p->pre_iteration;
+      p->pre_waiters_left = p->count;
+   }
+}
+
+/** Called after pthread_barrier_wait() / gomp_barrier_wait(). */
+void DRD_(barrier_post_wait)(const DrdThreadId tid, const Addr barrier,
+                             const BarrierT barrier_type, const Bool waited,
+                             const Bool serializing)
+{
+   struct barrier_info* p;
+   const UWord word_tid = tid;
+   struct barrier_thread_info* q;
+   struct barrier_thread_info* r;
+
+   p = DRD_(barrier_get)(barrier);
+
+   if (s_trace_barrier)
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] barrier_post_wait %s 0x%lx iteration %ld%s\n",
+                   tid,
+                   p ? barrier_get_typename(p) : "(?)",
+                   barrier,
+                   p ? p->post_iteration : -1,
+                   serializing ? " (serializing)" : "");
+   }
+
+   /*
+    * If p == 0, this means that the barrier has been destroyed after
+    * *_barrier_wait() returned and before this function was called. Just
+    * return in that case -- race conditions between *_barrier_wait()
+    * and *_barrier_destroy() are detected by the *_barrier_destroy() wrapper.
+    */
+   if (p == 0)
+      return;
+
+   /* If the *_barrier_wait() call returned an error code, exit. */
+   if (! waited)
+      return;
+
+   q = VG_(OSetGen_Lookup)(p->oset, &word_tid);
+   if (q == 0)
+   {
+      BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              BarrierErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "Error in barrier implementation"
+                              " -- barrier_wait() started before"
+                              " barrier_destroy() and finished after"
+                              " barrier_destroy()",
+                              &bei);
+
+      q = VG_(OSetGen_AllocNode)(p->oset, sizeof(*q));
+      DRD_(barrier_thread_initialize)(q, tid, p->pre_iteration);
+      VG_(OSetGen_Insert)(p->oset, q);
+      tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q);
+   }
+
+   /* Create a new segment and store a pointer to that segment. */
+   DRD_(thread_new_segment)(tid);
+   DRD_(thread_get_latest_segment)(&q->post_wait_sg, tid);
+   s_barrier_segment_creation_count++;
+
+   /*
+    * Combine all vector clocks that were stored in the pre_barrier_wait
+    * wrapper with the vector clock of the current thread.
+    */
+   {
+      VectorClock old_vc;
+
+      DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[tid].last->vc);
+      VG_(OSetGen_ResetIter)(p->oset);
+      for ( ; (r = VG_(OSetGen_Next)(p->oset)) != 0; )
+      {
+         if (r != q)
+         {
+            tl_assert(r->sg[p->post_iteration]);
+            DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc,
+                             &r->sg[p->post_iteration]->vc);
+         }
+      }
+      DRD_(thread_update_conflict_set)(tid, &old_vc);
+      DRD_(vc_cleanup)(&old_vc);
+   }
+
+   /*
+    * If the same number of threads as the barrier count indicates have
+    * called the post *_barrier_wait() wrapper, toggle p->post_iteration and
+    * reset the p->post_waiters_left counter.
+    */
+   if (--p->post_waiters_left <= 0)
+   {
+      p->post_iteration    = 1 - p->post_iteration;
+      p->post_waiters_left = p->count;
+   }
+}
+
+/** Called when thread tid stops to exist. */
+static void barrier_delete_thread(struct barrier_info* const p,
+                                  const DrdThreadId tid)
+{
+   struct barrier_thread_info* q;
+   const UWord word_tid = tid;
+
+   q = VG_(OSetGen_Remove)(p->oset, &word_tid);
+
+   /*
+    * q is only non-zero if the barrier object has been used by thread tid
+    * after the barrier_init() call and before the thread finished.
+    */
+   if (q)
+   {
+      DRD_(barrier_thread_destroy)(q);
+      VG_(OSetGen_FreeNode)(p->oset, q);
+   }
+}
+
+/**
+ * Report that *_barrier_destroy() has been called but that this call was
+ * not synchronized with the last *_barrier_wait() call on the same barrier.
+ *
+ * This topic has been discussed extensively on comp.programming.threads
+ * (February 3, 2009). See also
+ * <a href="http://groups.google.com/group/comp.programming.threads/browse_thread/thread/4f65535d6192aa50/a5f4bf1e3b437c4d">Immediately destroying pthread barriers</a>.
+ */
+static
+void barrier_report_wait_delete_race(const struct barrier_info* const p,
+                                     const struct barrier_thread_info* const q)
+{
+   tl_assert(p);
+   tl_assert(q);
+
+   {
+      BarrierErrInfo bei
+         = { DRD_(thread_get_running_tid)(), p->a1, q->tid, q->wait_call_ctxt };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              BarrierErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "Destruction of barrier not synchronized with"
+                              " barrier wait call",
+                              &bei);
+   }
+}
+
+static const char* barrier_get_typename(struct barrier_info* const p)
+{
+   tl_assert(p);
+
+   return barrier_type_name(p->barrier_type);
+}
+
+static const char* barrier_type_name(const BarrierT bt)
+{
+   switch (bt)
+   {
+   case pthread_barrier:
+      return "pthread barrier";
+   case gomp_barrier:
+      return "gomp barrier";
+   }
+   return "?";
+}
+
+ULong DRD_(get_barrier_segment_creation_count)(void)
+{
+   return s_barrier_segment_creation_count;
+}
diff --git a/drd/drd_barrier.h b/drd/drd_barrier.h
new file mode 100644
index 0000000..25dacd7
--- /dev/null
+++ b/drd/drd_barrier.h
@@ -0,0 +1,55 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+/* Barrier state information. */
+
+
+#ifndef __DRD_BARRIER_H
+#define __DRD_BARRIER_H
+
+
+#include "drd_basics.h"       // DrdThreadId
+#include "drd_clientreq.h"    // BarrierT
+#include "pub_tool_basics.h"  // Addr
+
+
+struct barrier_info;
+
+
+void DRD_(barrier_set_trace)(const Bool trace_barrier);
+void DRD_(barrier_init)(const Addr barrier,
+                        const BarrierT barrier_type, const Word count,
+                        const Bool reinitialization);
+void DRD_(barrier_destroy)(const Addr barrier, const BarrierT barrier_type);
+void DRD_(barrier_pre_wait)(const DrdThreadId tid, const Addr barrier,
+                            const BarrierT barrier_type);
+void DRD_(barrier_post_wait)(const DrdThreadId tid, const Addr barrier,
+                             const BarrierT barrier_type, const Bool waited,
+                             const Bool serializing);
+void DRD_(barrier_stop_using_mem)(const Addr a1, const Addr a2);
+ULong DRD_(get_barrier_segment_creation_count)(void);
+
+
+#endif /* __DRD_BARRIER_H */
diff --git a/drd/drd_basics.h b/drd/drd_basics.h
new file mode 100644
index 0000000..2d69e5b
--- /dev/null
+++ b/drd/drd_basics.h
@@ -0,0 +1,42 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of DRD, a thread error detector.
+
+  Copyright (C) 2009 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+/* Basic definitions needed by (almost) all DRD source files. */
+
+
+#ifndef __DRD_BASICS_H
+#define __DRD_BASICS_H
+
+
+#include "pub_tool_basics.h"      // Addr
+
+
+#define DRD_(str) VGAPPEND(vgDrd_, str)
+
+
+typedef UInt DrdThreadId;
+
+
+#endif /* __DRD_BASICS_H */
diff --git a/drd/drd_bitmap.c b/drd/drd_bitmap.c
new file mode 100644
index 0000000..309823e
--- /dev/null
+++ b/drd/drd_bitmap.c
@@ -0,0 +1,1251 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#include "drd_basics.h"           /* DRD_() */
+#include "drd_bitmap.h"
+#include "drd_error.h"
+#include "drd_suppression.h"
+#include "pub_drd_bitmap.h"
+#include "pub_tool_basics.h"      /* Addr, SizeT */
+#include "pub_tool_debuginfo.h"   /* VG_(get_objname)() */
+#include "pub_tool_libcassert.h"  /* tl_assert() */
+#include "pub_tool_libcbase.h"    /* VG_(memset) */
+#include "pub_tool_libcprint.h"   /* VG_(printf) */
+#include "pub_tool_machine.h"     /* VG_(get_IP)() */
+#include "pub_tool_mallocfree.h"  /* VG_(malloc), VG_(free) */
+
+
+/* Local function declarations. */
+
+static void bm2_merge(struct bitmap2* const bm2l,
+                      const struct bitmap2* const bm2r);
+static void bm2_print(const struct bitmap2* const bm2);
+
+
+/* Local variables. */
+
+static ULong s_bitmap_creation_count;
+static ULong s_bitmap_merge_count;
+static ULong s_bitmap2_merge_count;
+
+
+/* Function definitions. */
+
+struct bitmap* DRD_(bm_new)()
+{
+   struct bitmap* bm;
+
+   /* If this assert fails, fix the definition of BITS_PER_BITS_PER_UWORD */
+   /* in drd_bitmap.h.                                                    */
+   tl_assert((1 << BITS_PER_BITS_PER_UWORD) == BITS_PER_UWORD);
+
+   bm = VG_(malloc)("drd.bitmap.bn.1", sizeof(*bm));
+   DRD_(bm_init)(bm);
+
+   return bm;
+}
+
+void DRD_(bm_delete)(struct bitmap* const bm)
+{
+   tl_assert(bm);
+
+   DRD_(bm_cleanup)(bm);
+   VG_(free)(bm);
+}
+
+/** Initialize *bm. */
+void DRD_(bm_init)(struct bitmap* const bm)
+{
+   unsigned i;
+
+   tl_assert(bm);
+   /*
+    * Cache initialization. a1 is initialized with a value that never can
+    * match any valid address: the upper (ADDR_LSB_BITS + ADDR_IGNORED_BITS)
+    * bits of a1 are always zero for a valid cache entry.
+    */
+   for (i = 0; i < DRD_BITMAP_N_CACHE_ELEM; i++)
+   {
+      bm->cache[i].a1  = ~(UWord)1;
+      bm->cache[i].bm2 = 0;
+   }
+   bm->oset = VG_(OSetGen_Create)(0, 0, DRD_(bm2_alloc_node),
+                                  "drd.bitmap.bn.2", DRD_(bm2_free_node));
+
+   s_bitmap_creation_count++;
+}
+
+/** Free the memory allocated by DRD_(bm_init)(). */
+void DRD_(bm_cleanup)(struct bitmap* const bm)
+{
+   VG_(OSetGen_Destroy)(bm->oset);
+}
+
+/**
+ * Record an access of type access_type at addresses a .. a + size - 1 in
+ * bitmap bm.
+ *
+ * @note The current implementation of bm_access_range does not work for the
+ * highest addresses in the address range. At least on Linux this is
+ * not a problem since the upper part of the address space is reserved
+ * for the kernel.
+ */
+void DRD_(bm_access_range)(struct bitmap* const bm,
+                           const Addr a1, const Addr a2,
+                           const BmAccessTypeT access_type)
+{
+   tl_assert(access_type == eLoad || access_type == eStore);
+
+   if (access_type == eLoad)
+      return DRD_(bm_access_range_load)(bm, a1, a2);
+   else
+      return DRD_(bm_access_range_store)(bm, a1, a2);
+}
+
+void DRD_(bm_access_range_load)(struct bitmap* const bm, Addr a1, Addr a2)
+{
+   Addr b, b_next;
+
+   tl_assert(bm);
+   tl_assert(a1 <= a2);
+   tl_assert(a2 < first_address_with_higher_msb(a2));
+   tl_assert(a1 == first_address_with_same_lsb(a1));
+   tl_assert(a2 == first_address_with_same_lsb(a2));
+
+   for (b = a1; b < a2; b = b_next)
+   {
+      Addr b_start;
+      Addr b_end;
+      struct bitmap2* bm2;
+      UWord b0;
+
+      b_next = first_address_with_higher_msb(b);
+      if (b_next > a2)
+      {
+         b_next = a2;
+      }
+
+      bm2 = bm2_lookup_or_insert_exclusive(bm, address_msb(b));
+      tl_assert(bm2);
+
+      if (make_address(bm2->addr, 0) < a1)
+         b_start = a1;
+      else
+         if (make_address(bm2->addr, 0) < a2)
+            b_start = make_address(bm2->addr, 0);
+         else
+            break;
+
+      if (make_address(bm2->addr + 1, 0) < a2)
+         b_end = make_address(bm2->addr + 1, 0);
+      else
+         b_end = a2;
+
+      tl_assert(a1 <= b_start && b_start < b_end && b_end && b_end <= a2);
+      tl_assert(address_msb(b_start) == address_msb(b_end - 1));
+      tl_assert(address_lsb(b_start) <= address_lsb(b_end - 1));
+
+      if (address_lsb(b_start) == 0 && address_lsb(b_end) == 0)
+      {
+         unsigned k;
+
+         for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
+         {
+            bm2->bm1.bm0_r[k] = ~(UWord)0;
+         }
+      }
+      else
+      {
+         for (b0 = address_lsb(b_start); b0 <= address_lsb(b_end - 1); b0++)
+         {
+            bm0_set(bm2->bm1.bm0_r, b0);
+         }
+      }
+   }
+}
+
+void DRD_(bm_access_load_1)(struct bitmap* const bm, const Addr a1)
+{
+   bm_access_aligned_load(bm, a1, 1);
+}
+
+void DRD_(bm_access_load_2)(struct bitmap* const bm, const Addr a1)
+{
+   if ((a1 & 1) == 0)
+      bm_access_aligned_load(bm, a1, 2);
+   else
+      DRD_(bm_access_range)(bm, a1, a1 + 2, eLoad);
+}
+
+void DRD_(bm_access_load_4)(struct bitmap* const bm, const Addr a1)
+{
+   if ((a1 & 3) == 0)
+      bm_access_aligned_load(bm, a1, 4);
+   else
+      DRD_(bm_access_range)(bm, a1, a1 + 4, eLoad);
+}
+
+void DRD_(bm_access_load_8)(struct bitmap* const bm, const Addr a1)
+{
+   if ((a1 & 7) == 0)
+      bm_access_aligned_load(bm, a1, 8);
+   else if ((a1 & 3) == 0)
+   {
+      bm_access_aligned_load(bm, a1 + 0, 4);
+      bm_access_aligned_load(bm, a1 + 4, 4);
+   }
+   else
+      DRD_(bm_access_range)(bm, a1, a1 + 8, eLoad);
+}
+
+void DRD_(bm_access_range_store)(struct bitmap* const bm,
+                                 const Addr a1, const Addr a2)
+{
+   Addr b, b_next;
+
+   tl_assert(bm);
+   tl_assert(a1 <= a2);
+   tl_assert(a2 < first_address_with_higher_msb(a2));
+   tl_assert(a1 == first_address_with_same_lsb(a1));
+   tl_assert(a2 == first_address_with_same_lsb(a2));
+
+   for (b = a1; b < a2; b = b_next)
+   {
+      Addr b_start;
+      Addr b_end;
+      struct bitmap2* bm2;
+      UWord b0;
+
+      b_next = first_address_with_higher_msb(b);
+      if (b_next > a2)
+      {
+         b_next = a2;
+      }
+
+      bm2 = bm2_lookup_or_insert_exclusive(bm, address_msb(b));
+      tl_assert(bm2);
+
+      if (make_address(bm2->addr, 0) < a1)
+         b_start = a1;
+      else
+         if (make_address(bm2->addr, 0) < a2)
+            b_start = make_address(bm2->addr, 0);
+         else
+            break;
+
+      if (make_address(bm2->addr + 1, 0) < a2)
+         b_end = make_address(bm2->addr + 1, 0);
+      else
+         b_end = a2;
+
+      tl_assert(a1 <= b_start && b_start < b_end && b_end && b_end <= a2);
+      tl_assert(address_msb(b_start) == address_msb(b_end - 1));
+      tl_assert(address_lsb(b_start) <= address_lsb(b_end - 1));
+
+      if (address_lsb(b_start) == 0 && address_lsb(b_end) == 0)
+      {
+         unsigned k;
+
+         for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
+         {
+            bm2->bm1.bm0_w[k] = ~(UWord)0;
+         }
+      }
+      else
+      {
+         for (b0 = address_lsb(b_start); b0 <= address_lsb(b_end - 1); b0++)
+         {
+            bm0_set(bm2->bm1.bm0_w, b0);
+         }
+      }
+   }
+}
+
+void DRD_(bm_access_store_1)(struct bitmap* const bm, const Addr a1)
+{
+   bm_access_aligned_store(bm, a1, 1);
+}
+
+void DRD_(bm_access_store_2)(struct bitmap* const bm, const Addr a1)
+{
+   if ((a1 & 1) == 0)
+      bm_access_aligned_store(bm, a1, 2);
+   else
+      DRD_(bm_access_range)(bm, a1, a1 + 2, eStore);
+}
+
+void DRD_(bm_access_store_4)(struct bitmap* const bm, const Addr a1)
+{
+   if ((a1 & 3) == 0)
+      bm_access_aligned_store(bm, a1, 4);
+   else
+      DRD_(bm_access_range)(bm, a1, a1 + 4, eStore);
+}
+
+void DRD_(bm_access_store_8)(struct bitmap* const bm, const Addr a1)
+{
+   if ((a1 & 7) == 0)
+      bm_access_aligned_store(bm, a1, 8);
+   else if ((a1 & 3) == 0)
+   {
+      bm_access_aligned_store(bm, a1 + 0, 4);
+      bm_access_aligned_store(bm, a1 + 4, 4);
+   }
+   else
+      DRD_(bm_access_range)(bm, a1, a1 + 8, eStore);
+}
+
+Bool DRD_(bm_has)(struct bitmap* const bm, const Addr a1, const Addr a2,
+                  const BmAccessTypeT access_type)
+{
+   tl_assert(access_type == eLoad || access_type == eStore);
+
+   if (access_type == eLoad)
+      return DRD_(bm_has_any_load)(bm, a1, a2);
+   else
+      return DRD_(bm_has_any_store)(bm, a1, a2);
+}
+
+Bool
+DRD_(bm_has_any_load)(struct bitmap* const bm, const Addr a1, const Addr a2)
+{
+   Addr b, b_next;
+
+   tl_assert(bm);
+
+   for (b = a1; b < a2; b = b_next)
+   {
+      const struct bitmap2* bm2 = bm2_lookup(bm, address_msb(b));
+
+      b_next = first_address_with_higher_msb(b);
+      if (b_next > a2)
+      {
+         b_next = a2;
+      }
+
+      if (bm2)
+      {
+         Addr b_start;
+         Addr b_end;
+         UWord b0;
+         const struct bitmap1* const p1 = &bm2->bm1;
+
+         if (make_address(bm2->addr, 0) < a1)
+            b_start = a1;
+         else
+            if (make_address(bm2->addr, 0) < a2)
+               b_start = make_address(bm2->addr, 0);
+            else
+               break;
+         tl_assert(a1 <= b_start && b_start <= a2);
+
+         if (make_address(bm2->addr + 1, 0) < a2)
+            b_end = make_address(bm2->addr + 1, 0);
+         else
+            b_end = a2;
+         tl_assert(a1 <= b_end && b_end <= a2);
+         tl_assert(b_start < b_end);
+         tl_assert(address_lsb(b_start) <= address_lsb(b_end - 1));
+
+         for (b0 = address_lsb(b_start); b0 <= address_lsb(b_end - 1); b0++)
+         {
+            if (bm0_is_set(p1->bm0_r, b0))
+            {
+               return True;
+            }
+         }
+      }
+   }
+   return 0;
+}
+
+Bool DRD_(bm_has_any_store)(struct bitmap* const bm,
+                            const Addr a1, const Addr a2)
+{
+   Addr b, b_next;
+
+   tl_assert(bm);
+
+   for (b = a1; b < a2; b = b_next)
+   {
+      const struct bitmap2* bm2 = bm2_lookup(bm, address_msb(b));
+
+      b_next = first_address_with_higher_msb(b);
+      if (b_next > a2)
+      {
+         b_next = a2;
+      }
+
+      if (bm2)
+      {
+         Addr b_start;
+         Addr b_end;
+         UWord b0;
+         const struct bitmap1* const p1 = &bm2->bm1;
+
+         if (make_address(bm2->addr, 0) < a1)
+            b_start = a1;
+         else
+            if (make_address(bm2->addr, 0) < a2)
+               b_start = make_address(bm2->addr, 0);
+            else
+               break;
+         tl_assert(a1 <= b_start && b_start <= a2);
+
+         if (make_address(bm2->addr + 1, 0) < a2)
+            b_end = make_address(bm2->addr + 1, 0);
+         else
+            b_end = a2;
+         tl_assert(a1 <= b_end && b_end <= a2);
+         tl_assert(b_start < b_end);
+         tl_assert(address_lsb(b_start) <= address_lsb(b_end - 1));
+
+         for (b0 = address_lsb(b_start); b0 <= address_lsb(b_end - 1); b0++)
+         {
+            if (bm0_is_set(p1->bm0_w, b0))
+            {
+               return True;
+            }
+         }
+      }
+   }
+   return 0;
+}
+
+/* Return True if there is a read access, write access or both   */
+/* to any of the addresses in the range [ a1, a2 [ in bitmap bm. */
+Bool DRD_(bm_has_any_access)(struct bitmap* const bm,
+                             const Addr a1, const Addr a2)
+{
+   Addr b, b_next;
+
+   tl_assert(bm);
+
+   for (b = a1; b < a2; b = b_next)
+   {
+      const struct bitmap2* bm2 = bm2_lookup(bm, address_msb(b));
+
+      b_next = first_address_with_higher_msb(b);
+      if (b_next > a2)
+      {
+         b_next = a2;
+      }
+
+      if (bm2)
+      {
+         Addr b_start;
+         Addr b_end;
+         UWord b0;
+         const struct bitmap1* const p1 = &bm2->bm1;
+
+         if (make_address(bm2->addr, 0) < a1)
+            b_start = a1;
+         else
+            if (make_address(bm2->addr, 0) < a2)
+               b_start = make_address(bm2->addr, 0);
+            else
+               break;
+         tl_assert(a1 <= b_start && b_start <= a2);
+
+         if (make_address(bm2->addr + 1, 0) < a2)
+            b_end = make_address(bm2->addr + 1, 0);
+         else
+            b_end = a2;
+         tl_assert(a1 <= b_end && b_end <= a2);
+         tl_assert(b_start < b_end);
+         tl_assert(address_lsb(b_start) <= address_lsb(b_end - 1));
+
+         for (b0 = address_lsb(b_start); b0 <= address_lsb(b_end - 1); b0++)
+         {
+            /*
+             * Note: the statement below uses a binary or instead of a logical
+             * or on purpose.
+             */
+            if (bm0_is_set(p1->bm0_r, b0) | bm0_is_set(p1->bm0_w, b0))
+            {
+               return True;
+            }
+         }
+      }
+   }
+   return False;
+}
+
+/**
+ * Report whether an access of type access_type at address a is recorded in
+ * bitmap bm.
+ */
+Bool DRD_(bm_has_1)(struct bitmap* const bm,
+                    const Addr a, const BmAccessTypeT access_type)
+{
+   const struct bitmap2* p2;
+   const struct bitmap1* p1;
+   const UWord* p0;
+   const UWord a0 = address_lsb(a);
+
+   tl_assert(bm);
+
+   p2 = bm2_lookup(bm, address_msb(a));
+   if (p2)
+   {
+      p1 = &p2->bm1;
+      p0 = (access_type == eLoad) ? p1->bm0_r : p1->bm0_w;
+      return bm0_is_set(p0, a0) ? True : False;
+   }
+   return False;
+}
+
+void DRD_(bm_clear)(struct bitmap* const bm, Addr a1, Addr a2)
+{
+   Addr b, b_next;
+
+   tl_assert(bm);
+   tl_assert(a1);
+   tl_assert(a1 <= a2);
+   tl_assert(a1 == first_address_with_same_lsb(a1));
+   tl_assert(a2 == first_address_with_same_lsb(a2));
+
+   for (b = a1; b < a2; b = b_next)
+   {
+      struct bitmap2* p2;
+      Addr c;
+
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+      tl_assert(a1 <= b && b < a2);
+#endif
+
+      p2 = bm2_lookup_exclusive(bm, address_msb(b));
+
+      b_next = first_address_with_higher_msb(b);
+      if (b_next > a2)
+      {
+         b_next = a2;
+      }
+
+      if (p2 == 0)
+         continue;
+
+      c = b;
+      /* If the first address in the bitmap that must be cleared does not */
+      /* start on an UWord boundary, start clearing the first addresses.  */
+      if (uword_lsb(address_lsb(c)))
+      {
+         Addr c_next = first_address_with_higher_uword_msb(c);
+         if (c_next > b_next)
+            c_next = b_next;
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+         tl_assert(a1 <= b && b <= c && c <= c_next && c_next <= b_next
+                   && b_next <= a2);
+#endif
+         bm0_clear_range(p2->bm1.bm0_r, address_lsb(c), SCALED_SIZE(c_next - c));
+         bm0_clear_range(p2->bm1.bm0_w, address_lsb(c), SCALED_SIZE(c_next - c));
+         c = c_next;
+      }
+      /* If some UWords have to be cleared entirely, do this now. */
+      if (uword_lsb(address_lsb(c)) == 0)
+      {
+         Addr c_next = first_address_with_same_uword_lsb(b_next);
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+         tl_assert(uword_lsb(address_lsb(c)) == 0);
+         tl_assert(uword_lsb(address_lsb(c_next)) == 0);
+         tl_assert(c_next <= b_next);
+#endif
+         if (c_next > c)
+         {
+            UWord idx = uword_msb(address_lsb(c));
+            VG_(memset)(&p2->bm1.bm0_r[idx], 0, SCALED_SIZE((c_next - c) / 8));
+            VG_(memset)(&p2->bm1.bm0_w[idx], 0, SCALED_SIZE((c_next - c) / 8));
+            c = c_next;
+         }
+      }
+      /* If the last address in the bitmap that must be cleared does not */
+      /* fall on an UWord boundary, clear the last addresses.            */
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+      tl_assert(a1 <= b && b <= c && c <= b_next && b_next <= a2);
+#endif
+      bm0_clear_range(p2->bm1.bm0_r, address_lsb(c), SCALED_SIZE(b_next - c));
+      bm0_clear_range(p2->bm1.bm0_w, address_lsb(c), SCALED_SIZE(b_next - c));
+   }
+}
+
+/**
+ * Clear all references to loads in bitmap bm starting at address a1 and
+ * up to but not including address a2.
+ */
+void DRD_(bm_clear_load)(struct bitmap* const bm, Addr a1, Addr a2)
+{
+   Addr b, b_next;
+
+   tl_assert(bm);
+   tl_assert(a1);
+   tl_assert(a1 <= a2);
+   tl_assert(a1 == first_address_with_same_lsb(a1));
+   tl_assert(a2 == first_address_with_same_lsb(a2));
+
+   for (b = a1; b < a2; b = b_next)
+   {
+      struct bitmap2* p2;
+      Addr c;
+
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+      tl_assert(a1 <= b && b < a2);
+#endif
+
+      p2 = bm2_lookup_exclusive(bm, address_msb(b));
+
+      b_next = first_address_with_higher_msb(b);
+      if (b_next > a2)
+      {
+         b_next = a2;
+      }
+
+      if (p2 == 0)
+         continue;
+
+      c = b;
+      /* If the first address in the bitmap that must be cleared does not */
+      /* start on an UWord boundary, start clearing the first addresses.  */
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+      tl_assert(a1 <= b && b <= c && c < b_next && b_next <= a2);
+#endif
+      if (uword_lsb(address_lsb(c)))
+      {
+         Addr c_next = first_address_with_higher_uword_msb(c);
+         if (c_next > b_next)
+            c_next = b_next;
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+         tl_assert(a1 <= b && b <= c && c < c_next && c_next <= b_next
+                   && b_next <= a2);
+#endif
+         bm0_clear_range(p2->bm1.bm0_r, address_lsb(c), SCALED_SIZE(c_next - c));
+         c = c_next;
+      }
+      /* If some UWords have to be cleared entirely, do this now. */
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+      tl_assert(a1 <= b && b <= c && c <= b_next && b_next <= a2);
+#endif
+      if (uword_lsb(address_lsb(c)) == 0)
+      {
+         Addr c_next = first_address_with_same_uword_lsb(b_next);
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+         tl_assert(uword_lsb(address_lsb(c)) == 0);
+         tl_assert(uword_lsb(address_lsb(c_next)) == 0);
+         tl_assert(a1 <= b && b <= c && c <= c_next && c_next <= b_next
+                   && b_next <= a2);
+#endif
+         if (c_next > c)
+         {
+            UWord idx = uword_msb(address_lsb(c));
+            VG_(memset)(&p2->bm1.bm0_r[idx], 0, SCALED_SIZE((c_next - c) / 8));
+            c = c_next;
+         }
+      }
+      /* If the last address in the bitmap that must be cleared does not */
+      /* fall on an UWord boundary, clear the last addresses.            */
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+      tl_assert(a1 <= b && b <= c && c <= b_next && b_next <= a2);
+#endif
+      bm0_clear_range(p2->bm1.bm0_r, address_lsb(c), SCALED_SIZE(b_next - c));
+   }
+}
+
+/**
+ * Clear all references to stores in bitmap bm starting at address a1 and
+ * up to but not including address a2.
+ */
+void DRD_(bm_clear_store)(struct bitmap* const bm,
+                          const Addr a1, const Addr a2)
+{
+   Addr b, b_next;
+
+   tl_assert(bm);
+   tl_assert(a1);
+   tl_assert(a1 <= a2);
+   tl_assert(a1 == first_address_with_same_lsb(a1));
+   tl_assert(a2 == first_address_with_same_lsb(a2));
+
+   for (b = a1; b < a2; b = b_next)
+   {
+      struct bitmap2* p2;
+      Addr c;
+
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+      tl_assert(a1 <= b && b < a2);
+#endif
+
+      p2 = bm2_lookup_exclusive(bm, address_msb(b));
+
+      b_next = first_address_with_higher_msb(b);
+      if (b_next > a2)
+      {
+         b_next = a2;
+      }
+
+      if (p2 == 0)
+         continue;
+
+      c = b;
+      /* If the first address in the bitmap that must be cleared does not */
+      /* start on an UWord boundary, start clearing the first addresses.  */
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+      tl_assert(a1 <= b && b <= c && c < b_next && b_next <= a2);
+#endif
+      if (uword_lsb(address_lsb(c)))
+      {
+         Addr c_next = first_address_with_higher_uword_msb(c);
+         if (c_next > b_next)
+            c_next = b_next;
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+         tl_assert(a1 <= b && b <= c && c < c_next && c_next <= b_next
+                   && b_next <= a2);
+#endif
+         bm0_clear_range(p2->bm1.bm0_w, address_lsb(c), SCALED_SIZE(c_next - c));
+         c = c_next;
+      }
+      /* If some UWords have to be cleared entirely, do this now. */
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+      tl_assert(a1 <= b && b <= c && c <= b_next && b_next <= a2);
+#endif
+      if (uword_lsb(address_lsb(c)) == 0)
+      {
+         Addr c_next = first_address_with_same_uword_lsb(b_next);
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+         tl_assert(uword_lsb(address_lsb(c)) == 0);
+         tl_assert(uword_lsb(address_lsb(c_next)) == 0);
+         tl_assert(a1 <= b && b <= c && c <= c_next && c_next <= b_next
+                   && b_next <= a2);
+#endif
+         if (c_next > c)
+         {
+            UWord idx = uword_msb(address_lsb(c));
+            VG_(memset)(&p2->bm1.bm0_w[idx], 0, SCALED_SIZE((c_next - c) / 8));
+            c = c_next;
+         }
+      }
+      /* If the last address in the bitmap that must be cleared does not */
+      /* fall on an UWord boundary, clear the last addresses.            */
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+      tl_assert(a1 <= b && b <= c && c <= b_next && b_next <= a2);
+#endif
+      bm0_clear_range(p2->bm1.bm0_w, address_lsb(c), SCALED_SIZE(b_next - c));
+   }
+}
+
+/**
+ * Clear bitmap bm starting at address a1 and up to but not including address
+ * a2. Return True if and only if any of the addresses was set before
+ * clearing.
+ */
+Bool DRD_(bm_test_and_clear)(struct bitmap* const bm,
+                             const Addr a1, const Addr a2)
+{
+   Bool result;
+
+   result = DRD_(bm_has_any_access)(bm, a1, a2) != 0;
+   DRD_(bm_clear)(bm, a1, a2);
+   return result;
+}
+
+Bool DRD_(bm_has_conflict_with)(struct bitmap* const bm,
+                                const Addr a1, const Addr a2,
+                                const BmAccessTypeT access_type)
+{
+   Addr b, b_next;
+
+   tl_assert(bm);
+
+   for (b = a1; b < a2; b = b_next)
+   {
+      const struct bitmap2* bm2 = bm2_lookup(bm, address_msb(b));
+
+      b_next = first_address_with_higher_msb(b);
+      if (b_next > a2)
+      {
+         b_next = a2;
+      }
+
+      if (bm2)
+      {
+         Addr b_start;
+         Addr b_end;
+         UWord b0;
+         const struct bitmap1* const p1 = &bm2->bm1;
+
+         if (make_address(bm2->addr, 0) < a1)
+            b_start = a1;
+         else
+            if (make_address(bm2->addr, 0) < a2)
+               b_start = make_address(bm2->addr, 0);
+            else
+               break;
+         tl_assert(a1 <= b_start && b_start <= a2);
+
+         if (make_address(bm2->addr + 1, 0) < a2)
+            b_end = make_address(bm2->addr + 1, 0);
+         else
+            b_end = a2;
+         tl_assert(a1 <= b_end && b_end <= a2);
+         tl_assert(b_start < b_end);
+         tl_assert(address_lsb(b_start) <= address_lsb(b_end - 1));
+
+         for (b0 = address_lsb(b_start); b0 <= address_lsb(b_end - 1); b0++)
+         {
+            if (access_type == eLoad)
+            {
+               if (bm0_is_set(p1->bm0_w, b0))
+               {
+                  return True;
+               }
+            }
+            else
+            {
+               tl_assert(access_type == eStore);
+               if (bm0_is_set(p1->bm0_r, b0)
+                   | bm0_is_set(p1->bm0_w, b0))
+               {
+                  return True;
+               }
+            }
+         }
+      }
+   }
+   return False;
+}
+
+Bool DRD_(bm_load_has_conflict_with)(struct bitmap* const bm,
+                                     const Addr a1, const Addr a2)
+{
+   return DRD_(bm_has_conflict_with)(bm, a1, a2, eLoad);
+}
+
+Bool DRD_(bm_load_1_has_conflict_with)(struct bitmap* const bm, const Addr a1)
+{
+   return bm_aligned_load_has_conflict_with(bm, a1, 1);
+}
+
+Bool DRD_(bm_load_2_has_conflict_with)(struct bitmap* const bm, const Addr a1)
+{
+   if ((a1 & 1) == 0)
+      return bm_aligned_load_has_conflict_with(bm, a1, 2);
+   else
+      return DRD_(bm_has_conflict_with)(bm, a1, a1 + 2, eLoad);
+}
+
+Bool DRD_(bm_load_4_has_conflict_with)(struct bitmap* const bm, const Addr a1)
+{
+   if ((a1 & 3) == 0)
+      return bm_aligned_load_has_conflict_with(bm, a1, 4);
+   else
+      return DRD_(bm_has_conflict_with)(bm, a1, a1 + 4, eLoad);
+}
+
+Bool DRD_(bm_load_8_has_conflict_with)(struct bitmap* const bm, const Addr a1)
+{
+   if ((a1 & 7) == 0)
+      return bm_aligned_load_has_conflict_with(bm, a1, 8);
+   else
+      return DRD_(bm_has_conflict_with)(bm, a1, a1 + 8, eLoad);
+}
+
+Bool DRD_(bm_store_1_has_conflict_with)(struct bitmap* const bm, const Addr a1)
+{
+   return bm_aligned_store_has_conflict_with(bm, a1, 1);
+}
+
+Bool DRD_(bm_store_2_has_conflict_with)(struct bitmap* const bm, const Addr a1)
+{
+   if ((a1 & 1) == 0)
+      return bm_aligned_store_has_conflict_with(bm, a1, 2);
+   else
+      return DRD_(bm_has_conflict_with)(bm, a1, a1 + 2, eStore);
+}
+
+Bool DRD_(bm_store_4_has_conflict_with)(struct bitmap* const bm, const Addr a1)
+{
+   if ((a1 & 3) == 0)
+      return bm_aligned_store_has_conflict_with(bm, a1, 4);
+   else
+      return DRD_(bm_has_conflict_with)(bm, a1, a1 + 4, eStore);
+}
+
+Bool DRD_(bm_store_8_has_conflict_with)(struct bitmap* const bm, const Addr a1)
+{
+   if ((a1 & 7) == 0)
+      return bm_aligned_store_has_conflict_with(bm, a1, 8);
+   else
+      return DRD_(bm_has_conflict_with)(bm, a1, a1 + 8, eStore);
+}
+
+Bool DRD_(bm_store_has_conflict_with)(struct bitmap* const bm,
+                                      const Addr a1, const Addr a2)
+{
+   return DRD_(bm_has_conflict_with)(bm, a1, a2, eStore);
+}
+
+/**
+ * Return True if the two bitmaps *lhs and *rhs are identical, and false
+ * if not.
+ */
+Bool DRD_(bm_equal)(struct bitmap* const lhs, struct bitmap* const rhs)
+{
+   struct bitmap2* bm2l;
+   struct bitmap2* bm2r;
+
+   /* It's not possible to have two independent iterators over the same OSet, */
+   /* so complain if lhs == rhs.                                              */
+   tl_assert(lhs != rhs);
+
+   VG_(OSetGen_ResetIter)(lhs->oset);
+   VG_(OSetGen_ResetIter)(rhs->oset);
+
+   for ( ; (bm2l = VG_(OSetGen_Next)(lhs->oset)) != 0; )
+   {
+      while (bm2l
+             && ! DRD_(bm_has_any_access)(lhs,
+                                          make_address(bm2l->addr, 0),
+                                          make_address(bm2l->addr + 1, 0)))
+      {
+         bm2l = VG_(OSetGen_Next)(lhs->oset);
+      }
+      if (bm2l == 0)
+         break;
+      tl_assert(bm2l);
+
+      do
+      {
+         bm2r = VG_(OSetGen_Next)(rhs->oset);
+         if (bm2r == 0)
+            return False;
+      }
+      while (! DRD_(bm_has_any_access)(rhs,
+                                       make_address(bm2r->addr, 0),
+                                       make_address(bm2r->addr + 1, 0)));
+
+      tl_assert(bm2r);
+      tl_assert(DRD_(bm_has_any_access)(rhs,
+                                        make_address(bm2r->addr, 0),
+                                        make_address(bm2r->addr + 1, 0)));
+
+      if (bm2l != bm2r
+          && (bm2l->addr != bm2r->addr
+              || VG_(memcmp)(&bm2l->bm1, &bm2r->bm1, sizeof(bm2l->bm1)) != 0))
+      {
+         return False;
+      }
+   }
+
+   do
+   {
+      bm2r = VG_(OSetGen_Next)(rhs->oset);
+   } while (bm2r && ! DRD_(bm_has_any_access)(rhs,
+                                              make_address(bm2r->addr, 0),
+                                              make_address(bm2r->addr + 1, 0)));
+   if (bm2r)
+   {
+      tl_assert(DRD_(bm_has_any_access)(rhs,
+                                        make_address(bm2r->addr, 0),
+                                        make_address(bm2r->addr + 1, 0)));
+      return False;
+   }
+   return True;
+}
+
+void DRD_(bm_swap)(struct bitmap* const bm1, struct bitmap* const bm2)
+{
+   OSet* const tmp = bm1->oset;
+   bm1->oset = bm2->oset;
+   bm2->oset = tmp;
+}
+
+/** Merge bitmaps *lhs and *rhs into *lhs. */
+void DRD_(bm_merge2)(struct bitmap* const lhs, struct bitmap* const rhs)
+{
+   struct bitmap2* bm2l;
+   struct bitmap2* bm2r;
+
+   /*
+    * It's not possible to have two independent iterators over the same OSet,
+    * so complain if lhs == rhs.
+    */
+   tl_assert(lhs != rhs);
+
+   s_bitmap_merge_count++;
+
+   VG_(OSetGen_ResetIter)(rhs->oset);
+
+   for ( ; (bm2r = VG_(OSetGen_Next)(rhs->oset)) != 0; )
+   {
+      bm2l = VG_(OSetGen_Lookup)(lhs->oset, &bm2r->addr);
+      if (bm2l)
+      {
+         tl_assert(bm2l != bm2r);
+         bm2_merge(bm2l, bm2r);
+      }
+      else
+      {
+         bm2_insert_copy(lhs, bm2r);
+      }
+   }
+}
+
+/** Clear bitmap2::recalc. */
+void DRD_(bm_unmark)(struct bitmap* bm)
+{
+   struct bitmap2* bm2;
+
+   for (VG_(OSetGen_ResetIter)(bm->oset);
+        (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0;
+        )
+   {
+      bm2->recalc = False;
+   }
+}
+
+/**
+ * Report whether bitmap2::recalc has been set for the second level bitmap
+ * corresponding to address a.
+ */
+Bool DRD_(bm_is_marked)(struct bitmap* bm, const Addr a)
+{
+   const struct bitmap2* bm2;
+
+   bm2 = bm2_lookup(bm, a);
+   return bm2 && bm2->recalc;
+}
+
+/**
+ * Set bitmap2::recalc in bml for each second level bitmap in bmr that contains
+ * at least one access.
+ *
+ * @note Any new second-level bitmaps inserted in bml by this function are
+ *       uninitialized.
+ */
+void DRD_(bm_mark)(struct bitmap* bml, struct bitmap* bmr)
+{
+   struct bitmap2* bm2l;
+   struct bitmap2* bm2r;
+
+   for (VG_(OSetGen_ResetIter)(bmr->oset);
+        (bm2r = VG_(OSetGen_Next)(bmr->oset)) != 0;
+        )
+   {
+      /*if (DRD_(bm_has_any_access(bmr, make_address(bm2r->addr, 0),
+        make_address(bm2r->addr + 1, 0))))*/
+      {
+         bm2l = bm2_lookup_or_insert(bml, bm2r->addr);
+         bm2l->recalc = True;
+      }
+   }
+}
+
+/** Clear all second-level bitmaps for which bitmap2::recalc == True. */
+void DRD_(bm_clear_marked)(struct bitmap* bm)
+{
+   struct bitmap2* bm2;
+
+   for (VG_(OSetGen_ResetIter)(bm->oset);
+        (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0;
+        )
+   {
+      if (bm2->recalc)
+         bm2_clear(bm2);
+   }
+}
+
+/** Merge the second level bitmaps from *rhs into *lhs for which recalc == True. */
+void DRD_(bm_merge2_marked)(struct bitmap* const lhs, struct bitmap* const rhs)
+{
+   struct bitmap2* bm2l;
+   struct bitmap2* bm2r;
+
+   tl_assert(lhs != rhs);
+
+   /*
+    * It's not possible to have two independent iterators over the same OSet,
+    * so complain if lhs == rhs.
+    */
+   tl_assert(lhs != rhs);
+
+   s_bitmap_merge_count++;
+
+   VG_(OSetGen_ResetIter)(rhs->oset);
+
+   for ( ; (bm2r = VG_(OSetGen_Next)(rhs->oset)) != 0; )
+   {
+      bm2l = VG_(OSetGen_Lookup)(lhs->oset, &bm2r->addr);
+      if (bm2l && bm2l->recalc)
+      {
+         tl_assert(bm2l != bm2r);
+         bm2_merge(bm2l, bm2r);
+      }
+   }
+}
+
+/** Remove all marked second-level bitmaps that do not contain any access. */
+void DRD_(bm_remove_cleared_marked)(struct bitmap* bm)
+{
+   struct bitmap2* bm2;
+
+   VG_(OSetGen_ResetIter)(bm->oset);
+   for ( ; (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0; )
+   {
+      const UWord a1 = bm2->addr;
+      if (bm2->recalc
+          && ! DRD_(bm_has_any_access(bm, make_address(a1, 0),
+                                      make_address(a1 + 1, 0))))
+      {
+         bm2_remove(bm, a1);
+         VG_(OSetGen_ResetIterAt)(bm->oset, &a1);
+      }
+   }
+}
+
+/**
+ * Report whether there are any RW / WR / WW patterns in lhs and rhs.
+ * @param lhs First bitmap.
+ * @param rhs Bitmap to be compared with lhs.
+ * @return !=0 if there are data races, == 0 if there are none.
+ */
+int DRD_(bm_has_races)(struct bitmap* const lhs, struct bitmap* const rhs)
+{
+   VG_(OSetGen_ResetIter)(lhs->oset);
+   VG_(OSetGen_ResetIter)(rhs->oset);
+
+   for (;;)
+   {
+      const struct bitmap2* bm2l;
+      const struct bitmap2* bm2r;
+      const struct bitmap1* bm1l;
+      const struct bitmap1* bm1r;
+      unsigned k;
+
+      bm2l = VG_(OSetGen_Next)(lhs->oset);
+      bm2r = VG_(OSetGen_Next)(rhs->oset);
+      while (bm2l && bm2r && bm2l->addr != bm2r->addr)
+      {
+         if (bm2l->addr < bm2r->addr)
+            bm2l = VG_(OSetGen_Next)(lhs->oset);
+         else
+            bm2r = VG_(OSetGen_Next)(rhs->oset);
+      }
+      if (bm2l == 0 || bm2r == 0)
+         break;
+
+      bm1l = &bm2l->bm1;
+      bm1r = &bm2r->bm1;
+
+      for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
+      {
+         unsigned b;
+         for (b = 0; b < BITS_PER_UWORD; b++)
+         {
+            UWord const access_mask
+               = ((bm1l->bm0_r[k] & bm0_mask(b)) ? LHS_R : 0)
+               | ((bm1l->bm0_w[k] & bm0_mask(b)) ? LHS_W : 0)
+               | ((bm1r->bm0_r[k] & bm0_mask(b)) ? RHS_R : 0)
+               | ((bm1r->bm0_w[k] & bm0_mask(b)) ? RHS_W : 0);
+            Addr const a = make_address(bm2l->addr, k * BITS_PER_UWORD | b);
+            if (HAS_RACE(access_mask) && ! DRD_(is_suppressed)(a, a + 1))
+            {
+               return 1;
+            }
+         }
+      }
+   }
+   return 0;
+}
+
+void DRD_(bm_print)(struct bitmap* const bm)
+{
+   struct bitmap2* bm2;
+
+   for (VG_(OSetGen_ResetIter)(bm->oset);
+        (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0;
+        )
+   {
+      bm2_print(bm2);
+   }
+}
+
+static void bm2_print(const struct bitmap2* const bm2)
+{
+   const struct bitmap1* bm1;
+   Addr a;
+
+   tl_assert(bm2);
+
+   bm1 = &bm2->bm1;
+   for (a = make_address(bm2->addr, 0);
+        a <= make_address(bm2->addr + 1, 0) - 1;
+        a++)
+   {
+      const Bool r = bm0_is_set(bm1->bm0_r, address_lsb(a)) != 0;
+      const Bool w = bm0_is_set(bm1->bm0_w, address_lsb(a)) != 0;
+      if (r || w)
+      {
+         VG_(printf)("0x%08lx %c %c\n",
+                     a,
+                     w ? 'W' : ' ',
+                     r ? 'R' : ' ');
+      }
+   }
+}
+
+ULong DRD_(bm_get_bitmap_creation_count)(void)
+{
+   return s_bitmap_creation_count;
+}
+
+ULong DRD_(bm_get_bitmap2_creation_count)(void)
+{
+   return s_bitmap2_creation_count;
+}
+
+ULong DRD_(bm_get_bitmap2_merge_count)(void)
+{
+   return s_bitmap2_merge_count;
+}
+
+/** Compute *bm2l |= *bm2r. */
+static
+void bm2_merge(struct bitmap2* const bm2l, const struct bitmap2* const bm2r)
+{
+   unsigned k;
+
+   tl_assert(bm2l);
+   tl_assert(bm2r);
+   tl_assert(bm2l->addr == bm2r->addr);
+
+   s_bitmap2_merge_count++;
+
+   for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
+   {
+      bm2l->bm1.bm0_r[k] |= bm2r->bm1.bm0_r[k];
+   }
+   for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
+   {
+      bm2l->bm1.bm0_w[k] |= bm2r->bm1.bm0_w[k];
+   }
+}
diff --git a/drd/drd_bitmap.h b/drd/drd_bitmap.h
new file mode 100644
index 0000000..57d9423
--- /dev/null
+++ b/drd/drd_bitmap.h
@@ -0,0 +1,728 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#ifndef __DRD_BITMAP_H
+#define __DRD_BITMAP_H
+
+
+#include "pub_drd_bitmap.h"
+#include "pub_tool_basics.h"
+#include "pub_tool_oset.h"
+#include "pub_tool_libcbase.h"
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+#include "pub_tool_libcassert.h"
+#endif
+
+
+/* Bitmap representation. A bitmap is a data structure in which two bits are
+ * reserved per 32 bit address: one bit that indicates that the data at the
+ * specified address has been read, and one bit that indicates that the data
+ * has been written to.
+ */
+
+/* Client addresses are split into bitfields as follows:
+ * ------------------------------------------------------
+ * | Address MSB |      Address LSB      | Ignored bits |
+ * ------------------------------------------------------
+ * | Address MSB | UWord MSB | UWord LSB | Ignored bits |
+ * ------------------------------------------------------
+ */
+
+
+
+/* Address MSB / LSB split. */
+
+
+/** Number of least significant address bits that are ignored. */
+#define ADDR_IGNORED_BITS 0
+#define ADDR_IGNORED_MASK ((1U << ADDR_IGNORED_BITS) - 1U)
+#define ADDR_GRANULARITY  (1U << ADDR_IGNORED_BITS)
+
+/**
+ * Round argument a up to a multiple of (1 << ADDR_GRANULARITY), and next
+ * shift it right ADDR_GRANULARITY bits. The expression below is optimized
+ * for the case where a is a constant.
+ */
+#define SCALED_SIZE(a)                                                  \
+   (((((a) - 1U) | ADDR_IGNORED_MASK) + 1U) >> ADDR_IGNORED_BITS)
+
+/**
+ * Number of bits assigned to the least significant component of an address.
+ */
+#define ADDR_LSB_BITS 12
+
+/**
+ * Mask that has to be applied to an address of type Addr in order to
+ * compute the least significant part of an address split, after having
+ * shifted the address bits ADDR_GRANULARITY to the right.
+ */
+#define ADDR_LSB_MASK (((UWord)1 << ADDR_LSB_BITS) - 1U)
+
+/** Compute least significant bits of an address of type Addr. */
+static __inline__
+UWord address_lsb(const Addr a)
+{ return (a >> ADDR_IGNORED_BITS) & ADDR_LSB_MASK; }
+
+/**
+ * Compute the first address for which address_lsb() is equal to
+ * address_lsb(a).
+ */
+static __inline__
+Addr first_address_with_same_lsb(const Addr a)
+{
+   return ((a | ADDR_IGNORED_MASK) ^ ADDR_IGNORED_MASK);
+}
+
+/**
+ * Compute the first address for which address_lsb() is greater than
+ * address_lsb(a).
+ */
+static __inline__
+Addr first_address_with_higher_lsb(const Addr a)
+{
+   return ((a | ADDR_IGNORED_MASK) + 1U);
+}
+
+/** Compute most significant bits of an address of type Addr. */
+static __inline__
+UWord address_msb(const Addr a)
+{ return a >> (ADDR_LSB_BITS + ADDR_IGNORED_BITS); }
+
+static __inline__
+Addr first_address_with_higher_msb(const Addr a)
+{
+   return ((a | ((ADDR_LSB_MASK << ADDR_IGNORED_BITS) | ADDR_IGNORED_MASK))
+           + 1U);
+}
+
+/**
+ * Convert LSB and MSB back into an address.
+ *
+ * @note It is assumed that sizeof(Addr) == sizeof(UWord).
+ */
+static __inline__
+Addr make_address(const UWord a1, const UWord a0)
+{
+   return ((a1 << (ADDR_LSB_BITS + ADDR_IGNORED_BITS))
+           | (a0 << ADDR_IGNORED_BITS));
+}
+
+
+
+
+
+/** Number of bits that fit in a variable of type UWord. */
+#define BITS_PER_UWORD (8U * sizeof(UWord))
+
+/** Log2 of BITS_PER_UWORD. */
+#if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_arm)
+#define BITS_PER_BITS_PER_UWORD 5
+#elif defined(VGA_amd64) || defined(VGA_ppc64)
+#define BITS_PER_BITS_PER_UWORD 6
+#else
+#error Unknown platform.
+#endif
+
+/** Number of UWord's needed to store one bit per address LSB. */
+#define BITMAP1_UWORD_COUNT (1U << (ADDR_LSB_BITS - BITS_PER_BITS_PER_UWORD))
+
+/**
+ * Mask that has to be applied to an (Addr >> ADDR_IGNORED_BITS) expression
+ * in order to compute the least significant part of an UWord.
+ */
+#define UWORD_LSB_MASK (((UWord)1 << BITS_PER_BITS_PER_UWORD) - 1)
+
+/**
+ * Compute index into bm0[] array.
+ *
+ * @param a Address shifted right ADDR_IGNORED_BITS bits.
+ */
+static __inline__
+UWord uword_msb(const UWord a)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(a < (1U << ADDR_LSB_BITS));
+#endif
+   return a >> BITS_PER_BITS_PER_UWORD;
+}
+
+/**
+ * Return the least significant bits.
+ *
+ * @param a Address shifted right ADDR_IGNORED_BITS bits.
+ */
+static __inline__
+UWord uword_lsb(const UWord a)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(a < (1U << ADDR_LSB_BITS));
+#endif
+   return a & UWORD_LSB_MASK;
+}
+
+/**
+ * Compute the highest address lower than a for which
+ * uword_lsb(address_lsb(a)) == 0.
+ *
+ * @param a Address.
+ */
+static __inline__
+Addr first_address_with_same_uword_lsb(const Addr a)
+{
+   return (a & (~UWORD_LSB_MASK << ADDR_IGNORED_BITS));
+}
+
+/**
+ * First address that will go in the UWord past the one 'a' goes in.
+ *
+ *  @param a Address.
+ */
+static __inline__
+Addr first_address_with_higher_uword_msb(const Addr a)
+{
+   return ((a | ((UWORD_LSB_MASK << ADDR_IGNORED_BITS) | ADDR_IGNORED_MASK))
+           + 1);
+}
+
+
+
+/* Local variables. */
+
+static ULong s_bitmap2_creation_count;
+
+
+
+/*********************************************************************/
+/*           Functions for manipulating a struct bitmap1.            */
+/*********************************************************************/
+
+
+/* Lowest level, corresponding to the lowest ADDR_LSB_BITS of an address. */
+struct bitmap1
+{
+   UWord bm0_r[BITMAP1_UWORD_COUNT];
+   UWord bm0_w[BITMAP1_UWORD_COUNT];
+};
+
+static __inline__ UWord bm0_mask(const UWord a)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(address_msb(make_address(0, a)) == 0);
+#endif
+   return ((UWord)1 << uword_lsb(a));
+}
+
+/** Set the bit corresponding to address a in bitmap bm0. */
+static __inline__ void bm0_set(UWord* bm0, const UWord a)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(address_msb(make_address(0, a)) == 0);
+#endif
+   bm0[uword_msb(a)] |= (UWord)1 << uword_lsb(a);
+}
+
+/**
+ * Set the bits corresponding to all of the addresses in range
+ * [ a << ADDR_IGNORED_BITS .. (a + size) << ADDR_IGNORED_BITS [
+ * in bitmap bm0.
+ */
+static __inline__ void bm0_set_range(UWord* bm0,
+                                     const UWord a, const SizeT size)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(size > 0);
+   tl_assert(address_msb(make_address(0, a)) == 0);
+   tl_assert(address_msb(make_address(0, a + size - 1)) == 0);
+   tl_assert(uword_msb(a) == uword_msb(a + size - 1));
+#endif
+   bm0[uword_msb(a)]
+      |= (((UWord)1 << size) - 1) << uword_lsb(a);
+}
+
+/** Clear the bit corresponding to address a in bitmap bm0. */
+static __inline__ void bm0_clear(UWord* bm0, const UWord a)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(address_msb(make_address(0, a)) == 0);
+#endif
+   bm0[uword_msb(a)] &= ~((UWord)1 << uword_lsb(a));
+}
+
+/**
+ * Clear all of the addresses in range
+ * [ a << ADDR_IGNORED_BITS .. (a + size) << ADDR_IGNORED_BITS [
+ * in bitmap bm0.
+ */
+static __inline__ void bm0_clear_range(UWord* bm0,
+                                       const UWord a, const SizeT size)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(address_msb(make_address(0, a)) == 0);
+   tl_assert(size == 0 || address_msb(make_address(0, a + size - 1)) == 0);
+   tl_assert(size == 0 || uword_msb(a) == uword_msb(a + size - 1));
+#endif
+   /*
+    * Note: although the expression below yields a correct result even if
+    * size == 0, do not touch bm0[] if size == 0 because this might otherwise
+    * cause an access of memory just past the end of the bm0[] array.
+    */
+   if (size > 0)
+   {
+      bm0[uword_msb(a)]
+         &= ~((((UWord)1 << size) - 1) << uword_lsb(a));
+   }
+}
+
+/** Test whether the bit corresponding to address a is set in bitmap bm0. */
+static __inline__ UWord bm0_is_set(const UWord* bm0, const UWord a)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(address_msb(make_address(0, a)) == 0);
+#endif
+   return (bm0[uword_msb(a)] & ((UWord)1 << uword_lsb(a)));
+}
+
+/**
+ * Return true if a bit corresponding to any of the addresses in range
+ * [ a << ADDR_IGNORED_BITS .. (a + size) << ADDR_IGNORED_BITS [
+ * is set in bm0.
+ */
+static __inline__ UWord bm0_is_any_set(const UWord* bm0,
+                                       const Addr a, const SizeT size)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(size > 0);
+   tl_assert(address_msb(make_address(0, a)) == 0);
+   tl_assert(address_msb(make_address(0, a + size - 1)) == 0);
+   tl_assert(uword_msb(a) == uword_msb(a + size - 1));
+#endif
+   return (bm0[uword_msb(a)] & ((((UWord)1 << size) - 1) << uword_lsb(a)));
+}
+
+
+
+/*********************************************************************/
+/*           Functions for manipulating a struct bitmap.             */
+/*********************************************************************/
+
+
+/* Second level bitmap. */
+struct bitmap2
+{
+   Addr           addr;   ///< address_msb(...)
+   Bool           recalc;
+   struct bitmap1 bm1;
+};
+
+
+static void bm2_clear(struct bitmap2* const bm2);
+static __inline__
+struct bitmap2* bm2_insert(struct bitmap* const bm, const UWord a1);
+
+
+
+/**
+ * Rotate elements cache[0..n-1] such that the element at position n-1 is
+ * moved to position 0. This allows to speed up future cache lookups.
+ */
+static __inline__
+void bm_cache_rotate(struct bm_cache_elem cache[], const int n)
+{
+#if 0
+   struct bm_cache_elem t;
+
+   tl_assert(2 <= n && n <= 8);
+
+   t = cache[0];
+   if (n > 1)
+      cache[0] = cache[1];
+   if (n > 2)
+      cache[1] = cache[2];
+   if (n > 3)
+      cache[2] = cache[3];
+   if (n > 4)
+      cache[3] = cache[4];
+   if (n > 5)
+      cache[4] = cache[5];
+   if (n > 6)
+      cache[5] = cache[6];
+   if (n > 7)
+      cache[6] = cache[7];
+   cache[n - 1] = t;
+#endif
+}
+
+static __inline__
+Bool bm_cache_lookup(struct bitmap* const bm, const UWord a1,
+                     struct bitmap2** bm2)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(bm);
+   tl_assert(bm2);
+#endif
+
+#if DRD_BITMAP_N_CACHE_ELEM > 8
+#error Please update the code below.
+#endif
+#if DRD_BITMAP_N_CACHE_ELEM >= 1
+   if (a1 == bm->cache[0].a1)
+   {
+      *bm2 = bm->cache[0].bm2;
+      return True;
+   }
+#endif
+#if DRD_BITMAP_N_CACHE_ELEM >= 2
+   if (a1 == bm->cache[1].a1)
+   {
+      *bm2 = bm->cache[1].bm2;
+      return True;
+   }
+#endif
+#if DRD_BITMAP_N_CACHE_ELEM >= 3
+   if (a1 == bm->cache[2].a1)
+   {
+      *bm2 = bm->cache[2].bm2;
+      bm_cache_rotate(bm->cache, 3);
+      return True;
+   }
+#endif
+#if DRD_BITMAP_N_CACHE_ELEM >= 4
+   if (a1 == bm->cache[3].a1)
+   {
+      *bm2 = bm->cache[3].bm2;
+      bm_cache_rotate(bm->cache, 4);
+      return True;
+   }
+#endif
+#if DRD_BITMAP_N_CACHE_ELEM >= 5
+   if (a1 == bm->cache[4].a1)
+   {
+      *bm2 = bm->cache[4].bm2;
+      bm_cache_rotate(bm->cache, 5);
+      return True;
+   }
+#endif
+#if DRD_BITMAP_N_CACHE_ELEM >= 6
+   if (a1 == bm->cache[5].a1)
+   {
+      *bm2 = bm->cache[5].bm2;
+      bm_cache_rotate(bm->cache, 6);
+      return True;
+   }
+#endif
+#if DRD_BITMAP_N_CACHE_ELEM >= 7
+   if (a1 == bm->cache[6].a1)
+   {
+      *bm2 = bm->cache[6].bm2;
+      bm_cache_rotate(bm->cache, 7);
+      return True;
+   }
+#endif
+#if DRD_BITMAP_N_CACHE_ELEM >= 8
+   if (a1 == bm->cache[7].a1)
+   {
+      *bm2 = bm->cache[7].bm2;
+      bm_cache_rotate(bm->cache, 8);
+      return True;
+   }
+#endif
+   *bm2 = 0;
+   return False;
+}
+
+static __inline__
+void bm_update_cache(struct bitmap* const bm,
+                     const UWord a1,
+                     struct bitmap2* const bm2)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(bm);
+#endif
+
+#if DRD_BITMAP_N_CACHE_ELEM > 8
+#error Please update the code below.
+#endif
+#if DRD_BITMAP_N_CACHE_ELEM >= 8
+   bm->cache[7] = bm->cache[6];
+#endif
+#if DRD_BITMAP_N_CACHE_ELEM >= 7
+   bm->cache[6] = bm->cache[5];
+#endif
+#if DRD_BITMAP_N_CACHE_ELEM >= 6
+   bm->cache[5] = bm->cache[4];
+#endif
+#if DRD_BITMAP_N_CACHE_ELEM >= 5
+   bm->cache[4] = bm->cache[3];
+#endif
+#if DRD_BITMAP_N_CACHE_ELEM >= 4
+   bm->cache[3] = bm->cache[2];
+#endif
+#if DRD_BITMAP_N_CACHE_ELEM >= 3
+   bm->cache[2] = bm->cache[1];
+#endif
+#if DRD_BITMAP_N_CACHE_ELEM >= 2
+   bm->cache[1] = bm->cache[0];
+#endif
+   bm->cache[0].a1  = a1;
+   bm->cache[0].bm2 = bm2;
+}
+
+/**
+ * Look up the address a1 in bitmap bm and return a pointer to a potentially
+ * shared second level bitmap. The bitmap where the returned pointer points
+ * at may not be modified by the caller.
+ *
+ * @param a1 client address shifted right by ADDR_LSB_BITS.
+ * @param bm bitmap pointer.
+ */
+static __inline__
+const struct bitmap2* bm2_lookup(struct bitmap* const bm, const UWord a1)
+{
+   struct bitmap2* bm2;
+
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(bm);
+#endif
+
+   if (! bm_cache_lookup(bm, a1, &bm2))
+   {
+      bm2 = VG_(OSetGen_Lookup)(bm->oset, &a1);
+      bm_update_cache(bm, a1, bm2);
+   }
+   return bm2;
+}
+
+/**
+ * Look up the address a1 in bitmap bm and return a pointer to a second
+ * level bitmap that is not shared and hence may be modified.
+ *
+ * @param a1 client address shifted right by ADDR_LSB_BITS.
+ * @param bm bitmap pointer.
+ */
+static __inline__
+struct bitmap2*
+bm2_lookup_exclusive(struct bitmap* const bm, const UWord a1)
+{
+   struct bitmap2* bm2;
+
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(bm);
+#endif
+
+   if (! bm_cache_lookup(bm, a1, &bm2))
+   {
+      bm2 = VG_(OSetGen_Lookup)(bm->oset, &a1);
+   }
+
+   return bm2;
+}
+
+/** Clear the content of the second-level bitmap. */
+static __inline__
+void bm2_clear(struct bitmap2* const bm2)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(bm2);
+#endif
+   VG_(memset)(&bm2->bm1, 0, sizeof(bm2->bm1));
+}
+
+/**
+ * Insert an uninitialized second level bitmap for the address a1.
+ *
+ * @param bm bitmap pointer.
+ * @param a1 client address shifted right by ADDR_LSB_BITS.
+ *
+ * @note bitmap2::recalc isn't initialized here on purpose.
+ */
+static __inline__
+struct bitmap2* bm2_insert(struct bitmap* const bm, const UWord a1)
+{
+   struct bitmap2* bm2;
+
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(bm);
+#endif
+
+   s_bitmap2_creation_count++;
+
+   bm2 = VG_(OSetGen_AllocNode)(bm->oset, sizeof(*bm2));
+   bm2->addr = a1;
+   VG_(OSetGen_Insert)(bm->oset, bm2);
+
+   bm_update_cache(bm, a1, bm2);
+
+   return bm2;
+}
+
+static __inline__
+struct bitmap2* bm2_insert_copy(struct bitmap* const bm,
+                                struct bitmap2* const bm2)
+{
+   struct bitmap2* bm2_copy;
+
+   bm2_copy = bm2_insert(bm, bm2->addr);
+   VG_(memcpy)(&bm2_copy->bm1, &bm2->bm1, sizeof(bm2->bm1));
+   return bm2_copy;
+}
+
+/**
+ * Look up the address a1 in bitmap bm, and insert it if not found.
+ * The returned second level bitmap may not be modified.
+ *
+ * @param bm bitmap pointer.
+ * @param a1 client address shifted right by ADDR_LSB_BITS.
+ */
+static __inline__
+struct bitmap2* bm2_lookup_or_insert(struct bitmap* const bm, const UWord a1)
+{
+   struct bitmap2* bm2;
+
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(bm);
+#endif
+
+   if (bm_cache_lookup(bm, a1, &bm2))
+   {
+      if (bm2 == 0)
+      {
+         bm2 = bm2_insert(bm, a1);
+         bm2_clear(bm2);
+      }
+   }
+   else
+   {
+      bm2 = VG_(OSetGen_Lookup)(bm->oset, &a1);
+      if (! bm2)
+      {
+         bm2 = bm2_insert(bm, a1);
+         bm2_clear(bm2);
+      }
+      bm_update_cache(bm, a1, bm2);
+   }
+   return bm2;
+}
+
+/**
+ * Look up the address a1 in bitmap bm, and insert it if not found.
+ * The returned second level bitmap may be modified.
+ *
+ * @param a1 client address shifted right by ADDR_LSB_BITS.
+ * @param bm bitmap pointer.
+ */
+static __inline__
+struct bitmap2* bm2_lookup_or_insert_exclusive(struct bitmap* const bm,
+                                               const UWord a1)
+{
+   return bm2_lookup_or_insert(bm, a1);
+}
+
+static __inline__
+void bm2_remove(struct bitmap* const bm, const UWord a1)
+{
+   struct bitmap2* bm2;
+
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(bm);
+#endif
+
+   bm2 = VG_(OSetGen_Remove)(bm->oset, &a1);
+   VG_(OSetGen_FreeNode)(bm->oset, bm2);
+
+   bm_update_cache(bm, a1, NULL);
+}
+
+static __inline__
+void bm_access_aligned_load(struct bitmap* const bm,
+                            const Addr a1, const SizeT size)
+{
+   struct bitmap2* bm2;
+
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(bm);
+#endif
+
+   bm2 = bm2_lookup_or_insert_exclusive(bm, address_msb(a1));
+   bm0_set_range(bm2->bm1.bm0_r,
+                 (a1 >> ADDR_IGNORED_BITS) & ADDR_LSB_MASK,
+                 SCALED_SIZE(size));
+}
+
+static __inline__
+void bm_access_aligned_store(struct bitmap* const bm,
+                             const Addr a1, const SizeT size)
+{
+   struct bitmap2* bm2;
+
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(bm);
+#endif
+
+   bm2 = bm2_lookup_or_insert_exclusive(bm, address_msb(a1));
+   bm0_set_range(bm2->bm1.bm0_w,
+                 (a1 >> ADDR_IGNORED_BITS) & ADDR_LSB_MASK,
+                 SCALED_SIZE(size));
+}
+
+static __inline__
+Bool bm_aligned_load_has_conflict_with(struct bitmap* const bm,
+                                       const Addr a, const SizeT size)
+{
+   const struct bitmap2* bm2;
+
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(bm);
+#endif
+
+   bm2 = bm2_lookup(bm, address_msb(a));
+   return (bm2
+           && bm0_is_any_set(bm2->bm1.bm0_w,
+                             address_lsb(a),
+                             SCALED_SIZE(size)));
+}
+
+static __inline__
+Bool bm_aligned_store_has_conflict_with(struct bitmap* const bm,
+                                        const Addr a, const SizeT size)
+{
+   const struct bitmap2* bm2;
+
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(bm);
+#endif
+
+   bm2 = bm2_lookup(bm, address_msb(a));
+   if (bm2)
+   {
+      if (bm0_is_any_set(bm2->bm1.bm0_r, address_lsb(a), SCALED_SIZE(size))
+          | bm0_is_any_set(bm2->bm1.bm0_w, address_lsb(a), SCALED_SIZE(size)))
+      {
+         return True;
+      }
+   }
+   return False;
+}
+
+#endif /* __DRD_BITMAP_H */
diff --git a/drd/drd_bitmap2_node.c b/drd/drd_bitmap2_node.c
new file mode 100644
index 0000000..0241452
--- /dev/null
+++ b/drd/drd_bitmap2_node.c
@@ -0,0 +1,177 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+/*
+ * Block allocator for second-level bitmap nodes. Each node consists of
+ * an OSetGen node and a struct bitmap2. The code below allocates
+ * NODES_PER_CHUNK nodes at a time.
+ */
+
+
+#include "drd_basics.h"           /* DRD_() */
+#include "drd_bitmap.h"           /* struct bitmap2 */
+#include "pub_drd_bitmap.h"
+#include "pub_tool_basics.h"      /* Addr, SizeT */
+#include "pub_tool_libcassert.h"  /* tl_assert() */
+#include "pub_tool_libcbase.h"    /* VG_ROUNDUP() */
+#include "pub_tool_libcprint.h"   /* VG_(message)() */
+#include "pub_tool_mallocfree.h"  /* VG_(malloc), VG_(free) */
+
+
+#define NODES_PER_CHUNCK 512
+
+
+/* Local type definitions. */
+
+struct block_allocator_chunk {
+   struct block_allocator_chunk* next;
+   struct block_allocator_chunk* prev;
+   int   nallocated;
+   void* data;
+   void* data_end;
+   void* first_free;
+};
+
+
+/* Local variables. */
+
+static SizeT s_bm2_node_size;
+static struct block_allocator_chunk* s_first;
+
+
+/* Function definitions. */
+
+/**
+ * Allocate a new chunk and insert it at the start of the doubly-linked list
+ * s_first.
+ */
+static struct block_allocator_chunk* allocate_new_chunk(void)
+{
+   struct block_allocator_chunk* p;
+   int i;
+
+   tl_assert(s_bm2_node_size > 0);
+
+   p = VG_(malloc)("drd.bitmap.bac",
+                   sizeof(*p) + NODES_PER_CHUNCK * s_bm2_node_size);
+   tl_assert(p);
+   p->next = s_first;
+   if (s_first)
+      p->next->prev = p;
+   s_first = p;
+   p->prev = 0;
+   p->nallocated = 0;
+   p->data = (char*)p + sizeof(*p);
+   tl_assert(p->data);
+   p->data_end = (char*)(p->data) + NODES_PER_CHUNCK * s_bm2_node_size;
+   p->first_free = p->data;
+   for (i = 0; i < NODES_PER_CHUNCK - 1; i++)
+   {
+      *(void**)((char*)(p->data) + i * s_bm2_node_size)
+         = (char*)(p->data) + (i + 1) * s_bm2_node_size;
+   }
+   tl_assert(i == NODES_PER_CHUNCK - 1);
+   *(void**)((char*)(p->data) + i * s_bm2_node_size) = NULL;
+
+   return p;
+}
+
+/** Free a chunk and remove it from the list of chunks. */
+static void free_chunk(struct block_allocator_chunk* const p)
+{
+   tl_assert(p);
+   tl_assert(p->nallocated == 0);
+
+   if (p == s_first)
+      s_first = p->next;
+   else if (p->prev)
+      p->prev->next = p->next;
+   if (p->next)
+      p->next->prev = p->prev;
+   VG_(free)(p);
+}
+
+/** Allocate a node. */
+void* DRD_(bm2_alloc_node)(HChar* const ec, const SizeT szB)
+{
+   /*
+    * If szB < sizeof(struct bitmap2) then this function has been called to
+    * allocate an AVL tree root node. Otherwise it has been called to allocate
+    * an AVL tree branch or leaf node.
+    */
+   if (szB < sizeof(struct bitmap2))
+      return VG_(malloc)(ec, szB);
+
+   while (True)
+   {
+      struct block_allocator_chunk* p;
+
+      if (s_bm2_node_size == 0)
+         s_bm2_node_size = szB;
+      else
+         tl_assert(s_bm2_node_size == szB);
+
+      for (p = s_first; p; p = p->next)
+      {
+         if (p->first_free)
+         {
+            void* result;
+
+            p->nallocated++;
+            result = p->first_free;
+            p->first_free = *(void**)(p->first_free);
+            return result;
+         }
+      }
+
+      allocate_new_chunk();
+   }
+}
+
+/** Free a node. */
+void  DRD_(bm2_free_node)(void* const bm2)
+{
+   struct block_allocator_chunk* p;
+
+   tl_assert(s_bm2_node_size > 0);
+   tl_assert(bm2);
+
+   for (p = s_first; p; p = p->next)
+   {
+      if (p->data <= bm2 && bm2 < p->data_end)
+      {
+	 /* Free the memory that was allocated for a non-root AVL tree node. */
+         tl_assert(((char*)bm2 - (char*)(p->data)) % s_bm2_node_size == 0);
+         *(void**)bm2 = p->first_free;
+         p->first_free = bm2;
+         tl_assert(p->nallocated >= 1);
+         if (--(p->nallocated) == 0)
+            free_chunk(p);
+         return;
+      }
+   }
+
+   /* Free the memory that was allocated for an AVL tree root node. */
+   VG_(free)(bm2);
+}
diff --git a/drd/drd_clientobj.c b/drd/drd_clientobj.c
new file mode 100644
index 0000000..a09c5c0
--- /dev/null
+++ b/drd/drd_clientobj.c
@@ -0,0 +1,261 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#include "drd_clientobj.h"
+#include "drd_suppression.h"
+#include "pub_tool_basics.h"
+#include "pub_tool_libcassert.h"
+#include "pub_tool_libcbase.h"
+#include "pub_tool_libcprint.h"   // VG_(message)()
+#include "pub_tool_mallocfree.h"
+#include "pub_tool_options.h"     // VG_(clo_backtrace_size)
+#include "pub_tool_oset.h"
+#include "pub_tool_stacktrace.h"
+#include "pub_tool_threadstate.h" // VG_(get_running_tid)()
+
+
+/* Local variables. */
+
+static OSet* s_clientobj_set;
+static Bool s_trace_clientobj;
+
+
+/* Local functions. */
+
+static Bool clientobj_remove_obj(DrdClientobj* const p);
+
+
+/* Function definitions. */
+
+void DRD_(clientobj_set_trace)(const Bool trace)
+{
+   s_trace_clientobj = trace;
+}
+
+/** Initialize the client object set. */
+void DRD_(clientobj_init)(void)
+{
+   tl_assert(s_clientobj_set == 0);
+   s_clientobj_set = VG_(OSetGen_Create)(0, 0, VG_(malloc),
+                                         "drd.clientobj.ci.1", VG_(free));
+   tl_assert(s_clientobj_set);
+}
+
+/**
+ * Free the memory allocated for the client object set.
+ *
+ * @pre Client object set is empty.
+ */
+void DRD_(clientobj_cleanup)(void)
+{
+   tl_assert(s_clientobj_set);
+   tl_assert(VG_(OSetGen_Size)(s_clientobj_set) == 0);
+   VG_(OSetGen_Destroy)(s_clientobj_set);
+   s_clientobj_set = 0;
+}
+
+/**
+ * Return the data associated with the client object at client address addr.
+ * Return 0 if there is no client object in the set with the specified start
+ * address.
+ */
+DrdClientobj* DRD_(clientobj_get_any)(const Addr addr)
+{
+   return VG_(OSetGen_Lookup)(s_clientobj_set, &addr);
+}
+
+/**
+ * Return the data associated with the client object at client address addr
+ * and that has object type t. Return 0 if there is no client object in the
+ * set with the specified start address.
+ */
+DrdClientobj* DRD_(clientobj_get)(const Addr addr, const ObjType t)
+{
+   DrdClientobj* p;
+   p = VG_(OSetGen_Lookup)(s_clientobj_set, &addr);
+   if (p && p->any.type == t)
+      return p;
+   return 0;
+}
+
+/** Return true if and only if the address range of any client object overlaps
+ *  with the specified address range.
+ */
+Bool DRD_(clientobj_present)(const Addr a1, const Addr a2)
+{
+   DrdClientobj *p;
+
+   tl_assert(a1 <= a2);
+   VG_(OSetGen_ResetIter)(s_clientobj_set);
+   for ( ; (p = VG_(OSetGen_Next)(s_clientobj_set)) != 0; )
+   {
+      if (a1 <= p->any.a1 && p->any.a1 < a2)
+      {
+         return True;
+      }
+   }
+   return False;
+}
+
+/**
+ * Add state information for the client object at client address addr and
+ * of type t. Suppress data race reports on the address range [addr,addr+size[.
+ *
+ * @pre No other client object is present in the address range [addr,addr+size[.
+ */
+DrdClientobj* DRD_(clientobj_add)(const Addr a1, const ObjType t)
+{
+   DrdClientobj* p;
+
+   tl_assert(! DRD_(clientobj_present)(a1, a1 + 1));
+   tl_assert(VG_(OSetGen_Lookup)(s_clientobj_set, &a1) == 0);
+
+   if (s_trace_clientobj)
+   {
+      VG_(message)(Vg_UserMsg, "Adding client object 0x%lx of type %d\n", a1, t);
+   }
+
+   p = VG_(OSetGen_AllocNode)(s_clientobj_set, sizeof(*p));
+   VG_(memset)(p, 0, sizeof(*p));
+   p->any.a1   = a1;
+   p->any.type = t;
+   p->any.first_observed_at = VG_(record_ExeContext)(VG_(get_running_tid)(), 0);
+   VG_(OSetGen_Insert)(s_clientobj_set, p);
+   tl_assert(VG_(OSetGen_Lookup)(s_clientobj_set, &a1) == p);
+   if (t == ClientHbvar)
+      DRD_(mark_hbvar)(a1);
+   else
+      DRD_(start_suppression)(a1, a1 + 1, "clientobj");
+   return p;
+}
+
+/**
+ * Remove the information that was stored about the client object.
+ *
+ * @param[in] addr Address of the client object in the client address space.
+ * @param[in] t    Type of the client object.
+ */
+Bool DRD_(clientobj_remove)(const Addr addr, const ObjType t)
+{
+   DrdClientobj* p;
+
+   p = VG_(OSetGen_Lookup)(s_clientobj_set, &addr);
+   tl_assert(p);
+   tl_assert(p->any.type == t);
+   return clientobj_remove_obj(p);
+}
+
+/**
+ * Remove the information that was stored about the client object p.
+ *
+ * @note The order of operations below is important. The client object is
+ *   removed from the client object set after the cleanup function has been
+ *   called such that if the cleanup function can still use the function
+ *   DRD_(clientobj_get_any)(). This happens e.g. in the function
+ *   first_observed() in drd_error.c.
+ */
+static Bool clientobj_remove_obj(DrdClientobj* const p)
+{
+   tl_assert(p);
+
+   if (s_trace_clientobj)
+   {
+      VG_(message)(Vg_UserMsg, "Removing client object 0x%lx of type %d\n",
+                   p->any.a1, p->any.type);
+#if 0
+      VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
+                                 VG_(clo_backtrace_size));
+#endif
+   }
+
+   tl_assert(p->any.cleanup);
+   (*p->any.cleanup)(p);
+   VG_(OSetGen_Remove)(s_clientobj_set, &p->any.a1);
+   VG_(OSetGen_FreeNode)(s_clientobj_set, p);
+   return True;
+}
+
+/**
+ * Clean up all client objects p for which their start address p->any.a1 fits
+ * inside the address range [ a1, a2 [.
+ *
+ * @note The implementation of this function relies on the fact that the
+ *   data in s_clientobj_set is sorted on the start address of client objects.
+ */
+void DRD_(clientobj_stop_using_mem)(const Addr a1, const Addr a2)
+{
+   Addr removed_at;
+   DrdClientobj* p;
+
+   tl_assert(s_clientobj_set);
+
+   if (! DRD_(range_contains_suppression_or_hbvar)(a1, a2))
+      return;
+
+   VG_(OSetGen_ResetIterAt)(s_clientobj_set, &a1);
+   for ( ; (p = VG_(OSetGen_Next)(s_clientobj_set)) != 0 && p->any.a1 < a2; )
+   {
+      tl_assert(a1 <= p->any.a1);
+      removed_at = p->any.a1;
+      clientobj_remove_obj(p);
+      /*
+       * The above call removes an element from the oset and hence
+       * invalidates the iterator. Restore the iterator.
+       */
+      VG_(OSetGen_ResetIterAt)(s_clientobj_set, &removed_at);
+   }
+}
+
+/**
+ * Delete the per-thread information stored in client objects for the
+ * specified thread.
+ */
+void DRD_(clientobj_delete_thread)(const DrdThreadId tid)
+{
+   DrdClientobj *p;
+
+   VG_(OSetGen_ResetIter)(s_clientobj_set);
+   for ( ; (p = VG_(OSetGen_Next)(s_clientobj_set)) != 0; )
+   {
+      if (p->any.delete_thread)
+      {
+         (*p->any.delete_thread)(p, tid);
+      }
+   }
+}
+
+const char* DRD_(clientobj_type_name)(const ObjType t)
+{
+   switch (t)
+   {
+   case ClientMutex:     return "mutex";
+   case ClientCondvar:   return "cond";
+   case ClientHbvar:     return "order annotation";
+   case ClientSemaphore: return "semaphore";
+   case ClientBarrier:   return "barrier";
+   case ClientRwlock:    return "rwlock";
+   }
+   return "(unknown)";
+}
diff --git a/drd/drd_clientobj.h b/drd/drd_clientobj.h
new file mode 100644
index 0000000..269fed2
--- /dev/null
+++ b/drd/drd_clientobj.h
@@ -0,0 +1,171 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#ifndef __DRD_CLIENTOBJ_H
+#define __DRD_CLIENTOBJ_H
+
+
+#include "drd_basics.h"          /* DrdThreadId */
+#include "drd_clientreq.h"       /* MutexT */
+#include "pub_tool_basics.h"
+#include "pub_tool_execontext.h" /* ExeContext */
+#include "pub_tool_oset.h"
+#include "pub_tool_xarray.h"
+
+
+/* Forward declarations. */
+
+union drd_clientobj;
+
+
+/* Type definitions. */
+
+typedef enum {
+   ClientMutex     = 1,
+   ClientCondvar   = 2,
+   ClientHbvar     = 3,
+   ClientSemaphore = 4,
+   ClientBarrier   = 5,
+   ClientRwlock    = 6,
+} ObjType;
+
+struct any
+{
+   Addr        a1;
+   ObjType     type;
+   void        (*cleanup)(union drd_clientobj*);
+   void        (*delete_thread)(union drd_clientobj*, DrdThreadId);
+   ExeContext* first_observed_at;
+};
+
+struct mutex_info
+{
+   Addr            a1;
+   ObjType         type;
+   void            (*cleanup)(union drd_clientobj*);
+   void            (*delete_thread)(union drd_clientobj*, DrdThreadId);
+   ExeContext*     first_observed_at;
+   MutexT          mutex_type;      // pthread_mutex_t or pthread_spinlock_t.
+   int             recursion_count; // 0 if free, >= 1 if locked.
+   DrdThreadId     owner;           // owner if locked, last owner if free.
+   struct segment* last_locked_segment;
+   ULong           acquiry_time_ms;
+   ExeContext*     acquired_at;
+};
+
+struct cond_info
+{
+   Addr        a1;
+   ObjType     type;
+   void        (*cleanup)(union drd_clientobj*);
+   void        (*delete_thread)(union drd_clientobj*, DrdThreadId);
+   ExeContext* first_observed_at;
+   int         waiter_count;
+   Addr        mutex; // Client mutex specified in pthread_cond_wait() call, and
+            // null if no client threads are currently waiting on this cond.var.
+};
+
+struct hb_info
+{
+   Addr        a1;
+   ObjType     type;
+   void        (*cleanup)(union drd_clientobj*);
+   void        (*delete_thread)(union drd_clientobj*, DrdThreadId);
+   ExeContext* first_observed_at;
+   OSet*       oset;  // Per-thread order annotation information.
+};
+
+struct semaphore_info
+{
+   Addr        a1;
+   ObjType     type;
+   void        (*cleanup)(union drd_clientobj*);
+   void        (*delete_thread)(union drd_clientobj*, DrdThreadId);
+   ExeContext* first_observed_at;
+   UInt        waits_to_skip;     // Number of sem_wait() calls to skip
+   // (due to the value assigned by sem_init()).
+   UInt        value;             // Semaphore value.
+   UWord       waiters;           // Number of threads inside sem_wait().
+   DrdThreadId last_sem_post_tid; // Thread ID associated with last sem_post().
+   XArray*     last_sem_post_seg; // array of Segment*, used as a stack.
+};
+
+struct barrier_info
+{
+   Addr     a1;
+   ObjType  type;
+   void     (*cleanup)(union drd_clientobj*);
+   void     (*delete_thread)(union drd_clientobj*, DrdThreadId);
+   ExeContext* first_observed_at;
+   BarrierT barrier_type;      // pthread_barrier or gomp_barrier.
+   Word     count;             // Participant count in a barrier wait.
+   Word     pre_iteration;     // pre barrier completion count modulo two.
+   Word     post_iteration;    // post barrier completion count modulo two.
+   Word     pre_waiters_left;  // number of waiters left for a complete barrier.
+   Word     post_waiters_left; // number of waiters left for a complete barrier.
+   OSet*    oset;              // Per-thread barrier information.
+};
+
+struct rwlock_info
+{
+   Addr        a1;
+   ObjType     type;
+   void        (*cleanup)(union drd_clientobj*);
+   void        (*delete_thread)(union drd_clientobj*, DrdThreadId);
+   ExeContext* first_observed_at;
+   RwLockT     rwlock_type;
+   OSet*       thread_info;
+   ULong       acquiry_time_ms;
+   ExeContext* acquired_at;
+};
+
+typedef union drd_clientobj
+{
+   struct any            any;
+   struct mutex_info     mutex;
+   struct cond_info      cond;
+   struct hb_info        hb;
+   struct semaphore_info semaphore;
+   struct barrier_info   barrier;
+   struct rwlock_info    rwlock;
+} DrdClientobj;
+
+
+/* Function declarations. */
+
+void DRD_(clientobj_set_trace)(const Bool trace);
+void DRD_(clientobj_init)(void);
+void DRD_(clientobj_cleanup)(void);
+DrdClientobj* DRD_(clientobj_get_any)(const Addr addr);
+DrdClientobj* DRD_(clientobj_get)(const Addr addr, const ObjType t);
+Bool DRD_(clientobj_present)(const Addr a1, const Addr a2);
+DrdClientobj* DRD_(clientobj_add)(const Addr a1, const ObjType t);
+Bool DRD_(clientobj_remove)(const Addr addr, const ObjType t);
+void DRD_(clientobj_stop_using_mem)(const Addr a1, const Addr a2);
+void DRD_(clientobj_delete_thread)(const DrdThreadId tid);
+const char* DRD_(clientobj_type_name)(const ObjType t);
+
+
+#endif /* __DRD_CLIENTOBJ_H */
diff --git a/drd/drd_clientreq.c b/drd/drd_clientreq.c
new file mode 100644
index 0000000..d08d25e
--- /dev/null
+++ b/drd/drd_clientreq.c
@@ -0,0 +1,537 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#include "drd_barrier.h"
+#include "drd_clientreq.h"
+#include "drd_cond.h"
+#include "drd_error.h"
+#include "drd_hb.h"
+#include "drd_load_store.h"
+#include "drd_malloc_wrappers.h"
+#include "drd_mutex.h"
+#include "drd_rwlock.h"
+#include "drd_semaphore.h"
+#include "drd_suppression.h"      // drd_start_suppression()
+#include "drd_thread.h"
+#include "pub_tool_basics.h"      // Bool
+#include "pub_tool_debuginfo.h"   // VG_(describe_IP)()
+#include "pub_tool_libcassert.h"
+#include "pub_tool_libcassert.h"  // tl_assert()
+#include "pub_tool_libcprint.h"   // VG_(message)()
+#include "pub_tool_machine.h"     // VG_(get_SP)()
+#include "pub_tool_threadstate.h"
+#include "pub_tool_tooliface.h"   // VG_(needs_...)()
+
+
+/* Local function declarations. */
+
+static Bool handle_client_request(ThreadId vg_tid, UWord* arg, UWord* ret);
+
+
+/* Function definitions. */
+
+/**
+ * Tell the Valgrind core the address of the DRD function that processes
+ * client requests. Must be called before any client code is run.
+ */
+void DRD_(clientreq_init)(void)
+{
+   VG_(needs_client_requests)(handle_client_request);
+}
+
+/**
+ * DRD's handler for Valgrind client requests. The code below handles both
+ * DRD's public and tool-internal client requests.
+ */
+static Bool handle_client_request(ThreadId vg_tid, UWord* arg, UWord* ret)
+{
+   UWord result = 0;
+   const DrdThreadId drd_tid = DRD_(thread_get_running_tid)();
+
+   tl_assert(vg_tid == VG_(get_running_tid()));
+   tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_tid) == drd_tid);
+
+   switch (arg[0])
+   {
+   case VG_USERREQ__MALLOCLIKE_BLOCK:
+      if (arg[1])
+         DRD_(malloclike_block)(vg_tid, arg[1]/*addr*/, arg[2]/*size*/);
+      break;
+
+   case VG_USERREQ__FREELIKE_BLOCK:
+      if (arg[1] && ! DRD_(freelike_block)(vg_tid, arg[1]/*addr*/))
+      {
+         GenericErrInfo GEI = {
+	    .tid = DRD_(thread_get_running_tid)(),
+	    .addr = 0,
+	 };
+         VG_(maybe_record_error)(vg_tid,
+                                 GenericErr,
+                                 VG_(get_IP)(vg_tid),
+                                 "Invalid VG_USERREQ__FREELIKE_BLOCK request",
+                                 &GEI);
+      }
+      break;
+
+   case VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID:
+      result = vg_tid;
+      break;
+
+   case VG_USERREQ__DRD_GET_DRD_THREAD_ID:
+      result = drd_tid;
+      break;
+
+   case VG_USERREQ__DRD_SET_THREAD_NAME:
+      DRD_(thread_set_name)(drd_tid, (const char*)arg[1]);
+      break;
+
+   case VG_USERREQ__DRD_START_SUPPRESSION:
+      /*_VG_USERREQ__HG_ARANGE_MAKE_UNTRACKED*/
+   case VG_USERREQ_TOOL_BASE('H','G') + 256 + 39:
+      DRD_(start_suppression)(arg[1], arg[1] + arg[2], "client");
+      break;
+
+   case VG_USERREQ__DRD_FINISH_SUPPRESSION:
+      /*_VG_USERREQ__HG_ARANGE_MAKE_TRACKED*/
+   case VG_USERREQ_TOOL_BASE('H','G') + 256 + 40:
+      DRD_(finish_suppression)(arg[1], arg[1] + arg[2]);
+      break;
+
+   case VG_USERREQ__DRD_ANNOTATE_HAPPENS_BEFORE:
+      DRD_(hb_happens_before)(drd_tid, arg[1]);
+      break;
+
+   case VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER:
+      DRD_(hb_happens_after)(drd_tid, arg[1]);
+      break;
+
+   case VG_USERREQ__DRD_ANNOTATE_RWLOCK_CREATE:
+      if (arg[1])
+      {
+         struct mutex_info* const mutex_p = DRD_(mutex_get)(arg[1]);
+         if (mutex_p && mutex_p->mutex_type == mutex_type_spinlock)
+            break;
+      }
+      DRD_(rwlock_pre_init)(arg[1], user_rwlock);
+      break;
+
+   case VG_USERREQ__DRD_ANNOTATE_RWLOCK_DESTROY:
+      if (arg[1])
+      {
+         struct mutex_info* const mutex_p = DRD_(mutex_get)(arg[1]);
+         if (mutex_p && mutex_p->mutex_type == mutex_type_spinlock)
+            break;
+      }
+      DRD_(rwlock_post_destroy)(arg[1], user_rwlock);
+      break;
+
+   case VG_USERREQ__DRD_ANNOTATE_RWLOCK_ACQUIRED:
+      if (arg[1])
+      {
+         struct mutex_info* const mutex_p = DRD_(mutex_get)(arg[1]);
+         if (mutex_p && mutex_p->mutex_type == mutex_type_spinlock)
+            break;
+      }
+      tl_assert(arg[2] == !! arg[2]);
+      if (arg[2])
+      {
+         DRD_(rwlock_pre_wrlock)(arg[1], user_rwlock);
+         DRD_(rwlock_post_wrlock)(arg[1], user_rwlock, True);
+      }
+      else
+      {
+         DRD_(rwlock_pre_rdlock)(arg[1], user_rwlock);
+         DRD_(rwlock_post_rdlock)(arg[1], user_rwlock, True);
+      }
+      break;
+
+   case VG_USERREQ__DRD_ANNOTATE_RWLOCK_RELEASED:
+      if (arg[1])
+      {
+         struct mutex_info* const mutex_p = DRD_(mutex_get)(arg[1]);
+         if (mutex_p && mutex_p->mutex_type == mutex_type_spinlock)
+            break;
+      }
+      tl_assert(arg[2] == !! arg[2]);
+      DRD_(rwlock_pre_unlock)(arg[1], user_rwlock);
+      break;
+
+   case VG_USERREQ__SET_PTHREAD_COND_INITIALIZER:
+      DRD_(pthread_cond_initializer) = (Addr)arg[1];
+      DRD_(pthread_cond_initializer_size) = arg[2];
+      break;
+
+   case VG_USERREQ__DRD_START_NEW_SEGMENT:
+      DRD_(thread_new_segment)(DRD_(PtThreadIdToDrdThreadId)(arg[1]));
+      break;
+
+   case VG_USERREQ__DRD_START_TRACE_ADDR:
+      DRD_(start_tracing_address_range)(arg[1], arg[1] + arg[2]);
+      break;
+
+   case VG_USERREQ__DRD_STOP_TRACE_ADDR:
+      DRD_(stop_tracing_address_range)(arg[1], arg[1] + arg[2]);
+      break;
+
+   case VG_USERREQ__DRD_RECORD_LOADS:
+      DRD_(thread_set_record_loads)(drd_tid, arg[1]);
+      break;
+
+   case VG_USERREQ__DRD_RECORD_STORES:
+      DRD_(thread_set_record_stores)(drd_tid, arg[1]);
+      break;
+
+   case VG_USERREQ__SET_PTHREADID:
+      // pthread_self() returns 0 for programs not linked with libpthread.so.
+      if (arg[1] != INVALID_POSIX_THREADID)
+         DRD_(thread_set_pthreadid)(drd_tid, arg[1]);
+      break;
+
+   case VG_USERREQ__SET_JOINABLE:
+      DRD_(thread_set_joinable)(DRD_(PtThreadIdToDrdThreadId)(arg[1]),
+                                (Bool)arg[2]);
+      break;
+
+   case VG_USERREQ__ENTERING_PTHREAD_CREATE:
+      DRD_(thread_entering_pthread_create)(drd_tid);
+      break;
+
+   case VG_USERREQ__LEFT_PTHREAD_CREATE:
+      DRD_(thread_left_pthread_create)(drd_tid);
+      break;
+
+   case VG_USERREQ__POST_THREAD_JOIN:
+   {
+      const DrdThreadId thread_to_join = DRD_(PtThreadIdToDrdThreadId)(arg[1]);
+      if (thread_to_join == DRD_INVALID_THREADID)
+      {
+         InvalidThreadIdInfo ITI = { DRD_(thread_get_running_tid)(), arg[1] };
+         VG_(maybe_record_error)(vg_tid,
+                                 InvalidThreadId,
+                                 VG_(get_IP)(vg_tid),
+                                 "pthread_join(): invalid thread ID",
+                                 &ITI);
+      }
+      else
+      {
+         DRD_(thread_post_join)(drd_tid, thread_to_join);
+      }
+      break;
+   }
+
+   case VG_USERREQ__PRE_THREAD_CANCEL:
+   {
+      const DrdThreadId thread_to_cancel =DRD_(PtThreadIdToDrdThreadId)(arg[1]);
+      if (thread_to_cancel == DRD_INVALID_THREADID)
+      {
+         InvalidThreadIdInfo ITI = { DRD_(thread_get_running_tid)(), arg[1] };
+         VG_(maybe_record_error)(vg_tid,
+                                 InvalidThreadId,
+                                 VG_(get_IP)(vg_tid),
+                                 "pthread_cancel(): invalid thread ID",
+                                 &ITI);
+      }
+      else
+      {
+         DRD_(thread_pre_cancel)(thread_to_cancel);
+      }
+      break;
+   }
+
+   case VG_USERREQ__POST_THREAD_CANCEL:
+      break;
+
+   case VG_USERREQ__PRE_MUTEX_INIT:
+      if (DRD_(thread_enter_synchr)(drd_tid) == 0)
+         DRD_(mutex_init)(arg[1], arg[2]);
+      break;
+
+   case VG_USERREQ__POST_MUTEX_INIT:
+      DRD_(thread_leave_synchr)(drd_tid);
+      break;
+
+   case VG_USERREQ__PRE_MUTEX_DESTROY:
+      DRD_(thread_enter_synchr)(drd_tid);
+      break;
+
+   case VG_USERREQ__POST_MUTEX_DESTROY:
+      if (DRD_(thread_leave_synchr)(drd_tid) == 0)
+         DRD_(mutex_post_destroy)(arg[1]);
+      break;
+
+   case VG_USERREQ__PRE_MUTEX_LOCK:
+      if (DRD_(thread_enter_synchr)(drd_tid) == 0)
+         DRD_(mutex_pre_lock)(arg[1], arg[2], arg[3]);
+      break;
+
+   case VG_USERREQ__POST_MUTEX_LOCK:
+      if (DRD_(thread_leave_synchr)(drd_tid) == 0)
+         DRD_(mutex_post_lock)(arg[1], arg[2], False/*post_cond_wait*/);
+      break;
+
+   case VG_USERREQ__PRE_MUTEX_UNLOCK:
+      if (DRD_(thread_enter_synchr)(drd_tid) == 0)
+         DRD_(mutex_unlock)(arg[1], arg[2]);
+      break;
+
+   case VG_USERREQ__POST_MUTEX_UNLOCK:
+      DRD_(thread_leave_synchr)(drd_tid);
+      break;
+
+   case VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK:
+      if (DRD_(thread_enter_synchr)(drd_tid) == 0)
+         DRD_(spinlock_init_or_unlock)(arg[1]);
+      break;
+
+   case VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK:
+      DRD_(thread_leave_synchr)(drd_tid);
+      break;
+
+   case VG_USERREQ__PRE_COND_INIT:
+      if (DRD_(thread_enter_synchr)(drd_tid) == 0)
+         DRD_(cond_pre_init)(arg[1]);
+      break;
+
+   case VG_USERREQ__POST_COND_INIT:
+      DRD_(thread_leave_synchr)(drd_tid);
+      break;
+
+   case VG_USERREQ__PRE_COND_DESTROY:
+      DRD_(thread_enter_synchr)(drd_tid);
+      break;
+
+   case VG_USERREQ__POST_COND_DESTROY:
+      if (DRD_(thread_leave_synchr)(drd_tid) == 0)
+         DRD_(cond_post_destroy)(arg[1]);
+      break;
+
+   case VG_USERREQ__PRE_COND_WAIT:
+      if (DRD_(thread_enter_synchr)(drd_tid) == 0)
+      {
+         const Addr cond = arg[1];
+         const Addr mutex = arg[2];
+         const MutexT mutex_type = arg[3];
+         DRD_(mutex_unlock)(mutex, mutex_type);
+         DRD_(cond_pre_wait)(cond, mutex);
+      }
+      break;
+
+   case VG_USERREQ__POST_COND_WAIT:
+      if (DRD_(thread_leave_synchr)(drd_tid) == 0)
+      {
+         const Addr cond = arg[1];
+         const Addr mutex = arg[2];
+         const Bool took_lock = arg[3];
+         DRD_(cond_post_wait)(cond);
+         DRD_(mutex_post_lock)(mutex, took_lock, True);
+      }
+      break;
+
+   case VG_USERREQ__PRE_COND_SIGNAL:
+      if (DRD_(thread_enter_synchr)(drd_tid) == 0)
+         DRD_(cond_pre_signal)(arg[1]);
+      break;
+
+   case VG_USERREQ__POST_COND_SIGNAL:
+      DRD_(thread_leave_synchr)(drd_tid);
+      break;
+
+   case VG_USERREQ__PRE_COND_BROADCAST:
+      if (DRD_(thread_enter_synchr)(drd_tid) == 0)
+         DRD_(cond_pre_broadcast)(arg[1]);
+      break;
+
+   case VG_USERREQ__POST_COND_BROADCAST:
+      DRD_(thread_leave_synchr)(drd_tid);
+      break;
+
+   case VG_USERREQ__PRE_SEM_INIT:
+      if (DRD_(thread_enter_synchr)(drd_tid) == 0)
+         DRD_(semaphore_init)(arg[1], arg[2], arg[3]);
+      break;
+
+   case VG_USERREQ__POST_SEM_INIT:
+      DRD_(thread_leave_synchr)(drd_tid);
+      break;
+
+   case VG_USERREQ__PRE_SEM_DESTROY:
+      DRD_(thread_enter_synchr)(drd_tid);
+      break;
+
+   case VG_USERREQ__POST_SEM_DESTROY:
+      if (DRD_(thread_leave_synchr)(drd_tid) == 0)
+         DRD_(semaphore_destroy)(arg[1]);
+      break;
+
+   case VG_USERREQ__PRE_SEM_OPEN:
+      DRD_(thread_enter_synchr)(drd_tid);
+      break;
+
+   case VG_USERREQ__POST_SEM_OPEN:
+      if (DRD_(thread_leave_synchr)(drd_tid) == 0)
+         DRD_(semaphore_open)(arg[1], (Char*)arg[2], arg[3], arg[4], arg[5]);
+      break;
+
+   case VG_USERREQ__PRE_SEM_CLOSE:
+      if (DRD_(thread_enter_synchr)(drd_tid) == 0)
+         DRD_(semaphore_close)(arg[1]);
+      break;
+
+   case VG_USERREQ__POST_SEM_CLOSE:
+      DRD_(thread_leave_synchr)(drd_tid);
+      break;
+
+   case VG_USERREQ__PRE_SEM_WAIT:
+      if (DRD_(thread_enter_synchr)(drd_tid) == 0)
+         DRD_(semaphore_pre_wait)(arg[1]);
+      break;
+
+   case VG_USERREQ__POST_SEM_WAIT:
+      if (DRD_(thread_leave_synchr)(drd_tid) == 0)
+         DRD_(semaphore_post_wait)(drd_tid, arg[1], arg[2]);
+      break;
+
+   case VG_USERREQ__PRE_SEM_POST:
+      if (DRD_(thread_enter_synchr)(drd_tid) == 0)
+         DRD_(semaphore_pre_post)(drd_tid, arg[1]);
+      break;
+
+   case VG_USERREQ__POST_SEM_POST:
+      if (DRD_(thread_leave_synchr)(drd_tid) == 0)
+         DRD_(semaphore_post_post)(drd_tid, arg[1], arg[2]);
+      break;
+
+   case VG_USERREQ__PRE_BARRIER_INIT:
+      if (DRD_(thread_enter_synchr)(drd_tid) == 0)
+         DRD_(barrier_init)(arg[1], arg[2], arg[3], arg[4]);
+      break;
+
+   case VG_USERREQ__POST_BARRIER_INIT:
+      DRD_(thread_leave_synchr)(drd_tid);
+      break;
+
+   case VG_USERREQ__PRE_BARRIER_DESTROY:
+      DRD_(thread_enter_synchr)(drd_tid);
+      break;
+
+   case VG_USERREQ__POST_BARRIER_DESTROY:
+      if (DRD_(thread_leave_synchr)(drd_tid) == 0)
+         DRD_(barrier_destroy)(arg[1], arg[2]);
+      break;
+
+   case VG_USERREQ__PRE_BARRIER_WAIT:
+      if (DRD_(thread_enter_synchr)(drd_tid) == 0)
+         DRD_(barrier_pre_wait)(drd_tid, arg[1], arg[2]);
+      break;
+
+   case VG_USERREQ__POST_BARRIER_WAIT:
+      if (DRD_(thread_leave_synchr)(drd_tid) == 0)
+         DRD_(barrier_post_wait)(drd_tid, arg[1], arg[2], arg[3], arg[4]);
+      break;
+
+   case VG_USERREQ__PRE_RWLOCK_INIT:
+      DRD_(rwlock_pre_init)(arg[1], pthread_rwlock);
+      break;
+
+   case VG_USERREQ__POST_RWLOCK_DESTROY:
+      DRD_(rwlock_post_destroy)(arg[1], pthread_rwlock);
+      break;
+
+   case VG_USERREQ__PRE_RWLOCK_RDLOCK:
+      if (DRD_(thread_enter_synchr)(drd_tid) == 0)
+         DRD_(rwlock_pre_rdlock)(arg[1], pthread_rwlock);
+      break;
+
+   case VG_USERREQ__POST_RWLOCK_RDLOCK:
+      if (DRD_(thread_leave_synchr)(drd_tid) == 0)
+         DRD_(rwlock_post_rdlock)(arg[1], pthread_rwlock, arg[2]);
+      break;
+
+   case VG_USERREQ__PRE_RWLOCK_WRLOCK:
+      if (DRD_(thread_enter_synchr)(drd_tid) == 0)
+         DRD_(rwlock_pre_wrlock)(arg[1], pthread_rwlock);
+      break;
+
+   case VG_USERREQ__POST_RWLOCK_WRLOCK:
+      if (DRD_(thread_leave_synchr)(drd_tid) == 0)
+         DRD_(rwlock_post_wrlock)(arg[1], pthread_rwlock, arg[2]);
+      break;
+
+   case VG_USERREQ__PRE_RWLOCK_UNLOCK:
+      if (DRD_(thread_enter_synchr)(drd_tid) == 0)
+         DRD_(rwlock_pre_unlock)(arg[1], pthread_rwlock);
+      break;
+
+   case VG_USERREQ__POST_RWLOCK_UNLOCK:
+      DRD_(thread_leave_synchr)(drd_tid);
+      break;
+
+   case VG_USERREQ__DRD_CLEAN_MEMORY:
+      if (arg[2] > 0)
+         DRD_(clean_memory)(arg[1], arg[2]);
+      break;
+
+   case VG_USERREQ__HELGRIND_ANNOTATION_UNIMP:
+      {
+         /* Note: it is assumed below that the text arg[1] points to is never
+          * freed, e.g. because it points to static data.
+          */
+         UnimpClReqInfo UICR =
+            { DRD_(thread_get_running_tid)(), (Char*)arg[1] };
+         VG_(maybe_record_error)(vg_tid,
+                                 UnimpHgClReq,
+                                 VG_(get_IP)(vg_tid),
+                                 "",
+                                 &UICR);
+      }
+      break;
+
+   case VG_USERREQ__DRD_ANNOTATION_UNIMP:
+      {
+         /* Note: it is assumed below that the text arg[1] points to is never
+          * freed, e.g. because it points to static data.
+          */
+         UnimpClReqInfo UICR =
+            { DRD_(thread_get_running_tid)(), (Char*)arg[1] };
+         VG_(maybe_record_error)(vg_tid,
+                                 UnimpDrdClReq,
+                                 VG_(get_IP)(vg_tid),
+                                 "",
+                                 &UICR);
+      }
+      break;
+
+   default:
+#if 0
+      VG_(message)(Vg_DebugMsg, "Unrecognized client request 0x%lx 0x%lx",
+                   arg[0], arg[1]);
+      tl_assert(0);
+#endif
+      return False;
+   }
+
+   *ret = result;
+   return True;
+}
diff --git a/drd/drd_clientreq.h b/drd/drd_clientreq.h
new file mode 100644
index 0000000..57268cb
--- /dev/null
+++ b/drd/drd_clientreq.h
@@ -0,0 +1,264 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+/*
+ * This header file contains the tool-internal interface for the code that
+ * processes client requests.
+ */
+
+
+#ifndef __DRD_CLIENTREQ_H
+#define __DRD_CLIENTREQ_H
+
+
+#include "drd.h"
+#include "drd_basics.h" /* DRD_() */
+
+
+/*
+ * While the client requests defined in the header file "drd.h" define a
+ * public interface between client programs and the DRD tool, the client
+ * requests defined below are a tool-internal interface. These last client
+ * requests must only be used by the source code in the various *_intercepts.c
+ * source files.
+ */
+enum {
+   /* Declare the address and size of a variable with value
+    * PTHREAD_COND_INITIALIZER.
+    */
+   VG_USERREQ__SET_PTHREAD_COND_INITIALIZER = VG_USERREQ_TOOL_BASE('D', 'r'),
+   /* args: address, size. */
+
+   /* To ask the drd tool to start a new segment in the specified thread. */
+   VG_USERREQ__DRD_START_NEW_SEGMENT,
+   /* args: POSIX thread ID. */
+
+   /* Tell drd the pthread_t of the running thread. */
+   VG_USERREQ__SET_PTHREADID,
+   /* args: pthread_t. */
+   /* Ask drd that a the thread's state transition from */
+   /* VgTs_Zombie to VgTs_Empty is delayed until */
+   /* VG_USERREQ__POST_THREAD_JOIN is performed. */
+   VG_USERREQ__SET_JOINABLE,
+   /* args: pthread_t, Bool */
+
+   /* Tell DRD that the calling thread is about to enter pthread_create(). */
+   VG_USERREQ__ENTERING_PTHREAD_CREATE,
+   /* args: (none) */
+   /* Tell DRD that the calling thread has left pthread_create(). */
+   VG_USERREQ__LEFT_PTHREAD_CREATE,
+   /* args: (none) */
+
+   /* To notify drd that a thread finished because */
+   /* pthread_thread_join() was called on it. */
+   VG_USERREQ__POST_THREAD_JOIN,
+   /* args: pthread_t (joinee) */
+
+   /* To notify drd before a pthread_cancel call. */
+   VG_USERREQ__PRE_THREAD_CANCEL,
+   /* args: pthread_t */
+   /* To notify drd after a pthread_cancel call. */
+   VG_USERREQ__POST_THREAD_CANCEL,
+   /* args: pthread_t, Bool */
+
+   /* to notify the drd tool of a pthread_mutex_init call. */
+   VG_USERREQ__PRE_MUTEX_INIT,
+   /* args: Addr, MutexT */
+   /* to notify the drd tool of a pthread_mutex_init call. */
+   VG_USERREQ__POST_MUTEX_INIT,
+   /* args: Addr */
+   /* to notify the drd tool of a pthread_mutex_destroy call. */
+   VG_USERREQ__PRE_MUTEX_DESTROY,
+   /* args: Addr */
+   /* to notify the drd tool of a pthread_mutex_destroy call. */
+   VG_USERREQ__POST_MUTEX_DESTROY,
+   /* args: Addr, MutexT */
+   /* to notify the drd tool of pthread_mutex_lock calls */
+   VG_USERREQ__PRE_MUTEX_LOCK,
+   /* args: Addr, MutexT, Bool */
+   /* to notify the drd tool of pthread_mutex_lock calls */
+   VG_USERREQ__POST_MUTEX_LOCK,
+   /* args: Addr, Bool */
+   /* to notify the drd tool of pthread_mutex_unlock calls */
+   VG_USERREQ__PRE_MUTEX_UNLOCK,
+   /* args: Addr */
+   /* to notify the drd tool of pthread_mutex_unlock calls */
+   VG_USERREQ__POST_MUTEX_UNLOCK,
+   /* args: Addr */
+   /* to notify the drd tool of a pthread_spin_init/pthread_spin_unlock call */
+   VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK,
+   /* args: Addr */
+   /* to notify the drd tool of a pthread_spin_init/pthread_spin_unlock call */
+   VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK,
+   /* args: Addr */
+
+
+   /* to notify the drd tool of a pthread_cond_init call. */
+   VG_USERREQ__PRE_COND_INIT,
+   /* args: Addr */
+   /* to notify the drd tool of a pthread_cond_init call. */
+   VG_USERREQ__POST_COND_INIT,
+   /* args: Addr */
+   /* to notify the drd tool of a pthread_cond_destroy call. */
+   VG_USERREQ__PRE_COND_DESTROY,
+   /* args: Addr */
+   /* to notify the drd tool of a pthread_cond_destroy call. */
+   VG_USERREQ__POST_COND_DESTROY,
+   /* args: Addr */
+   VG_USERREQ__PRE_COND_WAIT,
+   /* args: Addr cond, Addr mutex, MutexT mt */
+   VG_USERREQ__POST_COND_WAIT,
+   /* args: Addr cond, Addr mutex, Bool took_lock*/
+   VG_USERREQ__PRE_COND_SIGNAL,
+   /* args: Addr cond */
+   VG_USERREQ__POST_COND_SIGNAL,
+   /* args: Addr cond */
+   VG_USERREQ__PRE_COND_BROADCAST,
+   /* args: Addr cond */
+   VG_USERREQ__POST_COND_BROADCAST,
+   /* args: Addr cond */
+
+   /* To notify the drd tool of a sem_init call. */
+   VG_USERREQ__PRE_SEM_INIT,
+   /* args: Addr sem, Word pshared, Word value */
+   /* To notify the drd tool of a sem_init call. */
+   VG_USERREQ__POST_SEM_INIT,
+   /* args: Addr sem */
+   /* To notify the drd tool of a sem_destroy call. */
+   VG_USERREQ__PRE_SEM_DESTROY,
+   /* args: Addr sem */
+   /* To notify the drd tool of a sem_destroy call. */
+   VG_USERREQ__POST_SEM_DESTROY,
+   /* args: Addr sem */
+   /* To notify the drd tool of a sem_open call. */
+   VG_USERREQ__PRE_SEM_OPEN,
+   /* args: Addr name, Word oflag, Word mode, Word value */
+   /* To notify the drd tool of a sem_open call. */
+   VG_USERREQ__POST_SEM_OPEN,
+   /* args: Addr sem, Word oflag, Word mode, Word value */
+   /* To notify the drd tool of a sem_close call. */
+   VG_USERREQ__PRE_SEM_CLOSE,
+   /* args: Addr sem */
+   /* To notify the drd tool of a sem_close call. */
+   VG_USERREQ__POST_SEM_CLOSE,
+   /* args: Addr sem */
+   /* To notify the drd tool of a sem_wait call. */
+   VG_USERREQ__PRE_SEM_WAIT,
+   /* args: Addr sem */
+   /* To notify the drd tool of a sem_wait call. */
+   VG_USERREQ__POST_SEM_WAIT,
+   /* args: Addr sem, Bool waited */
+   /* To notify the drd tool before a sem_post call. */
+   VG_USERREQ__PRE_SEM_POST,
+   /* args: Addr sem */
+   /* To notify the drd tool after a sem_post call. */
+   VG_USERREQ__POST_SEM_POST,
+   /* args: Addr sem, Bool waited */
+
+   /* To notify the drd tool of a pthread_barrier_init call. */
+   VG_USERREQ__PRE_BARRIER_INIT,
+   /* args: Addr barrier, BarrierT type, Word count, Bool reinit */
+   /* To notify the drd tool of a pthread_barrier_init call. */
+   VG_USERREQ__POST_BARRIER_INIT,
+   /* args: Addr barrier, BarrierT type */
+   /* To notify the drd tool of a pthread_barrier_destroy call. */
+   VG_USERREQ__PRE_BARRIER_DESTROY,
+   /* args: Addr barrier, BarrierT type. */
+   /* To notify the drd tool of a pthread_barrier_destroy call. */
+   VG_USERREQ__POST_BARRIER_DESTROY,
+   /* args: Addr barrier, BarrierT type. */
+   /* To notify the drd tool of a pthread_barrier_wait call. */
+   VG_USERREQ__PRE_BARRIER_WAIT,
+   /* args: Addr barrier, BarrierT type. */
+   /* To notify the drd tool of a pthread_barrier_wait call. */
+   VG_USERREQ__POST_BARRIER_WAIT,
+   /* args: Addr barrier, BarrierT type, Word has_waited, Word serializing */
+
+   /* To notify the drd tool of a pthread_rwlock_init call. */
+   VG_USERREQ__PRE_RWLOCK_INIT,
+   /* args: Addr rwlock, RwLockT */
+   /* To notify the drd tool of a pthread_rwlock_destroy call. */
+   VG_USERREQ__POST_RWLOCK_DESTROY,
+   /* args: Addr rwlock, RwLockT */
+   /* To notify the drd tool of a pthread_rwlock_rdlock call. */
+   VG_USERREQ__PRE_RWLOCK_RDLOCK,
+   /* args: Addr rwlock, RwLockT */
+   /* To notify the drd tool of a pthread_rwlock_rdlock call. */
+   VG_USERREQ__POST_RWLOCK_RDLOCK,
+   /* args: Addr rwlock, RwLockT, Bool took_lock */
+   /* To notify the drd tool of a pthread_rwlock_wrlock call. */
+   VG_USERREQ__PRE_RWLOCK_WRLOCK,
+   /* args: Addr rwlock, RwLockT */
+   /* To notify the drd tool of a pthread_rwlock_wrlock call. */
+   VG_USERREQ__POST_RWLOCK_WRLOCK,
+   /* args: Addr rwlock, RwLockT, Bool took_lock */
+   /* To notify the drd tool of a pthread_rwlock_unlock call. */
+   VG_USERREQ__PRE_RWLOCK_UNLOCK,
+   /* args: Addr rwlock, RwLockT */
+   /* To notify the drd tool of a pthread_rwlock_unlock call. */
+   VG_USERREQ__POST_RWLOCK_UNLOCK
+   /* args: Addr rwlock, RwLockT, Bool unlocked */
+
+};
+
+/**
+ * Error checking on POSIX recursive mutexes, POSIX error checking mutexes,
+ * POSIX default mutexes and POSIX spinlocks happens the code in drd_mutex.c.
+ * The values defined below specify the mutex type.
+ */
+typedef enum {
+   mutex_type_unknown          = -1,
+   mutex_type_invalid_mutex    = 0,
+   mutex_type_recursive_mutex  = 1,
+   mutex_type_errorcheck_mutex = 2,
+   mutex_type_default_mutex    = 3,
+   mutex_type_spinlock         = 4,
+} MutexT;
+
+/**
+ * Error checking on POSIX reader/writer locks and user-defined reader/writer
+ * locks happens by the code in drd_rwlock.c. The values defined below specify
+ * the rwlock type.
+ */
+typedef enum {
+   pthread_rwlock = 1,
+   user_rwlock    = 2,
+} RwLockT;
+
+/*
+ * Error checking on POSIX barriers and GOMP barriers happens by the same
+ * code. The integer values defined below specify the type of a barrier with
+ * a given client address.
+ */
+typedef enum {
+   pthread_barrier = 1,
+   gomp_barrier    = 2,
+} BarrierT;
+
+
+void DRD_(clientreq_init)(void);
+
+
+#endif //  __DRD_CLIENTREQ_H
diff --git a/drd/drd_cond.c b/drd/drd_cond.c
new file mode 100644
index 0000000..9565bb7
--- /dev/null
+++ b/drd/drd_cond.c
@@ -0,0 +1,432 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#include "drd_clientobj.h"
+#include "drd_cond.h"
+#include "drd_error.h"
+#include "drd_mutex.h"
+#include "pub_tool_errormgr.h"    /* VG_(maybe_record_error)() */
+#include "pub_tool_libcassert.h"  /* tl_assert()               */
+#include "pub_tool_libcbase.h"    /* VG_(memcmp)()             */
+#include "pub_tool_libcprint.h"   /* VG_(printf)()             */
+#include "pub_tool_machine.h"     /* VG_(get_IP)()             */
+#include "pub_tool_threadstate.h" /* VG_(get_running_tid)()    */
+
+
+/* Local functions. */
+
+static void DRD_(cond_cleanup)(struct cond_info* p);
+
+
+/* Local variables. */
+
+static Bool DRD_(s_report_signal_unlocked) = True;
+static Bool DRD_(s_trace_cond);
+
+
+/* Global variables. */
+
+Addr DRD_(pthread_cond_initializer);
+int DRD_(pthread_cond_initializer_size);
+
+
+/* Function definitions. */
+
+void DRD_(cond_set_report_signal_unlocked)(const Bool r)
+{
+   DRD_(s_report_signal_unlocked) = r;
+}
+
+void DRD_(cond_set_trace)(const Bool trace_cond)
+{
+   DRD_(s_trace_cond) = trace_cond;
+}
+
+static
+void DRD_(cond_initialize)(struct cond_info* const p, const Addr cond)
+{
+   tl_assert(cond != 0);
+   tl_assert(p->a1   == cond);
+   tl_assert(p->type == ClientCondvar);
+
+   p->cleanup       = (void(*)(DrdClientobj*))(DRD_(cond_cleanup));
+   p->delete_thread = 0;
+   p->waiter_count  = 0;
+   p->mutex         = 0;
+}
+
+/**
+ * Free the memory that was allocated by cond_initialize(). Called by
+ * DRD_(clientobj_remove)().
+ */
+static void DRD_(cond_cleanup)(struct cond_info* p)
+{
+   tl_assert(p);
+   if (p->mutex)
+   {
+      struct mutex_info* q;
+      q = &(DRD_(clientobj_get)(p->mutex, ClientMutex)->mutex);
+      {
+         CondDestrErrInfo cde = {
+	    DRD_(thread_get_running_tid)(),
+	    p->a1,
+	    q ? q->a1 : 0,
+	    q ? q->owner : DRD_INVALID_THREADID
+	 };
+         VG_(maybe_record_error)(VG_(get_running_tid)(),
+                                 CondDestrErr,
+                                 VG_(get_IP)(VG_(get_running_tid)()),
+                                 "Destroying condition variable that is being"
+                                 " waited upon",
+                                 &cde);
+      }
+   }
+}
+
+/**
+ * Report that the synchronization object at address 'addr' is of the
+ * wrong type.
+ */
+static void wrong_type(const Addr addr)
+{
+   GenericErrInfo gei = {
+      .tid  = DRD_(thread_get_running_tid)(),
+      .addr = addr,
+   };
+   VG_(maybe_record_error)(VG_(get_running_tid)(),
+                           GenericErr,
+                           VG_(get_IP)(VG_(get_running_tid)()),
+                           "wrong type of synchronization object",
+                           &gei);
+}
+
+static struct cond_info* cond_get_or_allocate(const Addr cond)
+{
+   struct cond_info *p;
+
+   tl_assert(offsetof(DrdClientobj, cond) == 0);
+   p = &(DRD_(clientobj_get)(cond, ClientCondvar)->cond);
+   if (p)
+      return p;
+
+   if (DRD_(clientobj_present)(cond, cond + 1))
+   {
+      wrong_type(cond);
+      return 0;
+   }
+
+   p = &(DRD_(clientobj_add)(cond, ClientCondvar)->cond);
+   DRD_(cond_initialize)(p, cond);
+   return p;
+}
+
+struct cond_info* DRD_(cond_get)(const Addr cond)
+{
+   tl_assert(offsetof(DrdClientobj, cond) == 0);
+   return &(DRD_(clientobj_get)(cond, ClientCondvar)->cond);
+}
+
+/** Called before pthread_cond_init(). */
+void DRD_(cond_pre_init)(const Addr cond)
+{
+   struct cond_info* p;
+
+   if (DRD_(s_trace_cond))
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] cond_init       cond 0x%lx\n",
+                   DRD_(thread_get_running_tid)(),
+                   cond);
+   }
+
+   p = DRD_(cond_get)(cond);
+
+   if (p)
+   {
+      CondErrInfo cei = { .tid = DRD_(thread_get_running_tid)(), .cond = cond };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              CondErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "initialized twice",
+                              &cei);
+   }
+
+   p = cond_get_or_allocate(cond);
+}
+
+/** Called after pthread_cond_destroy(). */
+void DRD_(cond_post_destroy)(const Addr cond)
+{
+   struct cond_info* p;
+
+   if (DRD_(s_trace_cond))
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] cond_destroy    cond 0x%lx\n",
+                   DRD_(thread_get_running_tid)(),
+                   cond);
+   }
+
+   p = DRD_(cond_get)(cond);
+   if (p == 0)
+   {
+      CondErrInfo cei = { .tid = DRD_(thread_get_running_tid)(), .cond = cond };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              CondErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "not a condition variable",
+                              &cei);
+      return;
+   }
+
+   if (p->waiter_count != 0)
+   {
+      CondErrInfo cei = { .tid = DRD_(thread_get_running_tid)(), .cond = cond };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              CondErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "destruction of condition variable being waited"
+                              " upon",
+                              &cei);
+   }
+
+   DRD_(clientobj_remove)(p->a1, ClientCondvar);
+}
+
+/**
+ * Called before pthread_cond_wait(). Note: before this function is called,
+ * mutex_unlock() has already been called from drd_clientreq.c.
+ */
+void DRD_(cond_pre_wait)(const Addr cond, const Addr mutex)
+{
+   struct cond_info* p;
+   struct mutex_info* q;
+
+   if (DRD_(s_trace_cond))
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] cond_pre_wait   cond 0x%lx\n",
+                   DRD_(thread_get_running_tid)(),
+                   cond);
+   }
+
+   p = cond_get_or_allocate(cond);
+   if (!p)
+   {
+      CondErrInfo cei = { .tid = DRD_(thread_get_running_tid)(), .cond = cond };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              CondErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "not a condition variable",
+                              &cei);
+      return;
+   }
+
+   if (p->waiter_count == 0)
+   {
+      p->mutex = mutex;
+   }
+   else if (p->mutex != mutex)
+   {
+      CondWaitErrInfo cwei
+         = { .tid = DRD_(thread_get_running_tid)(),
+             .cond = cond, .mutex1 = p->mutex, .mutex2 = mutex };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              CondWaitErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "Inconsistent association of condition variable"
+                              " and mutex",
+                              &cwei);
+   }
+   tl_assert(p->mutex);
+   q = DRD_(mutex_get)(p->mutex);
+   if (q
+       && q->owner == DRD_(thread_get_running_tid)() && q->recursion_count > 0)
+   {
+      const ThreadId vg_tid = VG_(get_running_tid)();
+      MutexErrInfo MEI = { DRD_(thread_get_running_tid)(),
+                           q->a1, q->recursion_count, q->owner };
+      VG_(maybe_record_error)(vg_tid,
+                              MutexErr,
+                              VG_(get_IP)(vg_tid),
+                              "Mutex locked recursively",
+                              &MEI);
+   }
+   else if (q == 0)
+   {
+      DRD_(not_a_mutex)(p->mutex);
+   }
+
+   ++p->waiter_count;
+}
+
+/**
+ * Called after pthread_cond_wait().
+ */
+void DRD_(cond_post_wait)(const Addr cond)
+{
+   struct cond_info* p;
+
+   if (DRD_(s_trace_cond))
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] cond_post_wait  cond 0x%lx\n",
+                   DRD_(thread_get_running_tid)(),
+                   cond);
+   }
+
+   p = DRD_(cond_get)(cond);
+   if (!p)
+   {
+      struct mutex_info* q;
+      q = &(DRD_(clientobj_get)(p->mutex, ClientMutex)->mutex);
+      {
+	 CondDestrErrInfo cde = {
+	    DRD_(thread_get_running_tid)(),
+	    p->a1,
+	    q ? q->a1 : 0,
+	    q ? q->owner : DRD_INVALID_THREADID
+	 };
+	 VG_(maybe_record_error)(VG_(get_running_tid)(),
+				 CondDestrErr,
+				 VG_(get_IP)(VG_(get_running_tid)()),
+				 "condition variable has been destroyed while"
+				 " being waited upon",
+				 &cde);
+      }
+      return;
+   }
+
+   if (p->waiter_count > 0)
+   {
+      --p->waiter_count;
+      if (p->waiter_count == 0)
+      {
+	 p->mutex = 0;
+      }
+   }
+}
+
+static void cond_signal(const DrdThreadId tid, struct cond_info* const cond_p)
+{
+   const ThreadId vg_tid = VG_(get_running_tid)();
+   const DrdThreadId drd_tid = DRD_(VgThreadIdToDrdThreadId)(vg_tid);
+
+   tl_assert(cond_p);
+
+   if (cond_p->waiter_count > 0)
+   {
+      if (DRD_(s_report_signal_unlocked)
+	  && ! DRD_(mutex_is_locked_by)(cond_p->mutex, drd_tid))
+      {
+	 /*
+	  * A signal is sent while the associated mutex has not been locked.
+	  * This can indicate but is not necessarily a race condition.
+	  */
+	 CondRaceErrInfo cei = { .tid = DRD_(thread_get_running_tid)(),
+				 .cond  = cond_p->a1,
+				 .mutex = cond_p->mutex,
+	 };
+	 VG_(maybe_record_error)(vg_tid,
+				 CondRaceErr,
+				 VG_(get_IP)(vg_tid),
+				 "CondErr",
+				 &cei);
+      }
+   }
+   else
+   {
+      /*
+       * No other thread is waiting for the signal, hence the signal will
+       * be lost. This is normal in a POSIX threads application.
+       */
+   }
+}
+
+static void not_initialized(Addr const cond)
+{
+   CondErrInfo cei = { .tid = DRD_(thread_get_running_tid)(), .cond = cond };
+   VG_(maybe_record_error)(VG_(get_running_tid)(),
+                           CondErr,
+                           VG_(get_IP)(VG_(get_running_tid)()),
+                           "condition variable has not been initialized",
+                           &cei);
+}
+
+/** Called before pthread_cond_signal(). */
+void DRD_(cond_pre_signal)(Addr const cond)
+{
+   struct cond_info* p;
+
+   p = DRD_(cond_get)(cond);
+   if (DRD_(s_trace_cond))
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] cond_signal     cond 0x%lx\n",
+                   DRD_(thread_get_running_tid)(),
+                   cond);
+   }
+
+   tl_assert(DRD_(pthread_cond_initializer));
+   if (!p && VG_(memcmp)((void*)cond, (void*)DRD_(pthread_cond_initializer),
+                         DRD_(pthread_cond_initializer_size)) != 0)
+   {
+      not_initialized(cond);
+      return;
+   }
+
+   if (!p)
+      p = cond_get_or_allocate(cond);
+
+   cond_signal(DRD_(thread_get_running_tid)(), p);
+}
+
+/** Called before pthread_cond_broadcast(). */
+void DRD_(cond_pre_broadcast)(Addr const cond)
+{
+   struct cond_info* p;
+
+   if (DRD_(s_trace_cond))
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] cond_broadcast  cond 0x%lx\n",
+                   DRD_(thread_get_running_tid)(),
+                   cond);
+   }
+
+   p = DRD_(cond_get)(cond);
+   tl_assert(DRD_(pthread_cond_initializer));
+   if (!p && VG_(memcmp)((void*)cond, (void*)DRD_(pthread_cond_initializer),
+                         DRD_(pthread_cond_initializer_size)) != 0)
+   {
+      not_initialized(cond);
+      return;
+   }
+
+   if (!p)
+      p = cond_get_or_allocate(cond);
+
+   cond_signal(DRD_(thread_get_running_tid)(), p);
+}
diff --git a/drd/drd_cond.h b/drd/drd_cond.h
new file mode 100644
index 0000000..7e386ae
--- /dev/null
+++ b/drd/drd_cond.h
@@ -0,0 +1,58 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#ifndef __DRD_COND_H
+#define __DRD_COND_H
+
+
+#include "drd_thread.h"      /* DrdThreadid */
+#include "pub_tool_basics.h" /* Addr        */
+
+
+/* Forward declarations. */
+
+struct cond_info;
+
+
+/* Variable declarations. */
+
+extern Addr DRD_(pthread_cond_initializer);
+extern int DRD_(pthread_cond_initializer_size);
+
+
+/* Function declarations. */
+
+void DRD_(cond_set_report_signal_unlocked)(const Bool r);
+void DRD_(cond_set_trace)(const Bool trace_cond);
+struct cond_info* DRD_(cond_get)(const Addr cond);
+void DRD_(cond_pre_init)(const Addr cond);
+void DRD_(cond_post_destroy)(const Addr cond);
+void DRD_(cond_pre_wait)(const Addr cond, const Addr mutex);
+void DRD_(cond_post_wait)(const Addr cond);
+void DRD_(cond_pre_signal)(const Addr cond);
+void DRD_(cond_pre_broadcast)(const Addr cond);
+
+
+#endif /* __DRD_COND_H */
diff --git a/drd/drd_cond_initializer.c b/drd/drd_cond_initializer.c
new file mode 100644
index 0000000..ab041f0
--- /dev/null
+++ b/drd/drd_cond_initializer.c
@@ -0,0 +1,8 @@
+/* Make the value of PTHREAD_COND_INITIALIZER available to DRD. */
+
+#include "drd_cond.h"
+#include <pthread.h>
+
+static pthread_cond_t pthread_cond_initializer = PTHREAD_COND_INITIALIZER;
+Addr DRD_(pthread_cond_initializer) = (Addr)&pthread_cond_initializer;
+int DRD_(pthread_cond_initializer_size) = sizeof(pthread_cond_initializer);
diff --git a/drd/drd_error.c b/drd/drd_error.c
new file mode 100644
index 0000000..88452bf
--- /dev/null
+++ b/drd/drd_error.c
@@ -0,0 +1,573 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#include "drd_clientobj.h"        /* struct mutex_info        */
+#include "drd_error.h"
+#include "drd_malloc_wrappers.h"
+#include "drd_mutex.h"
+#include "drd_suppression.h"      /* drd_start_suppression()  */
+#include "pub_drd_bitmap.h"       /* LHS_W, ...               */
+#include "pub_tool_vki.h"
+#include "pub_tool_basics.h"
+#include "pub_tool_libcassert.h"  /* tl_assert()              */
+#include "pub_tool_libcbase.h"    /* strlen()                 */
+#include "pub_tool_libcfile.h"    /* VG_(get_startup_wd)()    */
+#include "pub_tool_libcprint.h"   /* VG_(printf)()            */
+#include "pub_tool_machine.h"
+#include "pub_tool_mallocfree.h"  /* VG_(malloc), VG_(free)   */
+#include "pub_tool_threadstate.h" /* VG_(get_pthread_id)()    */
+#include "pub_tool_tooliface.h"   /* VG_(needs_tool_errors)() */
+
+
+/* Local variables. */
+
+static Bool s_show_conflicting_segments = True;
+
+
+void DRD_(set_show_conflicting_segments)(const Bool scs)
+{
+   s_show_conflicting_segments = scs;
+}
+
+/**
+ * Describe the client address a as good as possible, putting the result in ai.
+ */
+static
+void describe_malloced_addr(Addr const a, AddrInfo* const ai)
+{
+   Addr heap_block_start;
+
+   if (DRD_(heap_addrinfo)(a, &heap_block_start, &ai->size, &ai->lastchange))
+   {
+      ai->akind = eMallocd;
+      ai->rwoffset = a - heap_block_start;
+   }
+   else
+   {
+      ai->akind = eUnknown;
+   }
+}
+
+/**
+ * Report where a client synchronization object has been observed for the first
+ * time. The printed call stack will either refer to a pthread_*_init() or a
+ * pthread_*lock() call.
+ */
+static void first_observed(const Addr obj)
+{
+   DrdClientobj* cl;
+
+   cl = DRD_(clientobj_get_any)(obj);
+   if (cl)
+   {
+      tl_assert(cl->any.first_observed_at);
+      VG_(message)(Vg_UserMsg,
+                   "%s 0x%lx was first observed at:\n",
+                   DRD_(clientobj_type_name)(cl->any.type),
+                   obj);
+      VG_(pp_ExeContext)(cl->any.first_observed_at);
+   }
+}
+
+static
+void drd_report_data_race(Error* const err, const DataRaceErrInfo* const dri)
+{
+   AddrInfo ai;
+
+   XArray* /* of HChar */ descr1
+      = VG_(newXA)( VG_(malloc), "drd.error.drdr2.1",
+                    VG_(free), sizeof(HChar) );
+   XArray* /* of HChar */ descr2
+      = VG_(newXA)( VG_(malloc), "drd.error.drdr2.2",
+                    VG_(free), sizeof(HChar) );
+
+   tl_assert(dri);
+   tl_assert(dri->addr);
+   tl_assert(dri->size > 0);
+   tl_assert(descr1);
+   tl_assert(descr2);
+
+   (void) VG_(get_data_description)(descr1, descr2, dri->addr);
+   /* If there's nothing in descr1/2, free them.  Why is it safe to to
+      VG_(indexXA) at zero here?  Because VG_(get_data_description)
+      guarantees to zero terminate descr1/2 regardless of the outcome
+      of the call.  So there's always at least one element in each XA
+      after the call.
+   */
+   if (0 == VG_(strlen)( VG_(indexXA)( descr1, 0 ))) {
+      VG_(deleteXA)( descr1 );
+      descr1 = NULL;
+   }
+   if (0 == VG_(strlen)( VG_(indexXA)( descr2, 0 ))) {
+      VG_(deleteXA)( descr2 );
+      descr2 = NULL;
+   }
+   /* Assume (assert) that VG_(get_data_description) fills in descr1
+      before it fills in descr2 */
+   if (descr1 == NULL)
+      tl_assert(descr2 == NULL);
+   /* So anyway.  Do we have something useful? */
+   if (descr1 == NULL)
+   {
+      /* No.  Do Plan B. */
+      describe_malloced_addr(dri->addr, &ai);
+   }
+   VG_(message)(Vg_UserMsg,
+                "Conflicting %s by thread %d at 0x%08lx size %ld\n",
+                dri->access_type == eStore ? "store" : "load",
+                dri->tid,
+                dri->addr,
+                dri->size);
+   VG_(pp_ExeContext)(VG_(get_error_where)(err));
+   if (descr1 != NULL)
+   {
+      VG_(message)(Vg_UserMsg, "%s\n", (HChar*)VG_(indexXA)(descr1, 0));
+      if (descr2 != NULL)
+         VG_(message)(Vg_UserMsg, "%s\n", (HChar*)VG_(indexXA)(descr2, 0));
+   }
+   else if (ai.akind == eMallocd && ai.lastchange)
+   {
+      VG_(message)(Vg_UserMsg,
+                   "Address 0x%lx is at offset %ld from 0x%lx."
+                   " Allocation context:\n",
+                   dri->addr, ai.rwoffset, dri->addr - ai.rwoffset);
+      VG_(pp_ExeContext)(ai.lastchange);
+   }
+   else
+   {
+      char sect_name[64];
+      VgSectKind sect_kind;
+
+      sect_kind = VG_(DebugInfo_sect_kind)(sect_name, sizeof(sect_name),
+                                           dri->addr);
+      if (sect_kind != Vg_SectUnknown)
+      {
+         VG_(message)(Vg_UserMsg,
+                      "Allocation context: %s section of %s\n",
+                      VG_(pp_SectKind)(sect_kind),
+                      sect_name);
+      }
+      else
+      {
+         VG_(message)(Vg_UserMsg, "Allocation context: unknown.\n");
+      }
+   }
+   if (s_show_conflicting_segments)
+   {
+      DRD_(thread_report_conflicting_segments)(dri->tid,
+                                               dri->addr, dri->size,
+                                               dri->access_type);
+   }
+
+   if (descr2)
+      VG_(deleteXA)(descr2);
+   if (descr1)
+      VG_(deleteXA)(descr1);
+}
+
+/**
+ * Compare two error contexts. The core function VG_(maybe_record_error)()
+ * calls this function to compare error contexts such that errors that occur
+ * repeatedly are only printed once. This function is only called by the core
+ * if the error kind of e1 and e2 matches and if the ExeContext's of e1 and
+ * e2 also match.
+ */
+static Bool drd_compare_error_contexts(VgRes res, Error* e1, Error* e2)
+{
+   tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
+
+   switch (VG_(get_error_kind)(e1))
+   {
+   case DataRaceErr:
+   {
+      const DataRaceErrInfo* const dri1 = VG_(get_error_extra)(e1);
+      const DataRaceErrInfo* const dri2 = VG_(get_error_extra)(e2);
+      return dri1->access_type == dri2->access_type
+	     && dri1->size == dri2->size;
+   }
+   case MutexErr:
+   {
+      const MutexErrInfo* const mei1 = VG_(get_error_extra)(e1);
+      const MutexErrInfo* const mei2 = VG_(get_error_extra)(e2);
+      return mei1->mutex == mei2->mutex;
+   }
+   default:
+      return True;
+   }
+}
+
+/**
+ * Called by the core just before an error message will be printed. Used by
+ * DRD to print the thread number as a preamble.
+ */
+static void drd_tool_error_before_pp(Error* const e)
+{
+   static DrdThreadId s_last_tid_printed = 1;
+   DrdThreadId* err_extra;
+
+   err_extra = VG_(get_error_extra)(e);
+
+   if (err_extra && *err_extra != s_last_tid_printed)
+   {
+      VG_(umsg)("%s:\n", DRD_(thread_get_name)(*err_extra));
+      s_last_tid_printed = *err_extra;
+   }
+}
+
+/** Report an error to the user. */
+static void drd_tool_error_pp(Error* const e)
+{
+   switch (VG_(get_error_kind)(e))
+   {
+   case DataRaceErr: {
+      drd_report_data_race(e, VG_(get_error_extra)(e));
+      break;
+   }
+   case MutexErr: {
+      MutexErrInfo* p = (MutexErrInfo*)(VG_(get_error_extra)(e));
+      tl_assert(p);
+      if (p->recursion_count >= 0)
+      {
+         VG_(message)(Vg_UserMsg,
+                      "%s: mutex 0x%lx, recursion count %d, owner %d.\n",
+                      VG_(get_error_string)(e),
+                      p->mutex,
+                      p->recursion_count,
+                      p->owner);
+      }
+      else
+      {
+         VG_(message)(Vg_UserMsg,
+                      "The object at address 0x%lx is not a mutex.\n",
+                      p->mutex);
+      }
+      VG_(pp_ExeContext)(VG_(get_error_where)(e));
+      first_observed(p->mutex);
+      break;
+   }
+   case CondErr: {
+      CondErrInfo* cdei =(CondErrInfo*)(VG_(get_error_extra)(e));
+      VG_(message)(Vg_UserMsg,
+                   "%s: cond 0x%lx\n",
+                   VG_(get_error_string)(e),
+                   cdei->cond);
+      VG_(pp_ExeContext)(VG_(get_error_where)(e));
+      first_observed(cdei->cond);
+      break;
+   }
+   case CondDestrErr: {
+      CondDestrErrInfo* cdi = (CondDestrErrInfo*)(VG_(get_error_extra)(e));
+      VG_(message)(Vg_UserMsg,
+                   "%s: cond 0x%lx, mutex 0x%lx locked by thread %d\n",
+                   VG_(get_error_string)(e),
+                   cdi->cond, cdi->mutex,
+                   cdi->owner);
+      VG_(pp_ExeContext)(VG_(get_error_where)(e));
+      first_observed(cdi->mutex);
+      break;
+   }
+   case CondRaceErr: {
+      CondRaceErrInfo* cei = (CondRaceErrInfo*)(VG_(get_error_extra)(e));
+      VG_(message)(Vg_UserMsg,
+                   "Probably a race condition: condition variable 0x%lx has"
+                   " been signaled but the associated mutex 0x%lx is not"
+                   " locked by the signalling thread.\n",
+                   cei->cond, cei->mutex);
+      VG_(pp_ExeContext)(VG_(get_error_where)(e));
+      first_observed(cei->cond);
+      first_observed(cei->mutex);
+      break;
+   }
+   case CondWaitErr: {
+      CondWaitErrInfo* cwei = (CondWaitErrInfo*)(VG_(get_error_extra)(e));
+      VG_(message)(Vg_UserMsg,
+                   "%s: condition variable 0x%lx, mutexes 0x%lx and 0x%lx\n",
+                   VG_(get_error_string)(e),
+                   cwei->cond,
+                   cwei->mutex1,
+                   cwei->mutex2);
+      VG_(pp_ExeContext)(VG_(get_error_where)(e));
+      first_observed(cwei->cond);
+      first_observed(cwei->mutex1);
+      first_observed(cwei->mutex2);
+      break;
+   }
+   case SemaphoreErr: {
+      SemaphoreErrInfo* sei = (SemaphoreErrInfo*)(VG_(get_error_extra)(e));
+      tl_assert(sei);
+      VG_(message)(Vg_UserMsg,
+                   "%s: semaphore 0x%lx\n",
+                   VG_(get_error_string)(e),
+                   sei->semaphore);
+      VG_(pp_ExeContext)(VG_(get_error_where)(e));
+      first_observed(sei->semaphore);
+      break;
+   }
+   case BarrierErr: {
+      BarrierErrInfo* bei = (BarrierErrInfo*)(VG_(get_error_extra)(e));
+      tl_assert(bei);
+      VG_(message)(Vg_UserMsg,
+                   "%s: barrier 0x%lx\n",
+                   VG_(get_error_string)(e),
+                   bei->barrier);
+      VG_(pp_ExeContext)(VG_(get_error_where)(e));
+      if (bei->other_context)
+      {
+         VG_(message)(Vg_UserMsg,
+                      "Conflicting wait call by thread %d:\n",
+                      bei->other_tid);
+         VG_(pp_ExeContext)(bei->other_context);
+      }
+      first_observed(bei->barrier);
+      break;
+   }
+   case RwlockErr: {
+      RwlockErrInfo* p = (RwlockErrInfo*)(VG_(get_error_extra)(e));
+      tl_assert(p);
+      VG_(message)(Vg_UserMsg,
+                   "%s: rwlock 0x%lx.\n",
+                   VG_(get_error_string)(e),
+                   p->rwlock);
+      VG_(pp_ExeContext)(VG_(get_error_where)(e));
+      first_observed(p->rwlock);
+      break;
+   }
+   case HoldtimeErr: {
+      HoldtimeErrInfo* p =(HoldtimeErrInfo*)(VG_(get_error_extra)(e));
+      tl_assert(p);
+      tl_assert(p->acquired_at);
+      VG_(message)(Vg_UserMsg, "Acquired at:\n");
+      VG_(pp_ExeContext)(p->acquired_at);
+      VG_(message)(Vg_UserMsg,
+                   "Lock on %s 0x%lx was held during %d ms (threshold: %d ms).\n",
+                   VG_(get_error_string)(e),
+                   p->synchronization_object,
+                   p->hold_time_ms,
+                   p->threshold_ms);
+      VG_(pp_ExeContext)(VG_(get_error_where)(e));
+      first_observed(p->synchronization_object);
+      break;
+   }
+   case GenericErr: {
+      GenericErrInfo* gei = (GenericErrInfo*)(VG_(get_error_extra)(e));
+      VG_(message)(Vg_UserMsg, "%s\n", VG_(get_error_string)(e));
+      VG_(pp_ExeContext)(VG_(get_error_where)(e));
+      if (gei->addr)
+	 first_observed(gei->addr);
+      break;
+   }
+   case InvalidThreadId: {
+      InvalidThreadIdInfo* iti =(InvalidThreadIdInfo*)(VG_(get_error_extra)(e));
+      VG_(message)(Vg_UserMsg,
+                   "%s 0x%llx\n", VG_(get_error_string)(e), iti->ptid);
+      VG_(pp_ExeContext)(VG_(get_error_where)(e));
+      break;
+   }
+   case UnimpHgClReq: {
+      UnimpClReqInfo* uicr =(UnimpClReqInfo*)(VG_(get_error_extra)(e));
+      VG_(message)(Vg_UserMsg,
+                   "The annotation macro %s has not yet been implemented in"
+                   " <valgrind/helgrind.h>\n",
+                   /*VG_(get_error_string)(e),*/ uicr->descr);
+      VG_(pp_ExeContext)(VG_(get_error_where)(e));
+      break;
+   }
+   case UnimpDrdClReq: {
+      UnimpClReqInfo* uicr =(UnimpClReqInfo*)(VG_(get_error_extra)(e));
+      VG_(message)(Vg_UserMsg,
+                   "The annotation macro %s has not yet been implemented in"
+                   " <valgrind/drd.h>\n",
+                   uicr->descr);
+      VG_(pp_ExeContext)(VG_(get_error_where)(e));
+      break;
+   }
+   default:
+      VG_(message)(Vg_UserMsg,
+                   "%s\n",
+                   VG_(get_error_string)(e));
+      VG_(pp_ExeContext)(VG_(get_error_where)(e));
+      break;
+   }
+}
+
+static UInt drd_tool_error_update_extra(Error* e)
+{
+   switch (VG_(get_error_kind)(e))
+   {
+   case DataRaceErr:
+      return sizeof(DataRaceErrInfo);
+   case MutexErr:
+      return sizeof(MutexErrInfo);
+   case CondErr:
+      return sizeof(CondErrInfo);
+   case CondDestrErr:
+      return sizeof(CondDestrErrInfo);
+   case CondRaceErr:
+      return sizeof(CondRaceErrInfo);
+   case CondWaitErr:
+      return sizeof(CondWaitErrInfo);
+   case SemaphoreErr:
+      return sizeof(SemaphoreErrInfo);
+   case BarrierErr:
+      return sizeof(BarrierErrInfo);
+   case RwlockErr:
+      return sizeof(RwlockErrInfo);
+   case HoldtimeErr:
+      return sizeof(HoldtimeErrInfo);
+   case GenericErr:
+      return sizeof(GenericErrInfo);
+   case InvalidThreadId:
+      return sizeof(InvalidThreadIdInfo);
+   case UnimpHgClReq:
+      return sizeof(UnimpClReqInfo);
+   case UnimpDrdClReq:
+      return sizeof(UnimpClReqInfo);
+   default:
+      tl_assert(False);
+      break;
+   }
+}
+
+/**
+ * Parse suppression name.
+ *
+ * The suppression types recognized by DRD are the same types as the error
+ * types supported by DRD. So try to match the suppression name against the
+ * names of DRD error types.
+ */
+static Bool drd_is_recognized_suppression(Char* const name, Supp* const supp)
+{
+   DrdErrorKind skind = 0;
+
+   if (VG_(strcmp)(name, STR_DataRaceErr) == 0)
+      skind = DataRaceErr;
+   else if (VG_(strcmp)(name, STR_MutexErr) == 0)
+      skind = MutexErr;
+   else if (VG_(strcmp)(name, STR_CondErr) == 0)
+      skind = CondErr;
+   else if (VG_(strcmp)(name, STR_CondDestrErr) == 0)
+      skind = CondDestrErr;
+   else if (VG_(strcmp)(name, STR_CondRaceErr) == 0)
+      skind = CondRaceErr;
+   else if (VG_(strcmp)(name, STR_CondWaitErr) == 0)
+      skind = CondWaitErr;
+   else if (VG_(strcmp)(name, STR_SemaphoreErr) == 0)
+      skind = SemaphoreErr;
+   else if (VG_(strcmp)(name, STR_BarrierErr) == 0)
+      skind = BarrierErr;
+   else if (VG_(strcmp)(name, STR_RwlockErr) == 0)
+      skind = RwlockErr;
+   else if (VG_(strcmp)(name, STR_HoldtimeErr) == 0)
+      skind = HoldtimeErr;
+   else if (VG_(strcmp)(name, STR_GenericErr) == 0)
+      skind = GenericErr;
+   else if (VG_(strcmp)(name, STR_InvalidThreadId) == 0)
+      skind = InvalidThreadId;
+   else if (VG_(strcmp)(name, STR_UnimpHgClReq) == 0)
+      skind = UnimpHgClReq;
+   else if (VG_(strcmp)(name, STR_UnimpDrdClReq) == 0)
+      skind = UnimpDrdClReq;
+   else
+      return False;
+
+   VG_(set_supp_kind)(supp, skind);
+   return True;
+}
+
+/**
+ * Read additional suppression information from the suppression file.
+ *
+ * None of the suppression patterns recognized by DRD has 'extra' lines
+ * of information in the suppression file, so just return True to indicate
+ * that reading the 'extra' lines succeeded.
+ */
+static
+Bool drd_read_extra_suppression_info(Int fd, Char** bufpp,
+                                     SizeT* nBufp, Supp* supp)
+{
+   return True;
+}
+
+/**
+ * Determine whether or not the types of the given error message and the
+ * given suppression match.
+ */
+static Bool drd_error_matches_suppression(Error* const e, Supp* const supp)
+{
+   return VG_(get_supp_kind)(supp) == VG_(get_error_kind)(e);
+}
+
+static Char* drd_get_error_name(Error* e)
+{
+   switch (VG_(get_error_kind)(e))
+   {
+   case DataRaceErr:  return VGAPPEND(STR_, DataRaceErr);
+   case MutexErr:     return VGAPPEND(STR_, MutexErr);
+   case CondErr:      return VGAPPEND(STR_, CondErr);
+   case CondDestrErr: return VGAPPEND(STR_, CondDestrErr);
+   case CondRaceErr:  return VGAPPEND(STR_, CondRaceErr);
+   case CondWaitErr:  return VGAPPEND(STR_, CondWaitErr);
+   case SemaphoreErr: return VGAPPEND(STR_, SemaphoreErr);
+   case BarrierErr:   return VGAPPEND(STR_, BarrierErr);
+   case RwlockErr:    return VGAPPEND(STR_, RwlockErr);
+   case HoldtimeErr:  return VGAPPEND(STR_, HoldtimeErr);
+   case GenericErr:   return VGAPPEND(STR_, GenericErr);
+   case InvalidThreadId: return VGAPPEND(STR_, InvalidThreadId);
+   case UnimpHgClReq:  return VGAPPEND(STR_, UnimpHgClReq);
+   case UnimpDrdClReq: return VGAPPEND(STR_, UnimpDrdClReq);
+   default:
+      tl_assert(0);
+   }
+   return 0;
+}
+
+/**
+ * Return extra suppression information.
+ *
+ * Invoked while printing a suppression pattern because the user
+ * specified --gen-suppressions=yes or all on the command line. DRD does not
+ * define any 'extra' suppression information.
+ */
+static
+Bool drd_get_extra_suppression_info(Error* e,
+                                    /*OUT*/Char* buf, Int nBuf)
+{
+   return False;
+}
+
+/** Tell the Valgrind core about DRD's error handlers. */
+void DRD_(register_error_handlers)(void)
+{
+   VG_(needs_tool_errors)(drd_compare_error_contexts,
+                          drd_tool_error_before_pp,
+                          drd_tool_error_pp,
+                          False,
+                          drd_tool_error_update_extra,
+                          drd_is_recognized_suppression,
+                          drd_read_extra_suppression_info,
+                          drd_error_matches_suppression,
+                          drd_get_error_name,
+                          drd_get_extra_suppression_info);
+}
diff --git a/drd/drd_error.h b/drd/drd_error.h
new file mode 100644
index 0000000..a900291
--- /dev/null
+++ b/drd/drd_error.h
@@ -0,0 +1,185 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#ifndef __DRD_ERROR_H
+#define __DRD_ERROR_H
+
+
+#include "pub_drd_bitmap.h"     // BmAccessTypeT
+#include "drd_thread.h"         // DrdThreadId
+#include "pub_tool_basics.h"    // SizeT
+#include "pub_tool_debuginfo.h" // SegInfo
+#include "pub_tool_errormgr.h"  // ExeContext
+
+
+/* DRD error types. */
+
+typedef enum {
+#define STR_DataRaceErr  "ConflictingAccess"
+   DataRaceErr    = 1,
+#define STR_MutexErr     "MutexErr"
+   MutexErr       = 2,
+#define STR_CondErr      "CondErr"
+   CondErr        = 3,
+#define STR_CondDestrErr "CondDestrErr"
+   CondDestrErr   = 4,
+#define STR_CondRaceErr  "CondRaceErr"
+   CondRaceErr    = 5,
+#define STR_CondWaitErr  "CondWaitErr"
+   CondWaitErr    = 6,
+#define STR_SemaphoreErr "SemaphoreErr"
+   SemaphoreErr   = 7,
+#define STR_BarrierErr   "BarrierErr"
+   BarrierErr     = 8,
+#define STR_RwlockErr    "RwlockErr"
+   RwlockErr      = 9,
+#define STR_HoldtimeErr  "HoldtimeErr"
+   HoldtimeErr    = 10,
+#define STR_GenericErr   "GenericErr"
+   GenericErr     = 11,
+#define STR_InvalidThreadId "InvalidThreadId"
+   InvalidThreadId = 12,
+#define STR_UnimpHgClReq  "UnimpHgClReq"
+   UnimpHgClReq   = 13,
+#define STR_UnimpDrdClReq "UnimpDrdClReq"
+   UnimpDrdClReq  = 14,
+} DrdErrorKind;
+
+/* The classification of a faulting address. */
+typedef
+enum {
+   //Undescribed,   // as-yet unclassified
+   eStack,
+   eUnknown,       // classification yielded nothing useful
+   //Freed,
+   eMallocd,
+   eSegment,       // in a segment (as defined in pub_tool_debuginfo.h)
+   //UserG,         // in a user-defined block
+   //Mempool,       // in a mempool
+   //Register,      // in a register;  for Param errors only
+}
+   AddrKind;
+
+/* Records info about a faulting address. */
+typedef
+struct {                      // Used by:
+   AddrKind    akind;         //   ALL
+   SizeT       size;          //   ALL
+   PtrdiffT    rwoffset;      //   ALL
+   ExeContext* lastchange;    //   Mallocd
+   DrdThreadId stack_tid;     //   Stack
+   DebugInfo*  debuginfo;     //   Segment
+   Char        name[256];     //   Segment
+   Char        descr[256];    //   Segment
+} AddrInfo;
+
+/*
+ * NOTE: the first member of each error info structure MUST be the thread ID
+ * in which the error has been observed.
+ */
+typedef struct {
+   DrdThreadId   tid;         // Thread ID of the running thread.
+   Addr          addr;        // Conflicting address in current thread.
+   SizeT         size;        // Size in bytes of conflicting operation.
+   BmAccessTypeT access_type; // Access type: load or store.
+} DataRaceErrInfo;
+
+typedef struct {
+   DrdThreadId tid;
+   Addr        mutex;
+   Int         recursion_count;
+   DrdThreadId owner;
+} MutexErrInfo;
+
+typedef struct {
+   DrdThreadId tid;
+   Addr        cond;
+} CondErrInfo;
+
+typedef struct {
+   DrdThreadId tid;
+   Addr        cond;
+   Addr        mutex;
+   DrdThreadId owner;
+} CondDestrErrInfo;
+
+typedef struct {
+   DrdThreadId tid;
+   Addr        cond;
+   Addr        mutex;
+} CondRaceErrInfo;
+
+typedef struct {
+   DrdThreadId tid;
+   Addr        cond;
+   Addr        mutex1;
+   Addr        mutex2;
+} CondWaitErrInfo;
+
+typedef struct {
+   DrdThreadId tid;
+   Addr        semaphore;
+} SemaphoreErrInfo;
+
+typedef struct {
+   DrdThreadId tid;
+   Addr        barrier;
+   DrdThreadId other_tid;
+   ExeContext* other_context;
+} BarrierErrInfo;
+
+typedef struct {
+   DrdThreadId tid;
+   Addr        rwlock;
+} RwlockErrInfo;
+
+typedef struct {
+   DrdThreadId tid;
+   Addr        synchronization_object;
+   ExeContext* acquired_at;
+   UInt        hold_time_ms;
+   UInt        threshold_ms;
+} HoldtimeErrInfo;
+
+typedef struct {
+   DrdThreadId tid;
+   Addr        addr;
+} GenericErrInfo;
+
+typedef struct {
+   DrdThreadId tid;
+   ULong       ptid;
+} InvalidThreadIdInfo;
+
+typedef struct {
+   DrdThreadId tid;
+   Char*       descr;
+} UnimpClReqInfo;
+
+void DRD_(set_show_conflicting_segments)(const Bool scs);
+void DRD_(register_error_handlers)(void);
+
+
+#endif /* __DRD_ERROR_H */
diff --git a/drd/drd_hb.c b/drd/drd_hb.c
new file mode 100644
index 0000000..6b7151f
--- /dev/null
+++ b/drd/drd_hb.c
@@ -0,0 +1,261 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#include "drd_clientobj.h"
+#include "drd_hb.h"
+#include "drd_error.h"
+#include "pub_tool_errormgr.h"    /* VG_(maybe_record_error)() */
+#include "pub_tool_libcassert.h"  /* tl_assert()               */
+#include "pub_tool_libcprint.h"   /* VG_(printf)()             */
+#include "pub_tool_machine.h"     /* VG_(get_IP)()             */
+#include "pub_tool_mallocfree.h"  /* VG_(malloc)(), VG_(free)()*/
+#include "pub_tool_threadstate.h" /* VG_(get_running_tid)()    */
+
+
+/* Type definitions. */
+
+/** Per-thread hb information. */
+struct hb_thread_info
+{
+   UWord       tid; // A DrdThreadId declared as UWord because
+                    // this member variable is the key of an OSet.
+   Segment*    sg;  // Segment created before most recent
+                    // ANNOTATE_HAPPENS_BEFORE().
+};
+
+
+/* Local functions. */
+
+static void DRD_(hb_cleanup)(struct hb_info* p);
+
+
+/* Local variables. */
+
+static Bool DRD_(s_trace_hb);
+
+
+/* Function definitions. */
+
+void DRD_(hb_set_trace)(const Bool trace_hb)
+{
+   DRD_(s_trace_hb) = trace_hb;
+}
+
+/**
+ * Initialize the structure *p with the specified thread ID.
+ */
+static
+void DRD_(hb_thread_initialize)(struct hb_thread_info* const p,
+                                  const DrdThreadId tid)
+{
+   p->tid  = tid;
+   p->sg   = 0;
+}
+
+/**
+ * Deallocate the memory that is owned by members of struct hb_thread_info.
+ */
+static void DRD_(hb_thread_destroy)(struct hb_thread_info* const p)
+{
+   tl_assert(p);
+   DRD_(sg_put)(p->sg);
+}
+
+static
+void DRD_(hb_initialize)(struct hb_info* const p, const Addr hb)
+{
+   tl_assert(hb != 0);
+   tl_assert(p->a1   == hb);
+   tl_assert(p->type == ClientHbvar);
+
+   p->cleanup       = (void(*)(DrdClientobj*))(DRD_(hb_cleanup));
+   p->delete_thread = 0;
+   p->oset          = VG_(OSetGen_Create)(0, 0, VG_(malloc), "drd.hb",
+                                          VG_(free));
+}
+
+/**
+ * Free the memory that was allocated by hb_initialize(). Called by
+ * DRD_(clientobj_remove)().
+ */
+static void DRD_(hb_cleanup)(struct hb_info* p)
+{
+   struct hb_thread_info* r;
+
+   tl_assert(p);
+   VG_(OSetGen_ResetIter)(p->oset);
+   for ( ; (r = VG_(OSetGen_Next)(p->oset)) != 0; )
+      DRD_(hb_thread_destroy)(r);
+   VG_(OSetGen_Destroy)(p->oset);
+}
+
+/**
+ * Report that the synchronization object at address 'addr' is of the
+ * wrong type.
+ */
+static void wrong_type(const Addr addr)
+{
+   GenericErrInfo gei = {
+      .tid  = DRD_(thread_get_running_tid)(),
+      .addr = addr,
+   };
+   VG_(maybe_record_error)(VG_(get_running_tid)(),
+                           GenericErr,
+                           VG_(get_IP)(VG_(get_running_tid)()),
+                           "wrong type of synchronization object",
+                           &gei);
+}
+
+struct hb_info* DRD_(hb_get_or_allocate)(const Addr hb)
+{
+   struct hb_info *p;
+
+   tl_assert(offsetof(DrdClientobj, hb) == 0);
+   p = &(DRD_(clientobj_get)(hb, ClientHbvar)->hb);
+   if (p)
+      return p;
+
+   if (DRD_(clientobj_present)(hb, hb + 1))
+   {
+      wrong_type(hb);
+      return 0;
+   }
+
+   p = &(DRD_(clientobj_add)(hb, ClientHbvar)->hb);
+   DRD_(hb_initialize)(p, hb);
+   return p;
+}
+
+struct hb_info* DRD_(hb_get)(const Addr hb)
+{
+   tl_assert(offsetof(DrdClientobj, hb) == 0);
+   return &(DRD_(clientobj_get)(hb, ClientHbvar)->hb);
+}
+
+/** Called because of a happens-before annotation. */
+void DRD_(hb_happens_before)(const DrdThreadId tid, Addr const hb)
+{
+   const ThreadId vg_tid = VG_(get_running_tid)();
+   const DrdThreadId drd_tid = DRD_(VgThreadIdToDrdThreadId)(vg_tid);
+   const UWord word_tid = tid;
+   struct hb_info* p;
+   struct hb_thread_info* q;
+
+   p = DRD_(hb_get_or_allocate)(hb);
+   if (DRD_(s_trace_hb))
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] happens_before 0x%lx\n",
+                   DRD_(thread_get_running_tid)(),
+                   hb);
+   }
+
+   if (!p)
+      return;
+
+   /* Allocate the per-thread data structure if necessary. */
+   q = VG_(OSetGen_Lookup)(p->oset, &word_tid);
+   if (!q)
+   {
+      q = VG_(OSetGen_AllocNode)(p->oset, sizeof(*q));
+      DRD_(hb_thread_initialize)(q, tid);
+      VG_(OSetGen_Insert)(p->oset, q);
+      tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q);
+   }
+
+   /*
+    * Store a pointer to the latest segment of the current thread in the
+    * per-thread data structure.
+    */
+   DRD_(thread_get_latest_segment)(&q->sg, tid);
+   DRD_(thread_new_segment)(drd_tid);
+}
+
+/** Called because of a happens-after annotation. */
+void DRD_(hb_happens_after)(const DrdThreadId tid, const Addr hb)
+{
+   struct hb_info* p;
+   struct hb_thread_info* q;
+   VectorClock old_vc;
+
+   p = DRD_(hb_get_or_allocate)(hb);
+
+   if (DRD_(s_trace_hb))
+   {
+      VG_(message)(Vg_UserMsg, "[%d] happens_after 0x%lx\n",
+                   DRD_(thread_get_running_tid)(), hb);
+   }
+
+   if (!p)
+      return;
+
+   DRD_(thread_new_segment)(tid);
+
+   /*
+    * Combine all vector clocks that were stored because of happens-before
+    * annotations with the vector clock of the current thread.
+    */
+   DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[tid].last->vc);
+   VG_(OSetGen_ResetIter)(p->oset);
+   for ( ; (q = VG_(OSetGen_Next)(p->oset)) != 0; )
+   {
+      if (q->tid != tid)
+      {
+         tl_assert(q->sg);
+         DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, &q->sg->vc);
+      }
+   }
+   DRD_(thread_update_conflict_set)(tid, &old_vc);
+   DRD_(vc_cleanup)(&old_vc);
+}
+
+/** Called because of a happens-done annotation. */
+void DRD_(hb_happens_done)(const DrdThreadId tid, const Addr hb)
+{
+   struct hb_info* p;
+
+   if (DRD_(s_trace_hb))
+   {
+      VG_(message)(Vg_UserMsg, "[%d] happens_done  0x%lx\n",
+                   DRD_(thread_get_running_tid)(), hb);
+   }
+
+   p = DRD_(hb_get)(hb);
+   if (!p)
+   {
+      GenericErrInfo gei = {
+	 .tid = DRD_(thread_get_running_tid)(),
+	 .addr = hb,
+      };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              GenericErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "missing happens-before annotation",
+                              &gei);
+      return;
+   }
+
+   DRD_(clientobj_remove)(p->a1, ClientHbvar);
+}
diff --git a/drd/drd_hb.h b/drd/drd_hb.h
new file mode 100644
index 0000000..62c6477
--- /dev/null
+++ b/drd/drd_hb.h
@@ -0,0 +1,51 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#ifndef __DRD_HB_H
+#define __DRD_HB_H
+
+
+#include "drd_thread.h"      /* DrdThreadid */
+#include "pub_tool_basics.h" /* Addr        */
+
+
+/* Forward declarations. */
+
+struct hb_info;
+
+
+/* Function declarations. */
+
+void DRD_(hb_set_trace)(const Bool trace_hb);
+struct hb_info* DRD_(hb_get)(const Addr hb);
+struct hb_info* DRD_(hb_get_or_allocate)(const Addr hb);
+void DRD_(hb_init)(const Addr hb);
+void DRD_(hb_destroy)(const Addr hb);
+void DRD_(hb_happens_after)(const DrdThreadId tid, const Addr hb);
+void DRD_(hb_happens_before)(const DrdThreadId tid, const Addr hb);
+void DRD_(hb_happens_done)(const DrdThreadId tid, const Addr hb);
+
+
+#endif /* __DRD_HB_H */
diff --git a/drd/drd_load_store.c b/drd/drd_load_store.c
new file mode 100644
index 0000000..74ef230
--- /dev/null
+++ b/drd/drd_load_store.c
@@ -0,0 +1,619 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#include "drd_bitmap.h"
+#include "drd_thread_bitmap.h"
+#include "drd_vc.h"            /* DRD_(vc_snprint)() */
+
+/* Include several source files here in order to allow the compiler to */
+/* do more inlining.                                                   */
+#include "drd_bitmap.c"
+#include "drd_load_store.h"
+#include "drd_segment.c"
+#include "drd_thread.c"
+#include "drd_vc.c"
+#include "libvex_guest_offsets.h"
+
+
+/* STACK_POINTER_OFFSET: VEX register offset for the stack pointer register. */
+#if defined(VGA_x86)
+#define STACK_POINTER_OFFSET OFFSET_x86_ESP
+#elif defined(VGA_amd64)
+#define STACK_POINTER_OFFSET OFFSET_amd64_RSP
+#elif defined(VGA_ppc32)
+#define STACK_POINTER_OFFSET OFFSET_ppc32_GPR1
+#elif defined(VGA_ppc64)
+#define STACK_POINTER_OFFSET OFFSET_ppc64_GPR1
+#elif defined(VGA_arm)
+#define STACK_POINTER_OFFSET OFFSET_arm_R13
+#else
+#error Unknown architecture.
+#endif
+
+
+/* Local variables. */
+
+static Bool s_check_stack_accesses = False;
+static Bool s_first_race_only      = False;
+
+
+/* Function definitions. */
+
+Bool DRD_(get_check_stack_accesses)()
+{
+   return s_check_stack_accesses;
+}
+
+void DRD_(set_check_stack_accesses)(const Bool c)
+{
+   tl_assert(c == False || c == True);
+   s_check_stack_accesses = c;
+}
+
+Bool DRD_(get_first_race_only)()
+{
+   return s_first_race_only;
+}
+
+void DRD_(set_first_race_only)(const Bool fro)
+{
+   tl_assert(fro == False || fro == True);
+   s_first_race_only = fro;
+}
+
+void DRD_(trace_mem_access)(const Addr addr, const SizeT size,
+                            const BmAccessTypeT access_type)
+{
+   if (DRD_(is_any_traced)(addr, addr + size))
+   {
+      char* vc;
+
+      vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(DRD_(thread_get_running_tid)()));
+      VG_(message)(Vg_UserMsg,
+                   "%s 0x%lx size %ld (thread %d / vc %s)\n",
+                   access_type == eLoad
+                   ? "load "
+                   : access_type == eStore
+                   ? "store"
+                   : access_type == eStart
+                   ? "start"
+                   : access_type == eEnd
+                   ? "end  "
+                   : "????",
+                   addr,
+                   size,
+                   DRD_(thread_get_running_tid)(),
+                   vc);
+      VG_(free)(vc);
+      VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
+                                 VG_(clo_backtrace_size));
+      tl_assert(DRD_(DrdThreadIdToVgThreadId)(DRD_(thread_get_running_tid)())
+                == VG_(get_running_tid)());
+   }
+}
+
+static VG_REGPARM(2) void drd_trace_mem_load(const Addr addr, const SizeT size)
+{
+   return DRD_(trace_mem_access)(addr, size, eLoad);
+}
+
+static VG_REGPARM(2) void drd_trace_mem_store(const Addr addr,const SizeT size)
+{
+   return DRD_(trace_mem_access)(addr, size, eStore);
+}
+
+static void drd_report_race(const Addr addr, const SizeT size,
+                            const BmAccessTypeT access_type)
+{
+   DataRaceErrInfo drei;
+
+   drei.tid  = DRD_(thread_get_running_tid)();
+   drei.addr = addr;
+   drei.size = size;
+   drei.access_type = access_type;
+   VG_(maybe_record_error)(VG_(get_running_tid)(),
+                           DataRaceErr,
+                           VG_(get_IP)(VG_(get_running_tid)()),
+                           "Conflicting accesses",
+                           &drei);
+
+   if (s_first_race_only)
+   {
+      DRD_(start_suppression)(addr, addr + size, "first race only");
+   }
+}
+
+VG_REGPARM(2) void DRD_(trace_load)(Addr addr, SizeT size)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   /* The assert below has been commented out because of performance reasons.*/
+   tl_assert(DRD_(thread_get_running_tid)()
+             == DRD_(VgThreadIdToDrdThreadId)(VG_(get_running_tid())));
+#endif
+
+   if (DRD_(running_thread_is_recording_loads)()
+       && (s_check_stack_accesses
+           || ! DRD_(thread_address_on_stack)(addr))
+       && bm_access_load_triggers_conflict(addr, addr + size)
+       && ! DRD_(is_suppressed)(addr, addr + size))
+   {
+      drd_report_race(addr, size, eLoad);
+   }
+}
+
+static VG_REGPARM(1) void drd_trace_load_1(Addr addr)
+{
+   if (DRD_(running_thread_is_recording_loads)()
+       && (s_check_stack_accesses
+           || ! DRD_(thread_address_on_stack)(addr))
+       && bm_access_load_1_triggers_conflict(addr)
+       && ! DRD_(is_suppressed)(addr, addr + 1))
+   {
+      drd_report_race(addr, 1, eLoad);
+   }
+}
+
+static VG_REGPARM(1) void drd_trace_load_2(Addr addr)
+{
+   if (DRD_(running_thread_is_recording_loads)()
+       && (s_check_stack_accesses
+           || ! DRD_(thread_address_on_stack)(addr))
+       && bm_access_load_2_triggers_conflict(addr)
+       && ! DRD_(is_suppressed)(addr, addr + 2))
+   {
+      drd_report_race(addr, 2, eLoad);
+   }
+}
+
+static VG_REGPARM(1) void drd_trace_load_4(Addr addr)
+{
+   if (DRD_(running_thread_is_recording_loads)()
+       && (s_check_stack_accesses
+           || ! DRD_(thread_address_on_stack)(addr))
+       && bm_access_load_4_triggers_conflict(addr)
+       && ! DRD_(is_suppressed)(addr, addr + 4))
+   {
+      drd_report_race(addr, 4, eLoad);
+   }
+}
+
+static VG_REGPARM(1) void drd_trace_load_8(Addr addr)
+{
+   if (DRD_(running_thread_is_recording_loads)()
+       && (s_check_stack_accesses
+           || ! DRD_(thread_address_on_stack)(addr))
+       && bm_access_load_8_triggers_conflict(addr)
+       && ! DRD_(is_suppressed)(addr, addr + 8))
+   {
+      drd_report_race(addr, 8, eLoad);
+   }
+}
+
+VG_REGPARM(2) void DRD_(trace_store)(Addr addr, SizeT size)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   /* The assert below has been commented out because of performance reasons.*/
+   tl_assert(DRD_(thread_get_running_tid)()
+             == DRD_(VgThreadIdToDrdThreadId)(VG_(get_running_tid())));
+#endif
+
+   if (DRD_(running_thread_is_recording_stores)()
+       && (s_check_stack_accesses
+           || ! DRD_(thread_address_on_stack)(addr))
+       && bm_access_store_triggers_conflict(addr, addr + size)
+       && ! DRD_(is_suppressed)(addr, addr + size))
+   {
+      drd_report_race(addr, size, eStore);
+   }
+}
+
+static VG_REGPARM(1) void drd_trace_store_1(Addr addr)
+{
+   if (DRD_(running_thread_is_recording_stores)()
+       && (s_check_stack_accesses
+           || ! DRD_(thread_address_on_stack)(addr))
+       && bm_access_store_1_triggers_conflict(addr)
+       && ! DRD_(is_suppressed)(addr, addr + 1))
+   {
+      drd_report_race(addr, 1, eStore);
+   }
+}
+
+static VG_REGPARM(1) void drd_trace_store_2(Addr addr)
+{
+   if (DRD_(running_thread_is_recording_stores)()
+       && (s_check_stack_accesses
+           || ! DRD_(thread_address_on_stack)(addr))
+       && bm_access_store_2_triggers_conflict(addr)
+       && ! DRD_(is_suppressed)(addr, addr + 2))
+   {
+      drd_report_race(addr, 2, eStore);
+   }
+}
+
+static VG_REGPARM(1) void drd_trace_store_4(Addr addr)
+{
+   if (DRD_(running_thread_is_recording_stores)()
+       && (s_check_stack_accesses
+           || ! DRD_(thread_address_on_stack)(addr))
+       && bm_access_store_4_triggers_conflict(addr)
+       && ! DRD_(is_suppressed)(addr, addr + 4))
+   {
+      drd_report_race(addr, 4, eStore);
+   }
+}
+
+static VG_REGPARM(1) void drd_trace_store_8(Addr addr)
+{
+   if (DRD_(running_thread_is_recording_stores)()
+       && (s_check_stack_accesses
+           || ! DRD_(thread_address_on_stack)(addr))
+       && bm_access_store_8_triggers_conflict(addr)
+       && ! DRD_(is_suppressed)(addr, addr + 8))
+   {
+      drd_report_race(addr, 8, eStore);
+   }
+}
+
+/**
+ * Return true if and only if addr_expr matches the pattern (SP) or
+ * <offset>(SP).
+ */
+static Bool is_stack_access(IRSB* const bb, IRExpr* const addr_expr)
+{
+   Bool result = False;
+
+   if (addr_expr->tag == Iex_RdTmp)
+   {
+      int i;
+      for (i = 0; i < bb->stmts_size; i++)
+      {
+         if (bb->stmts[i]
+             && bb->stmts[i]->tag == Ist_WrTmp
+             && bb->stmts[i]->Ist.WrTmp.tmp == addr_expr->Iex.RdTmp.tmp)
+         {
+            IRExpr* e = bb->stmts[i]->Ist.WrTmp.data;
+            if (e->tag == Iex_Get && e->Iex.Get.offset == STACK_POINTER_OFFSET)
+            {
+               result = True;
+            }
+
+            //ppIRExpr(e);
+            //VG_(printf)(" (%s)\n", result ? "True" : "False");
+            break;
+         }
+      }
+   }
+   return result;
+}
+
+static void instrument_load(IRSB* const bb,
+                            IRExpr* const addr_expr,
+                            const HWord size)
+{
+   IRExpr* size_expr;
+   IRExpr** argv;
+   IRDirty* di;
+
+   if (UNLIKELY(DRD_(any_address_is_traced)()))
+   {
+      addStmtToIRSB(bb,
+         IRStmt_Dirty(
+            unsafeIRDirty_0_N(/*regparms*/2,
+                              "drd_trace_load",
+                              VG_(fnptr_to_fnentry)
+                              (drd_trace_mem_load),
+                              mkIRExprVec_2(addr_expr,
+                                            mkIRExpr_HWord(size)))));
+   }
+
+   if (! s_check_stack_accesses && is_stack_access(bb, addr_expr))
+      return;
+
+   switch (size)
+   {
+   case 1:
+      argv = mkIRExprVec_1(addr_expr);
+      di = unsafeIRDirty_0_N(/*regparms*/1,
+                             "drd_trace_load_1",
+                             VG_(fnptr_to_fnentry)(drd_trace_load_1),
+                             argv);
+      break;
+   case 2:
+      argv = mkIRExprVec_1(addr_expr);
+      di = unsafeIRDirty_0_N(/*regparms*/1,
+                             "drd_trace_load_2",
+                             VG_(fnptr_to_fnentry)(drd_trace_load_2),
+                             argv);
+      break;
+   case 4:
+      argv = mkIRExprVec_1(addr_expr);
+      di = unsafeIRDirty_0_N(/*regparms*/1,
+                             "drd_trace_load_4",
+                             VG_(fnptr_to_fnentry)(drd_trace_load_4),
+                             argv);
+      break;
+   case 8:
+      argv = mkIRExprVec_1(addr_expr);
+      di = unsafeIRDirty_0_N(/*regparms*/1,
+                             "drd_trace_load_8",
+                             VG_(fnptr_to_fnentry)(drd_trace_load_8),
+                             argv);
+      break;
+   default:
+      size_expr = mkIRExpr_HWord(size);
+      argv = mkIRExprVec_2(addr_expr, size_expr);
+      di = unsafeIRDirty_0_N(/*regparms*/2,
+                             "drd_trace_load",
+                             VG_(fnptr_to_fnentry)(DRD_(trace_load)),
+                             argv);
+      break;
+   }
+   addStmtToIRSB(bb, IRStmt_Dirty(di));
+}
+
+static void instrument_store(IRSB* const bb,
+                             IRExpr* const addr_expr,
+                             const HWord size)
+{
+   IRExpr* size_expr;
+   IRExpr** argv;
+   IRDirty* di;
+
+   if (UNLIKELY(DRD_(any_address_is_traced)()))
+   {
+      addStmtToIRSB(bb,
+                    IRStmt_Dirty(
+                                 unsafeIRDirty_0_N(/*regparms*/2,
+                                                   "drd_trace_store",
+                                                   VG_(fnptr_to_fnentry)
+                                                   (drd_trace_mem_store),
+                                                   mkIRExprVec_2(addr_expr,
+                                                                 mkIRExpr_HWord(size)))));
+   }
+
+   if (! s_check_stack_accesses && is_stack_access(bb, addr_expr))
+      return;
+
+   switch (size)
+   {
+   case 1:
+      argv = mkIRExprVec_1(addr_expr);
+      di = unsafeIRDirty_0_N(/*regparms*/1,
+                             "drd_trace_store_1",
+                             VG_(fnptr_to_fnentry)(drd_trace_store_1),
+                             argv);
+      break;
+   case 2:
+      argv = mkIRExprVec_1(addr_expr);
+      di = unsafeIRDirty_0_N(/*regparms*/1,
+                             "drd_trace_store_2",
+                             VG_(fnptr_to_fnentry)(drd_trace_store_2),
+                             argv);
+      break;
+   case 4:
+      argv = mkIRExprVec_1(addr_expr);
+      di = unsafeIRDirty_0_N(/*regparms*/1,
+                             "drd_trace_store_4",
+                             VG_(fnptr_to_fnentry)(drd_trace_store_4),
+                             argv);
+      break;
+   case 8:
+      argv = mkIRExprVec_1(addr_expr);
+      di = unsafeIRDirty_0_N(/*regparms*/1,
+                             "drd_trace_store_8",
+                             VG_(fnptr_to_fnentry)(drd_trace_store_8),
+                             argv);
+      break;
+   default:
+      size_expr = mkIRExpr_HWord(size);
+      argv = mkIRExprVec_2(addr_expr, size_expr);
+      di = unsafeIRDirty_0_N(/*regparms*/2,
+                             "drd_trace_store",
+                             VG_(fnptr_to_fnentry)(DRD_(trace_store)),
+                             argv);
+      break;
+   }
+   addStmtToIRSB(bb, IRStmt_Dirty(di));
+}
+
+IRSB* DRD_(instrument)(VgCallbackClosure* const closure,
+                       IRSB* const bb_in,
+                       VexGuestLayout* const layout,
+                       VexGuestExtents* const vge,
+                       IRType const gWordTy,
+                       IRType const hWordTy)
+{
+   IRDirty* di;
+   Int      i;
+   IRSB*    bb;
+   IRExpr** argv;
+   Bool     instrument = True;
+
+   /* Set up BB */
+   bb           = emptyIRSB();
+   bb->tyenv    = deepCopyIRTypeEnv(bb_in->tyenv);
+   bb->next     = deepCopyIRExpr(bb_in->next);
+   bb->jumpkind = bb_in->jumpkind;
+
+   for (i = 0; i < bb_in->stmts_used; i++)
+   {
+      IRStmt* const st = bb_in->stmts[i];
+      tl_assert(st);
+      tl_assert(isFlatIRStmt(st));
+
+      switch (st->tag)
+      {
+         /* Note: the code for not instrumenting the code in .plt          */
+         /* sections is only necessary on CentOS 3.0 x86 (kernel 2.4.21    */
+         /* + glibc 2.3.2 + NPTL 0.60 + binutils 2.14.90.0.4).             */
+         /* This is because on this platform dynamic library symbols are   */
+         /* relocated in another way than by later binutils versions. The  */
+         /* linker e.g. does not generate .got.plt sections on CentOS 3.0. */
+      case Ist_IMark:
+         instrument = VG_(DebugInfo_sect_kind)(NULL, 0, st->Ist.IMark.addr)
+            != Vg_SectPLT;
+         addStmtToIRSB(bb, st);
+         break;
+
+      case Ist_MBE:
+         switch (st->Ist.MBE.event)
+         {
+         case Imbe_Fence:
+            break; /* not interesting */
+         default:
+            tl_assert(0);
+         }
+         addStmtToIRSB(bb, st);
+         break;
+
+      case Ist_Store:
+         if (instrument)
+         {
+            instrument_store(bb,
+                             st->Ist.Store.addr,
+                             sizeofIRType(typeOfIRExpr(bb->tyenv,
+                                                       st->Ist.Store.data)));
+         }
+         addStmtToIRSB(bb, st);
+         break;
+
+      case Ist_WrTmp:
+         if (instrument)
+         {
+            const IRExpr* const data = st->Ist.WrTmp.data;
+            if (data->tag == Iex_Load)
+            {
+               instrument_load(bb,
+                               data->Iex.Load.addr,
+                               sizeofIRType(data->Iex.Load.ty));
+            }
+         }
+         addStmtToIRSB(bb, st);
+         break;
+
+      case Ist_Dirty:
+         if (instrument)
+         {
+            IRDirty* d = st->Ist.Dirty.details;
+            IREffect const mFx = d->mFx;
+            switch (mFx) {
+            case Ifx_None:
+               break;
+            case Ifx_Read:
+            case Ifx_Write:
+            case Ifx_Modify:
+               tl_assert(d->mAddr);
+               tl_assert(d->mSize > 0);
+               argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
+               if (mFx == Ifx_Read || mFx == Ifx_Modify) {
+                  di = unsafeIRDirty_0_N(
+                          /*regparms*/2,
+                          "drd_trace_load",
+                          VG_(fnptr_to_fnentry)(DRD_(trace_load)),
+                          argv);
+                  addStmtToIRSB(bb, IRStmt_Dirty(di));
+               }
+               if (mFx == Ifx_Write || mFx == Ifx_Modify)
+               {
+                  di = unsafeIRDirty_0_N(
+                          /*regparms*/2,
+                          "drd_trace_store",
+                          VG_(fnptr_to_fnentry)(DRD_(trace_store)),
+                          argv);
+                  addStmtToIRSB(bb, IRStmt_Dirty(di));
+               }
+               break;
+            default:
+               tl_assert(0);
+            }
+         }
+         addStmtToIRSB(bb, st);
+         break;
+
+      case Ist_CAS:
+         if (instrument)
+         {
+            /*
+             * Treat compare-and-swap as a read. By handling atomic
+             * instructions as read instructions no data races are reported
+             * between conflicting atomic operations nor between atomic
+             * operations and non-atomic reads. Conflicts between atomic
+             * operations and non-atomic write operations are still reported
+             * however.
+             */
+            Int    dataSize;
+            IRCAS* cas = st->Ist.CAS.details;
+            tl_assert(cas->addr != NULL);
+            tl_assert(cas->dataLo != NULL);
+            dataSize = sizeofIRType(typeOfIRExpr(bb->tyenv, cas->dataLo));
+            if (cas->dataHi != NULL)
+               dataSize *= 2; /* since it's a doubleword-CAS */
+            instrument_load(bb, cas->addr, dataSize);
+         }
+         addStmtToIRSB(bb, st);
+         break;
+
+      case Ist_LLSC: {
+         /* Ignore store-conditionals, and handle load-linked's
+            exactly like normal loads. */
+         IRType dataTy;
+         if (st->Ist.LLSC.storedata == NULL)
+         {
+            /* LL */
+            dataTy = typeOfIRTemp(bb_in->tyenv, st->Ist.LLSC.result);
+            if (instrument) {
+               instrument_load(bb,
+                               st->Ist.LLSC.addr,
+                               sizeofIRType(dataTy));
+            }
+         }
+         else
+         {
+            /* SC */
+            /*ignore */
+         }
+         addStmtToIRSB(bb, st);
+         break;
+      }
+
+      case Ist_NoOp:
+      case Ist_AbiHint:
+      case Ist_Put:
+      case Ist_PutI:
+      case Ist_Exit:
+         /* None of these can contain any memory references. */
+         addStmtToIRSB(bb, st);
+         break;
+
+      default:
+         ppIRStmt(st);
+         tl_assert(0);
+      }
+   }
+
+   return bb;
+}
+
diff --git a/drd/drd_load_store.h b/drd/drd_load_store.h
new file mode 100644
index 0000000..46b763f
--- /dev/null
+++ b/drd/drd_load_store.h
@@ -0,0 +1,56 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+/*
+ * Functions related to instrumentation of loads and stores.
+ */
+
+
+#ifndef __DRD_LOAD_STORE_H
+#define __DRD_LOAD_STORE_H
+
+
+#include <libvex.h>             /* IRSB */
+#include <pub_tool_tooliface.h> /* VgCallbackClosure */
+
+
+Bool DRD_(get_check_stack_accesses)(void);
+void DRD_(set_check_stack_accesses)(const Bool c);
+Bool DRD_(get_first_race_only)(void);
+void DRD_(set_first_race_only)(const Bool fro);
+IRSB* DRD_(instrument)(VgCallbackClosure* const closure,
+                       IRSB* const bb_in,
+                       VexGuestLayout* const layout,
+                       VexGuestExtents* const vge,
+                       IRType const gWordTy,
+                       IRType const hWordTy);
+void DRD_(trace_mem_access)(const Addr addr, const SizeT size,
+                            const BmAccessTypeT access_type);
+VG_REGPARM(2) void DRD_(trace_load)(Addr addr, SizeT size);
+VG_REGPARM(2) void DRD_(trace_store)(Addr addr, SizeT size);
+void DRD_(clean_memory)(const Addr a1, const SizeT len);
+
+
+#endif //  __DRD_LOAD_STORE_H
diff --git a/drd/drd_main.c b/drd/drd_main.c
new file mode 100644
index 0000000..953120b
--- /dev/null
+++ b/drd/drd_main.c
@@ -0,0 +1,776 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#include "drd_barrier.h"
+#include "drd_clientobj.h"
+#include "drd_clientreq.h"
+#include "drd_cond.h"
+#include "drd_error.h"
+#include "drd_load_store.h"
+#include "drd_malloc_wrappers.h"
+#include "drd_mutex.h"
+#include "drd_rwlock.h"
+#include "drd_segment.h"
+#include "drd_semaphore.h"
+#include "drd_suppression.h"
+#include "drd_thread.h"
+#include "libvex_guest_offsets.h"
+#include "pub_drd_bitmap.h"
+#include "pub_tool_vki.h"         // Must be included before pub_tool_libcproc
+#include "pub_tool_basics.h"
+#include "pub_tool_debuginfo.h"   // VG_(describe_IP)()
+#include "pub_tool_libcassert.h"  // tl_assert()
+#include "pub_tool_libcbase.h"    // VG_(strcmp)
+#include "pub_tool_libcprint.h"   // VG_(printf)
+#include "pub_tool_libcproc.h"
+#include "pub_tool_machine.h"
+#include "pub_tool_mallocfree.h"  // VG_(malloc)(), VG_(free)()
+#include "pub_tool_options.h"     // command line options
+#include "pub_tool_replacemalloc.h"
+#include "pub_tool_threadstate.h" // VG_(get_running_tid)()
+#include "pub_tool_tooliface.h"
+
+
+/* Local variables. */
+
+static Bool s_free_is_write    = False;
+static Bool s_print_stats      = False;
+static Bool s_var_info         = False;
+static Bool s_show_stack_usage = False;
+static Bool s_trace_alloc      = False;
+
+
+/**
+ * Implement the needs_command_line_options for drd.
+ */
+static Bool DRD_(process_cmd_line_option)(Char* arg)
+{
+   int check_stack_accesses   = -1;
+   int exclusive_threshold_ms = -1;
+   int first_race_only        = -1;
+   int report_signal_unlocked = -1;
+   int segment_merging        = -1;
+   int segment_merge_interval = -1;
+   int shared_threshold_ms    = -1;
+   int show_confl_seg         = -1;
+   int trace_barrier          = -1;
+   int trace_clientobj        = -1;
+   int trace_cond             = -1;
+   int trace_csw              = -1;
+   int trace_fork_join        = -1;
+   int trace_conflict_set     = -1;
+   int trace_conflict_set_bm  = -1;
+   int trace_mutex            = -1;
+   int trace_rwlock           = -1;
+   int trace_segment          = -1;
+   int trace_semaphore        = -1;
+   int trace_suppression      = -1;
+   Char* trace_address        = 0;
+
+   if      VG_BOOL_CLO(arg, "--check-stack-var",     check_stack_accesses) {}
+   else if VG_BOOL_CLO(arg, "--drd-stats",           s_print_stats) {}
+   else if VG_BOOL_CLO(arg, "--first-race-only",     first_race_only) {}
+   else if VG_BOOL_CLO(arg, "--free-is-write",       s_free_is_write) {}
+   else if VG_BOOL_CLO(arg,"--report-signal-unlocked",report_signal_unlocked)
+   {}
+   else if VG_BOOL_CLO(arg, "--segment-merging",     segment_merging) {}
+   else if VG_INT_CLO (arg, "--segment-merging-interval", segment_merge_interval)
+   {}
+   else if VG_BOOL_CLO(arg, "--show-confl-seg",      show_confl_seg) {}
+   else if VG_BOOL_CLO(arg, "--show-stack-usage",    s_show_stack_usage) {}
+   else if VG_BOOL_CLO(arg, "--trace-alloc",         s_trace_alloc) {}
+   else if VG_BOOL_CLO(arg, "--trace-barrier",       trace_barrier) {}
+   else if VG_BOOL_CLO(arg, "--trace-clientobj",     trace_clientobj) {}
+   else if VG_BOOL_CLO(arg, "--trace-cond",          trace_cond) {}
+   else if VG_BOOL_CLO(arg, "--trace-conflict-set",  trace_conflict_set) {}
+   else if VG_BOOL_CLO(arg, "--trace-conflict-set-bm", trace_conflict_set_bm){}
+   else if VG_BOOL_CLO(arg, "--trace-csw",           trace_csw) {}
+   else if VG_BOOL_CLO(arg, "--trace-fork-join",     trace_fork_join) {}
+   else if VG_BOOL_CLO(arg, "--trace-mutex",         trace_mutex) {}
+   else if VG_BOOL_CLO(arg, "--trace-rwlock",        trace_rwlock) {}
+   else if VG_BOOL_CLO(arg, "--trace-segment",       trace_segment) {}
+   else if VG_BOOL_CLO(arg, "--trace-semaphore",     trace_semaphore) {}
+   else if VG_BOOL_CLO(arg, "--trace-suppr",         trace_suppression) {}
+   else if VG_BOOL_CLO(arg, "--var-info",            s_var_info) {}
+   else if VG_INT_CLO (arg, "--exclusive-threshold", exclusive_threshold_ms) {}
+   else if VG_INT_CLO (arg, "--shared-threshold",    shared_threshold_ms)    {}
+   else if VG_STR_CLO (arg, "--trace-addr",          trace_address) {}
+   else
+      return VG_(replacement_malloc_process_cmd_line_option)(arg);
+
+   if (check_stack_accesses != -1)
+      DRD_(set_check_stack_accesses)(check_stack_accesses);
+   if (exclusive_threshold_ms != -1)
+   {
+      DRD_(mutex_set_lock_threshold)(exclusive_threshold_ms);
+      DRD_(rwlock_set_exclusive_threshold)(exclusive_threshold_ms);
+   }
+   if (first_race_only != -1)
+   {
+      DRD_(set_first_race_only)(first_race_only);
+   }
+   if (report_signal_unlocked != -1)
+   {
+      DRD_(cond_set_report_signal_unlocked)(report_signal_unlocked);
+   }
+   if (shared_threshold_ms != -1)
+   {
+      DRD_(rwlock_set_shared_threshold)(shared_threshold_ms);
+   }
+   if (segment_merging != -1)
+      DRD_(thread_set_segment_merging)(segment_merging);
+   if (segment_merge_interval != -1)
+      DRD_(thread_set_segment_merge_interval)(segment_merge_interval);
+   if (show_confl_seg != -1)
+      DRD_(set_show_conflicting_segments)(show_confl_seg);
+   if (trace_address)
+   {
+      const Addr addr = VG_(strtoll16)(trace_address, 0);
+      DRD_(start_tracing_address_range)(addr, addr + 1);
+   }
+   if (trace_barrier != -1)
+      DRD_(barrier_set_trace)(trace_barrier);
+   if (trace_clientobj != -1)
+      DRD_(clientobj_set_trace)(trace_clientobj);
+   if (trace_cond != -1)
+      DRD_(cond_set_trace)(trace_cond);
+   if (trace_csw != -1)
+      DRD_(thread_trace_context_switches)(trace_csw);
+   if (trace_fork_join != -1)
+      DRD_(thread_set_trace_fork_join)(trace_fork_join);
+   if (trace_conflict_set != -1)
+      DRD_(thread_trace_conflict_set)(trace_conflict_set);
+   if (trace_conflict_set_bm != -1)
+      DRD_(thread_trace_conflict_set_bm)(trace_conflict_set_bm);
+   if (trace_mutex != -1)
+      DRD_(mutex_set_trace)(trace_mutex);
+   if (trace_rwlock != -1)
+      DRD_(rwlock_set_trace)(trace_rwlock);
+   if (trace_segment != -1)
+      DRD_(sg_set_trace)(trace_segment);
+   if (trace_semaphore != -1)
+      DRD_(semaphore_set_trace)(trace_semaphore);
+   if (trace_suppression != -1)
+      DRD_(suppression_set_trace)(trace_suppression);
+
+   return True;
+}
+
+static void DRD_(print_usage)(void)
+{
+   VG_(printf)(
+"    --check-stack-var=yes|no  Whether or not to report data races on\n"
+"                              stack variables [no].\n"
+"    --exclusive-threshold=<n> Print an error message if any mutex or\n"
+"        writer lock is held longer than the specified time (in milliseconds).\n"
+"    --first-race-only=yes|no  Only report the first data race that occurs on\n"
+"                              a memory location instead of all races [no].\n"
+"    --free-is-write=yes|no    Whether to report races between freeing memory\n"
+"                              and subsequent accesses of that memory[no].\n"
+"    --report-signal-unlocked=yes|no Whether to report calls to\n"
+"                              pthread_cond_signal() where the mutex associated\n"
+"                              with the signal via pthread_cond_wait() is not\n"
+"                              locked at the time the signal is sent [yes].\n"
+"    --segment-merging=yes|no  Controls segment merging [yes].\n"
+"        Segment merging is an algorithm to limit memory usage of the\n"
+"        data race detection algorithm. Disabling segment merging may\n"
+"        improve the accuracy of the so-called 'other segments' displayed\n"
+"        in race reports but can also trigger an out of memory error.\n"
+"    --segment-merging-interval=<n> Perform segment merging every time n new\n"
+"        segments have been created. Default: %d.\n"
+"    --shared-threshold=<n>    Print an error message if a reader lock\n"
+"        is held longer than the specified time (in milliseconds).\n"
+"    --show-confl-seg=yes|no   Show conflicting segments in race reports [yes].\n"
+"    --show-stack-usage=yes|no Print stack usage at thread exit time [no].\n"
+"\n"
+"  drd options for monitoring process behavior:\n"
+"    --trace-addr=<address>    Trace all load and store activity for the.\n"
+"                              specified address [off].\n"
+"    --trace-alloc=yes|no      Trace all memory allocations and deallocations\n""                              [no].\n"
+"    --trace-barrier=yes|no    Trace all barrier activity [no].\n"
+"    --trace-cond=yes|no       Trace all condition variable activity [no].\n"
+"    --trace-fork-join=yes|no  Trace all thread fork/join activity [no].\n"
+"    --trace-mutex=yes|no      Trace all mutex activity [no].\n"
+"    --trace-rwlock=yes|no     Trace all reader-writer lock activity[no].\n"
+"    --trace-semaphore=yes|no  Trace all semaphore activity [no].\n",
+DRD_(thread_get_segment_merge_interval)()
+);
+}
+
+static void DRD_(print_debug_usage)(void)
+{
+   VG_(printf)(
+"    --drd-stats=yes|no        Print statistics about DRD activity [no].\n"
+"    --trace-clientobj=yes|no  Trace all client object activity [no].\n"
+"    --trace-csw=yes|no        Trace all scheduler context switches [no].\n"
+"    --trace-conflict-set=yes|no Trace all conflict set updates [no].\n"
+"    --trace-conflict-set-bm=yes|no Trace all conflict set bitmap\n"
+"                              updates [no]. Note: enabling this option\n"
+"                              will generate a lot of output !\n"
+"    --trace-segment=yes|no    Trace segment actions [no].\n"
+"    --trace-suppr=yes|no      Trace all address suppression actions [no].\n"
+);
+}
+
+
+//
+// Implements the thread-related core callbacks.
+//
+
+static void drd_pre_mem_read(const CorePart part,
+                             const ThreadId tid,
+                             Char* const s,
+                             const Addr a,
+                             const SizeT size)
+{
+   if (size > 0)
+   {
+      DRD_(trace_load)(a, size);
+   }
+}
+
+static void drd_pre_mem_read_asciiz(const CorePart part,
+                                    const ThreadId tid,
+                                    Char* const s,
+                                    const Addr a)
+{
+   const char* p = (void*)a;
+   SizeT size = 0;
+
+   /* Note: the expression '*p' reads client memory and may crash if the */
+   /* client provided an invalid pointer !                               */
+   while (*p)
+   {
+      p++;
+      size++;
+   }
+   if (size > 0)
+   {
+      DRD_(trace_load)(a, size);
+   }
+}
+
+static void drd_post_mem_write(const CorePart part,
+                               const ThreadId tid,
+                               const Addr a,
+                               const SizeT size)
+{
+   DRD_(thread_set_vg_running_tid)(VG_(get_running_tid)());
+   if (size > 0)
+   {
+      DRD_(trace_store)(a, size);
+   }
+}
+
+static __inline__
+void drd_start_using_mem(const Addr a1, const SizeT len,
+                         const Bool is_stack_mem)
+{
+   tl_assert(a1 <= a1 + len);
+
+   if (!is_stack_mem && s_trace_alloc)
+      VG_(message)(Vg_UserMsg, "Started using memory range 0x%lx + %ld%s\n",
+                   a1, len, DRD_(running_thread_inside_pthread_create)()
+                   ? " (inside pthread_create())" : "");
+
+   if (UNLIKELY(DRD_(any_address_is_traced)()))
+   {
+      DRD_(trace_mem_access)(a1, len, eStart);
+   }
+
+   if (UNLIKELY(DRD_(running_thread_inside_pthread_create)()))
+   {
+      DRD_(start_suppression)(a1, a1 + len, "pthread_create()");
+   }
+}
+
+static void drd_start_using_mem_w_ecu(const Addr a1,
+                                      const SizeT len,
+                                      UInt ec_uniq)
+{
+   drd_start_using_mem(a1, len, False);
+}
+
+static void drd_start_using_mem_w_tid(const Addr a1,
+                                      const SizeT len,
+                                      ThreadId tid)
+{
+   drd_start_using_mem(a1, len, False);
+}
+
+static __inline__
+void drd_stop_using_mem(const Addr a1, const SizeT len,
+                        const Bool is_stack_mem)
+{
+   const Addr a2 = a1 + len;
+
+   tl_assert(a1 <= a2);
+
+   if (UNLIKELY(DRD_(any_address_is_traced)()))
+      DRD_(trace_mem_access)(a1, len, eEnd);
+
+   if (!is_stack_mem && s_trace_alloc)
+      VG_(message)(Vg_UserMsg, "Stopped using memory range 0x%lx + %ld\n",
+                   a1, len);
+
+   if (!is_stack_mem || DRD_(get_check_stack_accesses)())
+   {
+      DRD_(thread_stop_using_mem)(a1, a2, !is_stack_mem && s_free_is_write);
+      DRD_(clientobj_stop_using_mem)(a1, a2);
+      DRD_(suppression_stop_using_mem)(a1, a2);
+   }
+   if (!is_stack_mem && s_free_is_write)
+      DRD_(trace_store)(a1, len);
+}
+
+static __inline__
+void drd_stop_using_nonstack_mem(const Addr a1, const SizeT len)
+{
+   drd_stop_using_mem(a1, len, False);
+}
+
+/**
+ * Discard all information DRD has about memory accesses and client objects
+ * in the specified address range.
+ */
+void DRD_(clean_memory)(const Addr a1, const SizeT len)
+{
+   const Bool is_stack_memory = DRD_(thread_address_on_any_stack)(a1);
+   drd_stop_using_mem(a1, len, is_stack_memory);
+   drd_start_using_mem(a1, len, is_stack_memory);
+}
+
+/**
+ * Suppress data race reports on all addresses contained in .plt and
+ * .got.plt sections inside the address range [ a, a + len [. The data in
+ * these sections is modified by _dl_relocate_object() every time a function
+ * in a shared library is called for the first time. Since the first call
+ * to a function in a shared library can happen from a multithreaded context,
+ * such calls can cause conflicting accesses. See also Ulrich Drepper's
+ * paper "How to Write Shared Libraries" for more information about relocation
+ * (http://people.redhat.com/drepper/dsohowto.pdf).
+ */
+static void DRD_(suppress_relocation_conflicts)(const Addr a, const SizeT len)
+{
+   const DebugInfo* di;
+
+#if 0
+   VG_(printf)("Evaluating range @ 0x%lx size %ld\n", a, len);
+#endif
+
+   for (di = VG_(next_DebugInfo)(0); di; di = VG_(next_DebugInfo)(di))
+   {
+      Addr  avma;
+      SizeT size;
+
+      avma = VG_(DebugInfo_get_plt_avma)(di);
+      size = VG_(DebugInfo_get_plt_size)(di);
+      tl_assert((avma && size) || (avma == 0 && size == 0));
+      if (size > 0)
+      {
+#if 0
+         VG_(printf)("Suppressing .plt @ 0x%lx size %ld\n", avma, size);
+#endif
+         tl_assert(VG_(DebugInfo_sect_kind)(NULL, 0, avma) == Vg_SectPLT);
+         DRD_(start_suppression)(avma, avma + size, ".plt");
+      }
+
+      avma = VG_(DebugInfo_get_gotplt_avma)(di);
+      size = VG_(DebugInfo_get_gotplt_size)(di);
+      tl_assert((avma && size) || (avma == 0 && size == 0));
+      if (size > 0)
+      {
+#if 0
+         VG_(printf)("Suppressing .got.plt @ 0x%lx size %ld\n", avma, size);
+#endif
+         tl_assert(VG_(DebugInfo_sect_kind)(NULL, 0, avma) == Vg_SectGOTPLT);
+         DRD_(start_suppression)(avma, avma + size, ".gotplt");
+      }
+   }
+}
+
+static
+void drd_start_using_mem_w_perms(const Addr a, const SizeT len,
+                                 const Bool rr, const Bool ww, const Bool xx,
+                                 ULong di_handle)
+{
+   DRD_(thread_set_vg_running_tid)(VG_(get_running_tid)());
+
+   drd_start_using_mem(a, len, False);
+
+   DRD_(suppress_relocation_conflicts)(a, len);
+}
+
+/* Called by the core when the stack of a thread grows, to indicate that */
+/* the addresses in range [ a, a + len [ may now be used by the client.  */
+/* Assumption: stacks grow downward.                                     */
+static __inline__
+void drd_start_using_mem_stack(const Addr a, const SizeT len)
+{
+   DRD_(thread_set_stack_min)(DRD_(thread_get_running_tid)(),
+                              a - VG_STACK_REDZONE_SZB);
+   drd_start_using_mem(a - VG_STACK_REDZONE_SZB,
+                       len + VG_STACK_REDZONE_SZB,
+                       True);
+}
+
+/* Called by the core when the stack of a thread shrinks, to indicate that */
+/* the addresses [ a, a + len [ are no longer accessible for the client.   */
+/* Assumption: stacks grow downward.                                       */
+static __inline__
+void drd_stop_using_mem_stack(const Addr a, const SizeT len)
+{
+   DRD_(thread_set_stack_min)(DRD_(thread_get_running_tid)(),
+                              a + len - VG_STACK_REDZONE_SZB);
+   drd_stop_using_mem(a - VG_STACK_REDZONE_SZB, len + VG_STACK_REDZONE_SZB,
+                      True);
+}
+
+static
+Bool on_alt_stack(const Addr a)
+{
+   ThreadId vg_tid;
+   Addr alt_min;
+   SizeT alt_size;
+
+   vg_tid = VG_(get_running_tid)();
+   alt_min = VG_(thread_get_altstack_min)(vg_tid);
+   alt_size = VG_(thread_get_altstack_size)(vg_tid);
+   return (SizeT)(a - alt_min) < alt_size;
+}
+
+static
+void drd_start_using_mem_alt_stack(const Addr a, const SizeT len)
+{
+   if (!on_alt_stack(a))
+      drd_start_using_mem_stack(a, len);
+}
+
+static
+void drd_stop_using_mem_alt_stack(const Addr a, const SizeT len)
+{
+   if (!on_alt_stack(a))
+      drd_stop_using_mem_stack(a, len);
+}
+
+/**
+ * Callback function invoked by the Valgrind core before a signal is delivered.
+ */
+static
+void drd_pre_deliver_signal(const ThreadId vg_tid, const Int sigNo,
+                            const Bool alt_stack)
+{
+   DrdThreadId drd_tid;
+
+   drd_tid = DRD_(VgThreadIdToDrdThreadId)(vg_tid);
+   DRD_(thread_set_on_alt_stack)(drd_tid, alt_stack);
+   if (alt_stack)
+   {
+      /*
+       * As soon a signal handler has been invoked on the alternate stack,
+       * switch to stack memory handling functions that can handle the
+       * alternate stack.
+       */
+      VG_(track_new_mem_stack)(drd_start_using_mem_alt_stack);
+      VG_(track_die_mem_stack)(drd_stop_using_mem_alt_stack);
+   }
+}
+
+/**
+ * Callback function invoked by the Valgrind core after a signal is delivered,
+ * at least if the signal handler did not longjmp().
+ */
+static
+void drd_post_deliver_signal(const ThreadId vg_tid, const Int sigNo)
+{
+   DrdThreadId drd_tid;
+
+   drd_tid = DRD_(VgThreadIdToDrdThreadId)(vg_tid);
+   DRD_(thread_set_on_alt_stack)(drd_tid, False);
+   if (DRD_(thread_get_threads_on_alt_stack)() == 0)
+   {
+      VG_(track_new_mem_stack)(drd_start_using_mem_stack);
+      VG_(track_die_mem_stack)(drd_stop_using_mem_stack);
+   }
+}
+
+/**
+ * Callback function called by the Valgrind core before a stack area is
+ * being used by a signal handler.
+ *
+ * @param[in] a   Start of address range.
+ * @param[in] len Address range length.
+ * @param[in] tid Valgrind thread ID for whom the signal frame is being
+ *                constructed.
+ */
+static void drd_start_using_mem_stack_signal(const Addr a, const SizeT len,
+                                             ThreadId tid)
+{
+   DRD_(thread_set_vg_running_tid)(VG_(get_running_tid)());
+   drd_start_using_mem(a, len, True);
+}
+
+static void drd_stop_using_mem_stack_signal(Addr a, SizeT len)
+{
+   drd_stop_using_mem(a, len, True);
+}
+
+static
+void drd_pre_thread_create(const ThreadId creator, const ThreadId created)
+{
+   const DrdThreadId drd_creator = DRD_(VgThreadIdToDrdThreadId)(creator);
+   tl_assert(created != VG_INVALID_THREADID);
+   DRD_(thread_pre_create)(drd_creator, created);
+   if (DRD_(IsValidDrdThreadId)(drd_creator))
+   {
+      DRD_(thread_new_segment)(drd_creator);
+   }
+   if (DRD_(thread_get_trace_fork_join)())
+   {
+      VG_(message)(Vg_DebugMsg,
+                   "drd_pre_thread_create creator = %d, created = %d\n",
+                   drd_creator, created);
+   }
+}
+
+/* Called by Valgrind's core before any loads or stores are performed on */
+/* the context of thread "created". At startup, this function is called  */
+/* with arguments (0,1).                                                 */
+static
+void drd_post_thread_create(const ThreadId vg_created)
+{
+   DrdThreadId drd_created;
+
+   tl_assert(vg_created != VG_INVALID_THREADID);
+
+   drd_created = DRD_(thread_post_create)(vg_created);
+   if (DRD_(thread_get_trace_fork_join)())
+   {
+      VG_(message)(Vg_DebugMsg,
+                   "drd_post_thread_create created = %d\n",
+                   drd_created);
+   }
+   if (! DRD_(get_check_stack_accesses)())
+   {
+      DRD_(start_suppression)(DRD_(thread_get_stack_max)(drd_created)
+                              - DRD_(thread_get_stack_size)(drd_created),
+                              DRD_(thread_get_stack_max)(drd_created),
+                              "stack");
+   }
+}
+
+/* Called after a thread has performed its last memory access. */
+static void drd_thread_finished(ThreadId vg_tid)
+{
+   DrdThreadId drd_tid;
+
+   tl_assert(VG_(get_running_tid)() == vg_tid);
+
+   drd_tid = DRD_(VgThreadIdToDrdThreadId)(vg_tid);
+   if (DRD_(thread_get_trace_fork_join)())
+   {
+      VG_(message)(Vg_DebugMsg,
+                   "drd_thread_finished tid = %d%s\n",
+                   drd_tid,
+                   DRD_(thread_get_joinable)(drd_tid)
+                   ? ""
+                   : " (which is a detached thread)");
+   }
+   if (s_show_stack_usage)
+   {
+      const SizeT stack_size = DRD_(thread_get_stack_size)(drd_tid);
+      const SizeT used_stack
+         = (DRD_(thread_get_stack_max)(drd_tid)
+            - DRD_(thread_get_stack_min_min)(drd_tid));
+      VG_(message)(Vg_UserMsg,
+                   "thread %d%s finished and used %ld bytes out of %ld"
+                   " on its stack. Margin: %ld bytes.\n",
+                   drd_tid,
+                   DRD_(thread_get_joinable)(drd_tid)
+                   ? ""
+                   : " (which is a detached thread)",
+                   used_stack,
+                   stack_size,
+                   stack_size - used_stack);
+
+   }
+   drd_stop_using_mem(DRD_(thread_get_stack_min)(drd_tid),
+                      DRD_(thread_get_stack_max)(drd_tid)
+                      - DRD_(thread_get_stack_min)(drd_tid),
+                      True);
+   DRD_(thread_set_record_loads)(drd_tid, False);
+   DRD_(thread_set_record_stores)(drd_tid, False);
+   DRD_(thread_finished)(drd_tid);
+}
+
+//
+// Implementation of the tool interface.
+//
+
+static void DRD_(post_clo_init)(void)
+{
+#if defined(VGO_linux) || defined(VGO_darwin)
+   /* fine */
+#else
+   VG_(printf)("\nWARNING: DRD has not yet been tested on this operating system.\n\n");
+#  endif
+
+   if (s_var_info)
+   {
+      VG_(needs_var_info)();
+   }
+}
+
+static void drd_start_client_code(const ThreadId tid, const ULong bbs_done)
+{
+   tl_assert(tid == VG_(get_running_tid)());
+   DRD_(thread_set_vg_running_tid)(tid);
+}
+
+static void DRD_(fini)(Int exitcode)
+{
+   // thread_print_all();
+   if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
+      VG_(message)(Vg_UserMsg,
+                   "For counts of detected and suppressed errors, "
+                   "rerun with: -v\n");
+   }
+
+   if (VG_(clo_stats) || s_print_stats)
+   {
+      ULong pu = DRD_(thread_get_update_conflict_set_count)();
+      ULong pu_seg_cr = DRD_(thread_get_update_conflict_set_new_sg_count)();
+      ULong pu_mtx_cv = DRD_(thread_get_update_conflict_set_sync_count)();
+      ULong pu_join   = DRD_(thread_get_update_conflict_set_join_count)();
+
+      VG_(message)(Vg_UserMsg,
+                   "   thread: %lld context switches.\n",
+                   DRD_(thread_get_context_switch_count)());
+      VG_(message)(Vg_UserMsg,
+                   "confl set: %lld full updates and %lld partial updates;\n",
+		   DRD_(thread_get_compute_conflict_set_count)(),
+		   pu);
+      VG_(message)(Vg_UserMsg,
+                   "           %lld partial updates during segment creation,\n",
+		   pu_seg_cr);
+      VG_(message)(Vg_UserMsg,
+                   "           %lld because of mutex/sema/cond.var. operations,\n",
+		   pu_mtx_cv);
+      VG_(message)(Vg_UserMsg,
+                   "           %lld because of barrier/rwlock operations and\n",
+		   pu - pu_seg_cr - pu_mtx_cv - pu_join);
+      VG_(message)(Vg_UserMsg,
+                   "           %lld partial updates because of thread join"
+		   " operations.\n",
+		   pu_join);
+      VG_(message)(Vg_UserMsg,
+                   " segments: created %lld segments, max %lld alive,\n",
+                   DRD_(sg_get_segments_created_count)(),
+                   DRD_(sg_get_max_segments_alive_count)());
+      VG_(message)(Vg_UserMsg,
+                   "           %lld discard points and %lld merges.\n",
+                   DRD_(thread_get_discard_ordered_segments_count)(),
+                   DRD_(sg_get_segment_merge_count)());
+      VG_(message)(Vg_UserMsg,
+                   "segmnt cr: %lld mutex, %lld rwlock, %lld semaphore and"
+                   " %lld barrier.\n",
+                   DRD_(get_mutex_segment_creation_count)(),
+                   DRD_(get_rwlock_segment_creation_count)(),
+                   DRD_(get_semaphore_segment_creation_count)(),
+                   DRD_(get_barrier_segment_creation_count)());
+      VG_(message)(Vg_UserMsg,
+                   "  bitmaps: %lld level one"
+                   " and %lld level two bitmaps were allocated.\n",
+                   DRD_(bm_get_bitmap_creation_count)(),
+                   DRD_(bm_get_bitmap2_creation_count)());
+      VG_(message)(Vg_UserMsg,
+                   "    mutex: %lld non-recursive lock/unlock events.\n",
+                   DRD_(get_mutex_lock_count)());
+      DRD_(print_malloc_stats)();
+   }
+}
+
+static
+void drd_pre_clo_init(void)
+{
+   // Basic tool stuff.
+   VG_(details_name)            ("drd");
+   VG_(details_version)         (NULL);
+   VG_(details_description)     ("a thread error detector");
+   VG_(details_copyright_author)("Copyright (C) 2006-2010, and GNU GPL'd,"
+                                 " by Bart Van Assche.");
+   VG_(details_bug_reports_to)  (VG_BUGS_TO);
+
+   VG_(basic_tool_funcs)        (DRD_(post_clo_init),
+                                 DRD_(instrument),
+                                 DRD_(fini));
+
+   // Command line stuff.
+   VG_(needs_command_line_options)(DRD_(process_cmd_line_option),
+                                   DRD_(print_usage),
+                                   DRD_(print_debug_usage));
+
+   // Error handling.
+   DRD_(register_error_handlers)();
+
+   // Core event tracking.
+   VG_(track_pre_mem_read)         (drd_pre_mem_read);
+   VG_(track_pre_mem_read_asciiz)  (drd_pre_mem_read_asciiz);
+   VG_(track_post_mem_write)       (drd_post_mem_write);
+   VG_(track_new_mem_brk)          (drd_start_using_mem_w_tid);
+   VG_(track_new_mem_mmap)         (drd_start_using_mem_w_perms);
+   VG_(track_new_mem_stack)        (drd_start_using_mem_stack);
+   VG_(track_new_mem_stack_signal) (drd_start_using_mem_stack_signal);
+   VG_(track_new_mem_startup)      (drd_start_using_mem_w_perms);
+   VG_(track_die_mem_brk)          (drd_stop_using_nonstack_mem);
+   VG_(track_die_mem_munmap)       (drd_stop_using_nonstack_mem);
+   VG_(track_die_mem_stack)        (drd_stop_using_mem_stack);
+   VG_(track_die_mem_stack_signal) (drd_stop_using_mem_stack_signal);
+   VG_(track_pre_deliver_signal)   (drd_pre_deliver_signal);
+   VG_(track_post_deliver_signal)  (drd_post_deliver_signal);
+   VG_(track_start_client_code)    (drd_start_client_code);
+   VG_(track_pre_thread_ll_create) (drd_pre_thread_create);
+   VG_(track_pre_thread_first_insn)(drd_post_thread_create);
+   VG_(track_pre_thread_ll_exit)   (drd_thread_finished);
+
+   // Other stuff.
+   DRD_(register_malloc_wrappers)(drd_start_using_mem_w_ecu,
+                                  drd_stop_using_nonstack_mem);
+
+   DRD_(clientreq_init)();
+
+   DRD_(suppression_init)();
+
+   DRD_(clientobj_init)();
+
+   {
+      Char* const smi = VG_(getenv)("DRD_SEGMENT_MERGING_INTERVAL");
+      if (smi)
+         DRD_(thread_set_segment_merge_interval)(VG_(strtoll10)(smi, NULL));
+   }
+}
+
+
+VG_DETERMINE_INTERFACE_VERSION(drd_pre_clo_init)
diff --git a/drd/drd_malloc_wrappers.c b/drd/drd_malloc_wrappers.c
new file mode 100644
index 0000000..6eeffdb
--- /dev/null
+++ b/drd/drd_malloc_wrappers.c
@@ -0,0 +1,376 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#include "drd_malloc_wrappers.h"
+#include "drd_thread.h"
+#include "pub_tool_basics.h"
+#include "pub_tool_execontext.h"
+#include "pub_tool_hashtable.h"
+#include "pub_tool_libcassert.h"
+#include "pub_tool_libcbase.h"
+#include "pub_tool_libcprint.h"
+#include "pub_tool_mallocfree.h"
+#include "pub_tool_options.h"
+#include "pub_tool_replacemalloc.h"
+#include "pub_tool_threadstate.h"
+#include "pub_tool_tooliface.h"
+
+
+/* Local type definitions. */
+
+/**
+ * Node with per-allocation information that will be stored in a hash map.
+ * As specified in <pub_tool_hashtable.h>, the first member must be a pointer
+ * and the second member must be an UWord.
+ */
+typedef struct _DRD_Chunk {
+   struct _DRD_Chunk* next;
+   UWord              data;   // pointer to actual block
+   SizeT              size;   // size requested
+   ExeContext*        where;  // where it was allocated
+} DRD_Chunk;
+
+
+/* Local variables. */
+
+static StartUsingMem s_start_using_mem_callback;
+static StopUsingMem  s_stop_using_mem_callback;
+/* Statistics. */
+static SizeT s_cmalloc_n_mallocs  = 0;
+static SizeT s_cmalloc_n_frees    = 0;
+static SizeT s_cmalloc_bs_mallocd = 0;
+/* Record malloc'd blocks. */
+static VgHashTable s_malloc_list = NULL;
+
+
+/* Function definitions. */
+
+/** Allocate client memory memory and update the hash map. */
+static void* new_block(ThreadId tid, SizeT size, SizeT align, Bool is_zeroed)
+{
+   void* p;
+
+   p = VG_(cli_malloc)(align, size);
+   if (!p)
+      return NULL;
+   if (is_zeroed)
+      VG_(memset)(p, 0, size);
+
+   DRD_(malloclike_block)(tid, (Addr)p, size);
+
+   return p;
+}
+
+/**
+ * Store information about a memory block that has been allocated by
+ * malloc() or a malloc() replacement in the hash map.
+ */
+void DRD_(malloclike_block)(const ThreadId tid, const Addr p, const SizeT size)
+{
+   DRD_Chunk* mc;
+
+   tl_assert(p);
+
+   if (size > 0)
+      s_start_using_mem_callback(p, size, 0/*ec_uniq*/);
+
+   s_cmalloc_n_mallocs++;
+   // Only update this stat if allocation succeeded.
+   s_cmalloc_bs_mallocd += size;
+
+   mc = VG_(malloc)("drd.malloc_wrappers.cDC.1", sizeof(DRD_Chunk));
+   mc->data  = p;
+   mc->size  = size;
+   mc->where = VG_(record_ExeContext)(tid, 0);
+   VG_(HT_add_node)(s_malloc_list, mc);
+}
+
+static void handle_free(ThreadId tid, void* p)
+{
+   tl_assert(p);
+
+   if (DRD_(freelike_block)(tid, (Addr)p))
+      VG_(cli_free)(p);
+   else
+      tl_assert(False);
+}
+
+/**
+ * Remove the information that was stored by DRD_(malloclike_block)() about
+ * a memory block.
+ */
+Bool DRD_(freelike_block)(const ThreadId tid, const Addr p)
+{
+   DRD_Chunk* mc;
+
+   tl_assert(p);
+
+   s_cmalloc_n_frees++;
+
+   mc = VG_(HT_remove)(s_malloc_list, (UWord)p);
+   if (mc)
+   {
+      tl_assert(p == mc->data);
+      if (mc->size > 0)
+         s_stop_using_mem_callback(mc->data, mc->size);
+      VG_(free)(mc);
+      return True;
+   }
+   return False;
+}
+
+/** Wrapper for malloc(). */
+static void* drd_malloc(ThreadId tid, SizeT n)
+{
+   return new_block(tid, n, VG_(clo_alignment), /*is_zeroed*/False);
+}
+
+/** Wrapper for memalign(). */
+static void* drd_memalign(ThreadId tid, SizeT align, SizeT n)
+{
+   return new_block(tid, n, align, /*is_zeroed*/False);
+}
+
+/** Wrapper for calloc(). */
+static void* drd_calloc(ThreadId tid, SizeT nmemb, SizeT size1)
+{
+   return new_block(tid, nmemb*size1, VG_(clo_alignment),
+                          /*is_zeroed*/True);
+}
+
+/** Wrapper for free(). */
+static void drd_free(ThreadId tid, void* p)
+{
+   handle_free(tid, p);
+}
+
+/**
+ * Wrapper for realloc(). Returns a pointer to the new block of memory, or
+ * NULL if no new block could not be allocated. Notes:
+ * - realloc(NULL, size) has the same effect as malloc(size).
+ * - realloc(p, 0) has the same effect as free(p).
+ * - success is not guaranteed even if the requested size is smaller than the
+ *   allocated size.
+*/
+static void* drd_realloc(ThreadId tid, void* p_old, SizeT new_size)
+{
+   DRD_Chunk* mc;
+   void*      p_new;
+   SizeT      old_size;
+
+   if (! p_old)
+      return drd_malloc(tid, new_size);
+
+   if (new_size == 0)
+   {
+      drd_free(tid, p_old);
+      return NULL;
+   }
+
+   s_cmalloc_n_mallocs++;
+   s_cmalloc_n_frees++;
+   s_cmalloc_bs_mallocd += new_size;
+
+   mc = VG_(HT_lookup)(s_malloc_list, (UWord)p_old);
+   if (mc == NULL)
+   {
+      tl_assert(0);
+      return NULL;
+   }
+
+   old_size = mc->size;
+
+   if (old_size == new_size)
+   {
+      /* size unchanged */
+      mc->where = VG_(record_ExeContext)(tid, 0);
+      p_new = p_old;
+   }
+   else if (new_size < old_size)
+   {
+      /* new size is smaller but nonzero */
+      s_stop_using_mem_callback(mc->data + new_size, old_size - new_size);
+      mc->size = new_size;
+      mc->where = VG_(record_ExeContext)(tid, 0);
+      p_new = p_old;
+   }
+   else
+   {
+      /* new size is bigger */
+      p_new = VG_(cli_malloc)(VG_(clo_alignment), new_size);
+
+      if (p_new)
+      {
+         /* Copy from old to new. */
+         VG_(memcpy)(p_new, p_old, mc->size);
+
+         /* Free old memory. */
+         VG_(cli_free)(p_old);
+         if (mc->size > 0)
+            s_stop_using_mem_callback(mc->data, mc->size);
+         VG_(HT_remove)(s_malloc_list, (UWord)p_old);
+
+         /* Update state information. */
+         mc->data  = (Addr)p_new;
+         mc->size  = new_size;
+         mc->where = VG_(record_ExeContext)(tid, 0);
+         VG_(HT_add_node)(s_malloc_list, mc);
+         s_start_using_mem_callback((Addr)p_new, new_size, 0/*ec_uniq*/);
+      }
+      else
+      {
+         /* Allocation failed -- leave original block untouched. */
+      }
+   }
+
+   return p_new;
+}
+
+/** Wrapper for __builtin_new(). */
+static void* drd___builtin_new(ThreadId tid, SizeT n)
+{
+   return new_block(tid, n, VG_(clo_alignment), /*is_zeroed*/False);
+}
+
+/** Wrapper for __builtin_delete(). */
+static void drd___builtin_delete(ThreadId tid, void* p)
+{
+   handle_free(tid, p);
+}
+
+/** Wrapper for __builtin_vec_new(). */
+static void* drd___builtin_vec_new(ThreadId tid, SizeT n)
+{
+   return new_block(tid, n, VG_(clo_alignment), /*is_zeroed*/False);
+}
+
+/** Wrapper for __builtin_vec_delete(). */
+static void drd___builtin_vec_delete(ThreadId tid, void* p)
+{
+   handle_free(tid, p);
+}
+
+/**
+ * Wrapper for malloc_usable_size() / malloc_size(). This function takes
+ * a pointer to a block allocated by `malloc' and returns the amount of space
+ * that is available in the block. This may or may not be more than the size
+ * requested from `malloc', due to alignment or minimum size constraints.
+ */
+static SizeT drd_malloc_usable_size(ThreadId tid, void* p)
+{
+   DRD_Chunk* mc;
+
+   mc = VG_(HT_lookup)(s_malloc_list, (UWord)p);
+
+   return mc ? mc->size : 0;
+}
+
+void DRD_(register_malloc_wrappers)(const StartUsingMem start_callback,
+                                    const StopUsingMem stop_callback)
+{
+   tl_assert(s_malloc_list == 0);
+   s_malloc_list = VG_(HT_construct)("drd_malloc_list");
+   tl_assert(s_malloc_list);
+   tl_assert(start_callback);
+   tl_assert(stop_callback);
+
+   s_start_using_mem_callback = start_callback;
+   s_stop_using_mem_callback  = stop_callback;
+
+   VG_(needs_malloc_replacement)(drd_malloc,
+                                 drd___builtin_new,
+                                 drd___builtin_vec_new,
+                                 drd_memalign,
+                                 drd_calloc,
+                                 drd_free,
+                                 drd___builtin_delete,
+                                 drd___builtin_vec_delete,
+                                 drd_realloc,
+                                 drd_malloc_usable_size,
+                                 0);
+}
+
+Bool DRD_(heap_addrinfo)(Addr const a,
+                         Addr* const data,
+                         SizeT* const size,
+                         ExeContext** const where)
+{
+   DRD_Chunk* mc;
+
+   tl_assert(data);
+   tl_assert(size);
+   tl_assert(where);
+
+   VG_(HT_ResetIter)(s_malloc_list);
+   while ((mc = VG_(HT_Next)(s_malloc_list)))
+   {
+      if (mc->data <= a && a < mc->data + mc->size)
+      {
+         *data  = mc->data;
+         *size  = mc->size;
+         *where = mc->where;
+         return True;
+      }
+   }
+   return False;
+}
+
+/*------------------------------------------------------------*/
+/*--- Statistics printing                                  ---*/
+/*------------------------------------------------------------*/
+
+void DRD_(print_malloc_stats)(void)
+{
+   DRD_Chunk* mc;
+   SizeT     nblocks = 0;
+   SizeT     nbytes  = 0;
+
+   if (VG_(clo_verbosity) == 0)
+      return;
+   if (VG_(clo_xml))
+      return;
+
+   /* Count memory still in use. */
+   VG_(HT_ResetIter)(s_malloc_list);
+   while ((mc = VG_(HT_Next)(s_malloc_list)))
+   {
+      nblocks++;
+      nbytes += mc->size;
+   }
+
+   VG_(message)(Vg_DebugMsg,
+                "malloc/free: in use at exit: %lu bytes in %lu blocks.\n",
+                nbytes, nblocks);
+   VG_(message)(Vg_DebugMsg,
+                "malloc/free: %lu allocs, %lu frees, %lu bytes allocated.\n",
+                s_cmalloc_n_mallocs,
+                s_cmalloc_n_frees, s_cmalloc_bs_mallocd);
+   if (VG_(clo_verbosity) > 1)
+      VG_(message)(Vg_DebugMsg, " \n");
+}
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
diff --git a/drd/drd_malloc_wrappers.h b/drd/drd_malloc_wrappers.h
new file mode 100644
index 0000000..2f9c2ce
--- /dev/null
+++ b/drd/drd_malloc_wrappers.h
@@ -0,0 +1,49 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __MALLOC_WRAPPERS_H
+#define __MALLOC_WRAPPERS_H
+
+
+#include "drd_basics.h"          /* DRD_() */
+#include "pub_tool_basics.h"     /* Bool */
+#include "pub_tool_execontext.h" /* ExeContext */
+
+
+typedef void (*StartUsingMem)(const Addr a1, const SizeT len, UInt ec_uniq);
+typedef void (*StopUsingMem)(const Addr a1, const SizeT len);
+
+
+void DRD_(register_malloc_wrappers)(const StartUsingMem start_callback,
+                                    const StopUsingMem stop_callback);
+void DRD_(malloclike_block)(const ThreadId tid, const Addr p, const SizeT size);
+Bool DRD_(freelike_block)(const ThreadId tid, const Addr p);
+Bool DRD_(heap_addrinfo)(Addr const a,
+                         Addr* const data,
+                         SizeT* const size,
+                         ExeContext** const where);
+void DRD_(print_malloc_stats)(void);
+
+
+#endif // __MALLOC_WRAPPERS_H
diff --git a/drd/drd_mutex.c b/drd/drd_mutex.c
new file mode 100644
index 0000000..87494f8
--- /dev/null
+++ b/drd/drd_mutex.c
@@ -0,0 +1,547 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#include "drd_basics.h"
+#include "drd_clientobj.h"
+#include "drd_error.h"
+#include "drd_mutex.h"
+#include "pub_tool_vki.h"
+#include "pub_tool_errormgr.h"    // VG_(maybe_record_error)()
+#include "pub_tool_libcassert.h"  // tl_assert()
+#include "pub_tool_libcbase.h"    // VG_(strlen)
+#include "pub_tool_libcprint.h"   // VG_(message)()
+#include "pub_tool_libcproc.h"    // VG_(read_millisecond_timer)()
+#include "pub_tool_machine.h"     // VG_(get_IP)()
+#include "pub_tool_threadstate.h" // VG_(get_running_tid)()
+
+
+/* Local functions. */
+
+static void mutex_cleanup(struct mutex_info* p);
+static Bool mutex_is_locked(struct mutex_info* const p);
+static void mutex_delete_thread(struct mutex_info* p, const DrdThreadId tid);
+
+
+/* Local variables. */
+
+static Bool s_trace_mutex;
+static ULong s_mutex_lock_count;
+static ULong s_mutex_segment_creation_count;
+static UInt s_mutex_lock_threshold_ms = 1000 * 1000;
+
+
+/* Function definitions. */
+
+void DRD_(mutex_set_trace)(const Bool trace_mutex)
+{
+   tl_assert(!! trace_mutex == trace_mutex);
+   s_trace_mutex = trace_mutex;
+}
+
+void DRD_(mutex_set_lock_threshold)(const UInt lock_threshold_ms)
+{
+   s_mutex_lock_threshold_ms = lock_threshold_ms;
+}
+
+static
+void DRD_(mutex_initialize)(struct mutex_info* const p,
+                            const Addr mutex, const MutexT mutex_type)
+{
+   tl_assert(mutex);
+   tl_assert(p->a1 == mutex);
+
+   p->cleanup             = (void(*)(DrdClientobj*))mutex_cleanup;
+   p->delete_thread
+      = (void(*)(DrdClientobj*, DrdThreadId))mutex_delete_thread;
+   p->mutex_type          = mutex_type;
+   p->recursion_count     = 0;
+   p->owner               = DRD_INVALID_THREADID;
+   p->last_locked_segment = 0;
+   p->acquiry_time_ms     = 0;
+   p->acquired_at         = 0;
+}
+
+/** Deallocate the memory that was allocated by mutex_initialize(). */
+static void mutex_cleanup(struct mutex_info* p)
+{
+   tl_assert(p);
+
+   if (s_trace_mutex)
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] mutex_destroy   %s 0x%lx rc %d owner %d\n",
+                   DRD_(thread_get_running_tid)(),
+                   DRD_(mutex_get_typename)(p),
+                   p->a1,
+                   p ? p->recursion_count : -1,
+                   p ? p->owner : DRD_INVALID_THREADID);
+   }
+
+   if (mutex_is_locked(p))
+   {
+      MutexErrInfo MEI = { DRD_(thread_get_running_tid)(),
+                           p->a1, p->recursion_count, p->owner };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              MutexErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "Destroying locked mutex",
+                              &MEI);
+   }
+
+   DRD_(sg_put)(p->last_locked_segment);
+   p->last_locked_segment = 0;
+}
+
+/** Report that address 'mutex' is not the address of a mutex object. */
+void DRD_(not_a_mutex)(const Addr mutex)
+{
+   MutexErrInfo MEI = { DRD_(thread_get_running_tid)(),
+                        mutex, -1, DRD_INVALID_THREADID };
+   VG_(maybe_record_error)(VG_(get_running_tid)(),
+                           MutexErr,
+                           VG_(get_IP)(VG_(get_running_tid)()),
+                           "Not a mutex",
+                           &MEI);
+}
+
+/**
+ * Report that address 'mutex' is not the address of a mutex object of the
+ * expected type.
+ */
+static void wrong_mutex_type(const Addr mutex)
+{
+   MutexErrInfo MEI = { DRD_(thread_get_running_tid)(),
+                        mutex, -1, DRD_INVALID_THREADID };
+   VG_(maybe_record_error)(VG_(get_running_tid)(),
+                           MutexErr,
+                           VG_(get_IP)(VG_(get_running_tid)()),
+                           "Mutex type mismatch",
+                           &MEI);
+}
+
+static
+struct mutex_info*
+DRD_(mutex_get_or_allocate)(const Addr mutex, const MutexT mutex_type)
+{
+   struct mutex_info* p;
+
+   tl_assert(offsetof(DrdClientobj, mutex) == 0);
+   p = &(DRD_(clientobj_get)(mutex, ClientMutex)->mutex);
+   if (p)
+   {
+      if (mutex_type == mutex_type_unknown || p->mutex_type == mutex_type)
+	 return p;
+      else
+      {
+	 wrong_mutex_type(mutex);
+	 return 0;
+      }
+   }
+
+   if (DRD_(clientobj_present)(mutex, mutex + 1))
+   {
+      DRD_(not_a_mutex)(mutex);
+      return 0;
+   }
+
+   p = &(DRD_(clientobj_add)(mutex, ClientMutex)->mutex);
+   DRD_(mutex_initialize)(p, mutex, mutex_type);
+   return p;
+}
+
+struct mutex_info* DRD_(mutex_get)(const Addr mutex)
+{
+   tl_assert(offsetof(DrdClientobj, mutex) == 0);
+   return &(DRD_(clientobj_get)(mutex, ClientMutex)->mutex);
+}
+
+/** Called before pthread_mutex_init(). */
+struct mutex_info*
+DRD_(mutex_init)(const Addr mutex, const MutexT mutex_type)
+{
+   struct mutex_info* p;
+
+   if (s_trace_mutex)
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] mutex_init      %s 0x%lx\n",
+                   DRD_(thread_get_running_tid)(),
+                   DRD_(mutex_type_name)(mutex_type),
+                   mutex);
+   }
+
+   if (mutex_type == mutex_type_invalid_mutex)
+   {
+      DRD_(not_a_mutex)(mutex);
+      return 0;
+   }
+
+   p = DRD_(mutex_get)(mutex);
+   if (p)
+   {
+      const ThreadId vg_tid = VG_(get_running_tid)();
+      MutexErrInfo MEI = { DRD_(thread_get_running_tid)(),
+                           p->a1, p->recursion_count, p->owner };
+      VG_(maybe_record_error)(vg_tid,
+                              MutexErr,
+                              VG_(get_IP)(vg_tid),
+                              "Mutex reinitialization",
+                              &MEI);
+      p->mutex_type = mutex_type;
+      return p;
+   }
+   p = DRD_(mutex_get_or_allocate)(mutex, mutex_type);
+
+   return p;
+}
+
+/** Called after pthread_mutex_destroy(). */
+void DRD_(mutex_post_destroy)(const Addr mutex)
+{
+   struct mutex_info* p;
+
+   p = DRD_(mutex_get)(mutex);
+   if (p == 0)
+   {
+      DRD_(not_a_mutex)(mutex);
+      return;
+   }
+
+   DRD_(clientobj_remove)(mutex, ClientMutex);
+}
+
+/**
+ * Called before pthread_mutex_lock() is invoked. If a data structure for the
+ * client-side object was not yet created, do this now. Also check whether an
+ * attempt is made to lock recursively a synchronization object that must not
+ * be locked recursively.
+ */
+void DRD_(mutex_pre_lock)(const Addr mutex, MutexT mutex_type,
+                          const Bool trylock)
+{
+   struct mutex_info* p;
+
+   p = DRD_(mutex_get_or_allocate)(mutex, mutex_type);
+   if (p && mutex_type == mutex_type_unknown)
+      mutex_type = p->mutex_type;
+
+   if (s_trace_mutex)
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] %s %s 0x%lx rc %d owner %d\n",
+                   DRD_(thread_get_running_tid)(),
+                   trylock ? "pre_mutex_lock " : "mutex_trylock  ",
+                   p ? DRD_(mutex_get_typename)(p) : "(?)",
+                   mutex,
+                   p ? p->recursion_count : -1,
+                   p ? p->owner : DRD_INVALID_THREADID);
+   }
+
+   if (p == 0)
+   {
+      DRD_(not_a_mutex)(mutex);
+      return;
+   }
+
+   tl_assert(p);
+
+   if (mutex_type == mutex_type_invalid_mutex)
+   {
+      DRD_(not_a_mutex)(mutex);
+      return;
+   }
+
+   if (! trylock
+       && p->owner == DRD_(thread_get_running_tid)()
+       && p->recursion_count >= 1
+       && mutex_type != mutex_type_recursive_mutex)
+   {
+      MutexErrInfo MEI = { DRD_(thread_get_running_tid)(),
+                           p->a1, p->recursion_count, p->owner };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              MutexErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "Recursive locking not allowed",
+                              &MEI);
+   }
+}
+
+/**
+ * Update mutex_info state when locking the pthread_mutex_t mutex.
+ * Note: this function must be called after pthread_mutex_lock() has been
+ * called, or a race condition is triggered !
+ */
+void DRD_(mutex_post_lock)(const Addr mutex, const Bool took_lock,
+                           const Bool post_cond_wait)
+{
+   const DrdThreadId drd_tid = DRD_(thread_get_running_tid)();
+   struct mutex_info* p;
+
+   p = DRD_(mutex_get)(mutex);
+
+   if (s_trace_mutex)
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] %s %s 0x%lx rc %d owner %d%s\n",
+                   drd_tid,
+                   post_cond_wait ? "cond_post_wait " : "post_mutex_lock",
+                   p ? DRD_(mutex_get_typename)(p) : "(?)",
+                   mutex,
+                   p ? p->recursion_count : 0,
+                   p ? p->owner : VG_INVALID_THREADID,
+                   took_lock ? "" : " (locking failed)");
+   }
+
+   if (! p || ! took_lock)
+      return;
+
+   if (p->recursion_count == 0)
+   {
+      if (p->owner != drd_tid && p->owner != DRD_INVALID_THREADID)
+      {
+         tl_assert(p->last_locked_segment);
+
+         DRD_(thread_new_segment_and_combine_vc)(drd_tid,
+                                                 p->last_locked_segment);
+      }
+      else
+         DRD_(thread_new_segment)(drd_tid);
+
+      s_mutex_segment_creation_count++;
+
+      p->owner           = drd_tid;
+      p->acquiry_time_ms = VG_(read_millisecond_timer)();
+      p->acquired_at     = VG_(record_ExeContext)(VG_(get_running_tid)(), 0);
+      s_mutex_lock_count++;
+   }
+   else if (p->owner != drd_tid)
+   {
+      VG_(message)(Vg_UserMsg,
+                   "The impossible happened: mutex 0x%lx is locked"
+                   " simultaneously by two threads (recursion count %d,"
+                   " owners %d and %d) !\n",
+                   p->a1, p->recursion_count, p->owner, drd_tid);
+      p->owner = drd_tid;
+   }
+   p->recursion_count++;
+}
+
+/**
+ * Update mutex_info state when unlocking the pthread_mutex_t mutex.
+ *
+ * @param[in] mutex      Address of the client mutex.
+ * @param[in] mutex_type Mutex type.
+ *
+ * @return New value of the mutex recursion count.
+ *
+ * @note This function must be called before pthread_mutex_unlock() is called,
+ *       or a race condition is triggered !
+ */
+void DRD_(mutex_unlock)(const Addr mutex, MutexT mutex_type)
+{
+   const DrdThreadId drd_tid = DRD_(thread_get_running_tid)();
+   const ThreadId vg_tid = VG_(get_running_tid)();
+   struct mutex_info* p;
+
+   p = DRD_(mutex_get)(mutex);
+   if (p && mutex_type == mutex_type_unknown)
+      mutex_type = p->mutex_type;
+
+   if (s_trace_mutex)
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] mutex_unlock    %s 0x%lx rc %d\n",
+                   drd_tid,
+                   p ? DRD_(mutex_get_typename)(p) : "(?)",
+                   mutex,
+                   p ? p->recursion_count : 0);
+   }
+
+   if (p == 0 || mutex_type == mutex_type_invalid_mutex)
+   {
+      DRD_(not_a_mutex)(mutex);
+      return;
+   }
+
+   if (p->owner == DRD_INVALID_THREADID)
+   {
+      MutexErrInfo MEI = { DRD_(thread_get_running_tid)(),
+                           p->a1, p->recursion_count, p->owner };
+      VG_(maybe_record_error)(vg_tid,
+                              MutexErr,
+                              VG_(get_IP)(vg_tid),
+                              "Mutex not locked",
+                              &MEI);
+      return;
+   }
+
+   tl_assert(p);
+   if (p->mutex_type != mutex_type)
+   {
+      VG_(message)(Vg_UserMsg, "??? mutex 0x%lx: type changed from %d into %d\n",
+                   p->a1, p->mutex_type, mutex_type);
+   }
+   tl_assert(p->mutex_type == mutex_type);
+   tl_assert(p->owner != DRD_INVALID_THREADID);
+
+   if (p->owner != drd_tid || p->recursion_count <= 0)
+   {
+      MutexErrInfo MEI = { DRD_(thread_get_running_tid)(),
+                           p->a1, p->recursion_count, p->owner };
+      VG_(maybe_record_error)(vg_tid,
+                              MutexErr,
+                              VG_(get_IP)(vg_tid),
+                              "Mutex not locked by calling thread",
+                              &MEI);
+      return;
+   }
+   tl_assert(p->recursion_count > 0);
+   p->recursion_count--;
+   tl_assert(p->recursion_count >= 0);
+
+   if (p->recursion_count == 0)
+   {
+      if (s_mutex_lock_threshold_ms > 0)
+      {
+         Long held = VG_(read_millisecond_timer)() - p->acquiry_time_ms;
+         if (held > s_mutex_lock_threshold_ms)
+         {
+            HoldtimeErrInfo HEI
+               = { DRD_(thread_get_running_tid)(),
+                   mutex, p->acquired_at, held, s_mutex_lock_threshold_ms };
+            VG_(maybe_record_error)(vg_tid,
+                                    HoldtimeErr,
+                                    VG_(get_IP)(vg_tid),
+                                    "mutex",
+                                    &HEI);
+         }
+      }
+
+      /* This pthread_mutex_unlock() call really unlocks the mutex. Save the */
+      /* current vector clock of the thread such that it is available when  */
+      /* this mutex is locked again.                                        */
+
+      DRD_(thread_get_latest_segment)(&p->last_locked_segment, drd_tid);
+      DRD_(thread_new_segment)(drd_tid);
+      p->acquired_at = 0;
+      s_mutex_segment_creation_count++;
+   }
+}
+
+void DRD_(spinlock_init_or_unlock)(const Addr spinlock)
+{
+   struct mutex_info* mutex_p = DRD_(mutex_get)(spinlock);
+   if (mutex_p)
+   {
+      DRD_(mutex_unlock)(spinlock, mutex_type_spinlock);
+   }
+   else
+   {
+      DRD_(mutex_init)(spinlock, mutex_type_spinlock);
+   }
+}
+
+const char* DRD_(mutex_get_typename)(struct mutex_info* const p)
+{
+   tl_assert(p);
+
+   return DRD_(mutex_type_name)(p->mutex_type);
+}
+
+const char* DRD_(mutex_type_name)(const MutexT mt)
+{
+   switch (mt)
+   {
+   case mutex_type_unknown:
+      return "mutex";
+   case mutex_type_invalid_mutex:
+      return "invalid mutex";
+   case mutex_type_recursive_mutex:
+      return "recursive mutex";
+   case mutex_type_errorcheck_mutex:
+      return "error checking mutex";
+   case mutex_type_default_mutex:
+      return "mutex";
+   case mutex_type_spinlock:
+      return "spinlock";
+   }
+   tl_assert(0);
+   return "?";
+}
+
+/** Return true if the specified mutex is locked by any thread. */
+static Bool mutex_is_locked(struct mutex_info* const p)
+{
+   tl_assert(p);
+   return (p->recursion_count > 0);
+}
+
+Bool DRD_(mutex_is_locked_by)(const Addr mutex, const DrdThreadId tid)
+{
+   struct mutex_info* const p = DRD_(mutex_get)(mutex);
+   if (p)
+   {
+      return (p->recursion_count > 0 && p->owner == tid);
+   }
+   return False;
+}
+
+int DRD_(mutex_get_recursion_count)(const Addr mutex)
+{
+   struct mutex_info* const p = DRD_(mutex_get)(mutex);
+   tl_assert(p);
+   return p->recursion_count;
+}
+
+/**
+ * Call this function when thread tid stops to exist, such that the
+ * "last owner" field can be cleared if it still refers to that thread.
+ */
+static void mutex_delete_thread(struct mutex_info* p, const DrdThreadId tid)
+{
+   tl_assert(p);
+
+   if (p->owner == tid && p->recursion_count > 0)
+   {
+      MutexErrInfo MEI = { DRD_(thread_get_running_tid)(),
+                           p->a1, p->recursion_count, p->owner };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              MutexErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "Mutex still locked at thread exit",
+                              &MEI);
+      p->owner = VG_INVALID_THREADID;
+   }
+}
+
+ULong DRD_(get_mutex_lock_count)(void)
+{
+   return s_mutex_lock_count;
+}
+
+ULong DRD_(get_mutex_segment_creation_count)(void)
+{
+   return s_mutex_segment_creation_count;
+}
diff --git a/drd/drd_mutex.h b/drd/drd_mutex.h
new file mode 100644
index 0000000..c619ff5
--- /dev/null
+++ b/drd/drd_mutex.h
@@ -0,0 +1,58 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#ifndef __DRD_MUTEX_H
+#define __DRD_MUTEX_H
+
+
+#include "drd_clientreq.h"        // MutexT
+#include "drd_thread.h"           // DrdThreadId
+#include "pub_tool_basics.h"      // Addr
+
+
+struct mutex_info;
+
+
+void DRD_(mutex_set_trace)(const Bool trace_mutex);
+void DRD_(mutex_set_lock_threshold)(const UInt lock_threshold_ms);
+struct mutex_info* DRD_(mutex_init)(const Addr mutex, const MutexT mutex_type);
+void DRD_(mutex_post_destroy)(const Addr mutex);
+void DRD_(not_a_mutex)(const Addr mutex);
+struct mutex_info* DRD_(mutex_get)(const Addr mutex);
+void DRD_(mutex_pre_lock)(const Addr mutex, const MutexT mutex_type,
+                          const Bool trylock);
+void DRD_(mutex_post_lock)(const Addr mutex, const Bool took_lock,
+                           const Bool post_cond_wait);
+void DRD_(mutex_unlock)(const Addr mutex, const MutexT mutex_type);
+void DRD_(spinlock_init_or_unlock)(const Addr spinlock);
+const char* DRD_(mutex_get_typename)(struct mutex_info* const p);
+const char* DRD_(mutex_type_name)(const MutexT mt);
+Bool DRD_(mutex_is_locked_by)(const Addr mutex, const DrdThreadId tid);
+int DRD_(mutex_get_recursion_count)(const Addr mutex);
+ULong DRD_(get_mutex_lock_count)(void);
+ULong DRD_(get_mutex_segment_creation_count)(void);
+
+
+#endif /* __DRD_MUTEX_H */
diff --git a/drd/drd_pthread_intercepts.c b/drd/drd_pthread_intercepts.c
new file mode 100644
index 0000000..44da42d
--- /dev/null
+++ b/drd/drd_pthread_intercepts.c
@@ -0,0 +1,1235 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+
+/*--------------------------------------------------------------------*/
+/*--- Client-space code for DRD.          drd_pthread_intercepts.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+  This file is part of DRD, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+/* ---------------------------------------------------------------------
+   ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU.
+
+   These functions are not called directly - they're the targets of code
+   redirection or load notifications (see pub_core_redir.h for info).
+   They're named weirdly so that the intercept code can find them when the
+   shared object is initially loaded.
+
+   Note that this filename has the "drd_" prefix because it can appear
+   in stack traces, and the "drd_" makes it a little clearer that it
+   originates from Valgrind.
+   ------------------------------------------------------------------ */
+
+/*
+ * Define _GNU_SOURCE to make sure that pthread_spinlock_t is available when
+ * compiling with older glibc versions (2.3 or before).
+ */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <assert.h>         /* assert() */
+#include <pthread.h>        /* pthread_mutex_t */
+#include <semaphore.h>      /* sem_t */
+#include <stdint.h>         /* uintptr_t */
+#include <stdio.h>          /* fprintf() */
+#include <stdlib.h>         /* malloc(), free() */
+#include <unistd.h>         /* confstr() */
+#include "config.h"         /* HAVE_PTHREAD_MUTEX_ADAPTIVE_NP etc. */
+#include "drd_basics.h"     /* DRD_() */
+#include "drd_clientreq.h"
+#include "pub_tool_redir.h" /* VG_WRAP_FUNCTION_ZZ() */
+
+
+/* Defines. */
+
+/*
+ * Do not undefine the two macro's below, or the following two subtle race
+ * conditions will be introduced in the data race detection algorithm:
+ * - sg_init() runs on the context of the created thread and copies the
+ *   vector clock of the creator thread. This only works reliably if
+ *   the creator thread waits until this copy has been performed.
+ * - Since DRD_(thread_compute_minimum_vc)() does not take the vector
+ *   clocks into account that are involved in thread creation but
+ *   for which the corresponding thread has not yet been created, by
+ *   undefining the macro below it becomes possible that segments get
+ *   discarded that should not yet be discarded. Or: some data races
+ *   are not detected.
+ */
+#define WAIT_UNTIL_CREATED_THREAD_STARTED
+#define ALLOCATE_THREAD_ARGS_ON_THE_STACK
+
+/**
+ * Macro for generating a Valgrind interception function.
+ * @param[in] ret_ty Return type of the function to be generated.
+ * @param[in] zf Z-encoded name of the interception function.
+ * @param[in] implf Name of the function that implements the intercept.
+ * @param[in] arg_decl Argument declaration list enclosed in parentheses.
+ * @param[in] argl Argument list enclosed in parentheses.
+ */
+#define PTH_FUNC(ret_ty, zf, implf, argl_decl, argl)                    \
+   ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl;     \
+   ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl      \
+   { return implf argl; }
+
+/**
+ * Macro for generating three Valgrind interception functions: one with the
+ * Z-encoded name zf, one with ZAZa ("@*") appended to the name zf and one
+ * with ZDZa ("$*") appended to the name zf. The second generated interception
+ * function will intercept versioned symbols on Linux, and the third will
+ * intercept versioned symbols on Darwin.
+ */
+#define PTH_FUNCS(ret_ty, zf, implf, argl_decl, argl)           \
+   PTH_FUNC(ret_ty, zf, implf, argl_decl, argl);                \
+   PTH_FUNC(ret_ty, zf ## ZAZa, implf, argl_decl, argl);        \
+   PTH_FUNC(ret_ty, zf ## ZDZa, implf, argl_decl, argl);
+
+/*
+ * Not inlining one of the intercept functions will cause the regression
+ * tests to fail because this would cause an additional stackfram to appear
+ * in the output. The __always_inline macro guarantees that inlining will
+ * happen, even when compiling with optimization disabled.
+ */
+#undef __always_inline /* since already defined in <cdefs.h> */
+#if __GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 2
+#define __always_inline __inline__ __attribute__((always_inline))
+#else
+#define __always_inline __inline__
+#endif
+
+/* Local data structures. */
+
+typedef struct
+{
+   void* (*start)(void*);
+   void* arg;
+   int   detachstate;
+#if defined(WAIT_UNTIL_CREATED_THREAD_STARTED)
+   int   wrapper_started;
+#endif
+} DrdPosixThreadArgs;
+
+
+/* Local function declarations. */
+
+static void DRD_(init)(void) __attribute__((constructor));
+static void DRD_(check_threading_library)(void);
+static void DRD_(set_main_thread_state)(void);
+
+
+/* Function definitions. */
+
+/**
+ * Shared library initialization function. The function init() is called after
+ * dlopen() has loaded the shared library with DRD client intercepts because
+ * the constructor attribute was specified in the declaration of this function.
+ * Note: do specify the -nostdlib option to gcc when linking this code into a
+ * shared library because doing so would cancel the effect of the constructor
+ * attribute ! Using the gcc option -nodefaultlibs is fine because this last
+ * option preserves the shared library initialization code that calls
+ * constructor and destructor functions.
+ */
+static void DRD_(init)(void)
+{
+   DRD_(check_threading_library)();
+   DRD_(set_main_thread_state)();
+}
+
+/**
+ * POSIX threads and DRD each have their own mutex type identification.
+ * Convert POSIX threads' mutex type to DRD's mutex type. In the code below
+ * if-statements are used to test the value of 'kind' instead of a switch
+ * statement because some of the PTHREAD_MUTEX_ macro's may have the same
+ * value.
+ */
+static MutexT DRD_(pthread_to_drd_mutex_type)(const int kind)
+{
+   if (kind == PTHREAD_MUTEX_RECURSIVE)
+      return mutex_type_recursive_mutex;
+   else if (kind == PTHREAD_MUTEX_ERRORCHECK)
+      return mutex_type_errorcheck_mutex;
+   else if (kind == PTHREAD_MUTEX_NORMAL)
+      return mutex_type_default_mutex;
+   else if (kind == PTHREAD_MUTEX_DEFAULT)
+      return mutex_type_default_mutex;
+#if defined(HAVE_PTHREAD_MUTEX_ADAPTIVE_NP)
+   else if (kind == PTHREAD_MUTEX_ADAPTIVE_NP)
+      return mutex_type_default_mutex;
+#endif
+   else
+   {
+      return mutex_type_invalid_mutex;
+   }
+}
+
+#define IS_ALIGNED(p) (((uintptr_t)(p) & (sizeof(*(p)) - 1)) == 0)
+
+/**
+ * Read the mutex type stored in the client memory used for the mutex
+ * implementation.
+ *
+ * @note This function depends on the implementation of the POSIX threads
+ *   library -- the POSIX standard does not define the name of the member in
+ *   which the mutex type is stored.
+ * @note The function mutex_type() has been declared inline in order
+ *   to avoid that it shows up in call stacks (drd/tests/...exp* files).
+ * @note glibc stores the mutex type in the lowest two bits, and uses the
+ *   higher bits for flags like PTHREAD_MUTEXATTR_FLAG_ROBUST and
+ *   PTHREAD_MUTEXATTR_FLAG_PSHARED.
+ */
+static __always_inline MutexT DRD_(mutex_type)(pthread_mutex_t* mutex)
+{
+#if defined(HAVE_PTHREAD_MUTEX_T__M_KIND)
+   /* glibc + LinuxThreads. */
+   if (IS_ALIGNED(&mutex->__m_kind))
+   {
+      const int kind = mutex->__m_kind & 3;
+      return DRD_(pthread_to_drd_mutex_type)(kind);
+   }
+#elif defined(HAVE_PTHREAD_MUTEX_T__DATA__KIND)
+   /* glibc + NPTL. */
+   if (IS_ALIGNED(&mutex->__data.__kind))
+   {
+      const int kind = mutex->__data.__kind & 3;
+      return DRD_(pthread_to_drd_mutex_type)(kind);
+   }
+#else
+   /*
+    * Another POSIX threads implementation. The mutex type won't be printed
+    * when enabling --trace-mutex=yes.
+    */
+#endif
+   return mutex_type_unknown;
+}
+
+/**
+ * Tell DRD whether 'tid' is a joinable thread or a detached thread.
+ */
+static void DRD_(set_joinable)(const pthread_t tid, const int joinable)
+{
+   int res;
+   assert(joinable == 0 || joinable == 1);
+   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__SET_JOINABLE,
+                              tid, joinable, 0, 0, 0);
+}
+
+/** Tell DRD that the calling thread is about to enter pthread_create(). */
+static __always_inline void DRD_(entering_pthread_create)(void)
+{
+   int res;
+   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__ENTERING_PTHREAD_CREATE,
+                              0, 0, 0, 0, 0);
+}
+
+/** Tell DRD that the calling thread has left pthread_create(). */
+static __always_inline void DRD_(left_pthread_create)(void)
+{
+   int res;
+   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__LEFT_PTHREAD_CREATE,
+                              0, 0, 0, 0, 0);
+}
+
+/**
+ * Entry point for newly created threads. This function is called from the
+ * thread created by pthread_create().
+ */
+static void* DRD_(thread_wrapper)(void* arg)
+{
+   int res;
+   DrdPosixThreadArgs* arg_ptr;
+   DrdPosixThreadArgs arg_copy;
+
+   arg_ptr = (DrdPosixThreadArgs*)arg;
+   arg_copy = *arg_ptr;
+#if defined(WAIT_UNTIL_CREATED_THREAD_STARTED)
+   arg_ptr->wrapper_started = 1;
+#else
+#if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK)
+#error Defining ALLOCATE_THREAD_ARGS_ON_THE_STACK but not \
+       WAIT_UNTIL_CREATED_THREAD_STARTED is not supported.
+#else
+   free(arg_ptr);
+#endif
+#endif
+
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID,
+                              pthread_self(), 0, 0, 0, 0);
+
+   DRD_(set_joinable)(pthread_self(),
+                      arg_copy.detachstate == PTHREAD_CREATE_JOINABLE);
+
+   return (arg_copy.start)(arg_copy.arg);
+}
+
+/**
+ * Return 1 if the LinuxThreads implementation of POSIX Threads has been
+ * detected, and 0 otherwise.
+ *
+ * @see For more information about the confstr() function, see also
+ * http://www.opengroup.org/onlinepubs/009695399/functions/confstr.html
+ */
+static int DRD_(detected_linuxthreads)(void)
+{
+#if defined(linux)
+#if defined(_CS_GNU_LIBPTHREAD_VERSION)
+   /* Linux with a recent glibc. */
+   char buffer[256];
+   unsigned len;
+   len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer));
+   assert(len <= sizeof(buffer));
+   return len > 0 && buffer[0] == 'l';
+#else
+   /* Linux without _CS_GNU_LIBPTHREAD_VERSION: most likely LinuxThreads. */
+   return 1;
+#endif
+#else
+   /* Another OS than Linux, hence no LinuxThreads. */
+   return 0;
+#endif
+}
+
+/**
+ * Stop and print an error message in case a non-supported threading
+ * library implementation (LinuxThreads) has been detected.
+ */
+static void DRD_(check_threading_library)(void)
+{
+   if (DRD_(detected_linuxthreads)())
+   {
+      if (getenv("LD_ASSUME_KERNEL"))
+      {
+         fprintf(stderr,
+"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n"
+"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n"
+"after having unset the environment variable LD_ASSUME_KERNEL. Giving up.\n"
+);
+      }
+      else
+      {
+         fprintf(stderr,
+"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n"
+"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n"
+"after having upgraded to a newer version of your Linux distribution.\n"
+"Giving up.\n"
+);
+      }
+      abort();
+   }
+}
+
+/**
+ * The main thread is the only thread not created by pthread_create().
+ * Update DRD's state information about the main thread.
+ */
+static void DRD_(set_main_thread_state)(void)
+{
+   int res;
+
+   // Make sure that DRD knows about the main thread's POSIX thread ID.
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID,
+                              pthread_self(), 0, 0, 0, 0);
+}
+
+/*
+ * Note: as of today there exist three different versions of pthread_create
+ * in Linux:
+ * - pthread_create@GLIBC_2.0
+ * - pthread_create@@GLIBC_2.1
+ * - pthread_create@@GLIBC_2.2.5
+ * As an example, in libpthread-2.3.4 both pthread_create@GLIBC_2.0 and
+ * pthread_create@@GLIBC_2.1 are defined, while in libpthread-2.9 all three
+ * versions have been implemented. In any glibc version where more than one
+ * pthread_create function has been implemented, older versions call the
+ * newer versions. Or: the pthread_create* wrapper defined below can be
+ * called recursively. Any code in this wrapper should take this in account.
+ * As an example, it is not safe to invoke the DRD_STOP_RECORDING
+ * / DRD_START_RECORDING client requests from the pthread_create wrapper.
+ * See also the implementation of pthread_create@GLIBC_2.0 in
+ * glibc-2.9/nptl/pthread_create.c.
+ */
+
+static __always_inline
+int pthread_create_intercept(pthread_t* thread, const pthread_attr_t* attr,
+                             void* (*start)(void*), void* arg)
+{
+   int    res;
+   int    ret;
+   OrigFn fn;
+#if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK)
+   DrdPosixThreadArgs thread_args;
+#endif
+   DrdPosixThreadArgs* thread_args_p;
+
+   VALGRIND_GET_ORIG_FN(fn);
+
+#if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK)
+   thread_args_p = &thread_args;
+#else
+   thread_args_p = malloc(sizeof(*thread_args_p));
+#endif
+   assert(thread_args_p);
+
+   thread_args_p->start           = start;
+   thread_args_p->arg             = arg;
+#if defined(WAIT_UNTIL_CREATED_THREAD_STARTED)
+   DRD_IGNORE_VAR(thread_args_p->wrapper_started);
+   thread_args_p->wrapper_started = 0;
+#endif
+   /*
+    * Find out whether the thread will be started as a joinable thread
+    * or as a detached thread. If no thread attributes have been specified,
+    * this means that the new thread will be started as a joinable thread.
+    */
+   thread_args_p->detachstate = PTHREAD_CREATE_JOINABLE;
+   if (attr)
+   {
+      if (pthread_attr_getdetachstate(attr, &thread_args_p->detachstate) != 0)
+      {
+         assert(0);
+      }
+   }
+   assert(thread_args_p->detachstate == PTHREAD_CREATE_JOINABLE
+          || thread_args_p->detachstate == PTHREAD_CREATE_DETACHED);
+
+
+   DRD_(entering_pthread_create)();
+   CALL_FN_W_WWWW(ret, fn, thread, attr, DRD_(thread_wrapper), thread_args_p);
+   DRD_(left_pthread_create)();
+
+#if defined(WAIT_UNTIL_CREATED_THREAD_STARTED)
+   if (ret == 0)
+   {
+      /*
+       * Wait until the thread wrapper started.
+       * @todo Find out why some regression tests fail if thread arguments are
+       *   passed via dynamically allocated memory and if the loop below is
+       *   removed.
+       */
+      while (! thread_args_p->wrapper_started)
+      {
+         sched_yield();
+      }
+   }
+
+#if defined(ALLOCATE_THREAD_ARGS_DYNAMICALLY)
+   free(thread_args_p);
+#endif
+
+#endif
+
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_START_NEW_SEGMENT,
+                              pthread_self(), 0, 0, 0, 0);
+
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZucreate, pthread_create_intercept,
+          (pthread_t *thread, const pthread_attr_t *attr,
+           void *(*start) (void *), void *arg),
+          (thread, attr, start, arg));
+
+static __always_inline
+int pthread_join_intercept(pthread_t pt_joinee, void **thread_return)
+{
+   int      ret;
+   int      res;
+   OrigFn   fn;
+
+   VALGRIND_GET_ORIG_FN(fn);
+   CALL_FN_W_WW(ret, fn, pt_joinee, thread_return);
+   if (ret == 0)
+   {
+      VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_JOIN,
+                                 pt_joinee, 0, 0, 0, 0);
+   }
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZujoin, pthread_join_intercept,
+          (pthread_t pt_joinee, void **thread_return),
+          (pt_joinee, thread_return));
+
+static __always_inline
+int pthread_detach_intercept(pthread_t pt_thread)
+{
+   int ret;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   {
+      CALL_FN_W_W(ret, fn, pt_thread);
+      if (ret == 0)
+      {
+         DRD_(set_joinable)(pt_thread, 0);
+      }
+   }
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZudetach, pthread_detach_intercept,
+          (pthread_t thread), (thread));
+
+// NOTE: be careful to intercept only pthread_cancel() and not
+// pthread_cancel_init() on Linux.
+
+static __always_inline
+int pthread_cancel_intercept(pthread_t pt_thread)
+{
+   int res;
+   int ret;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_THREAD_CANCEL,
+                              pt_thread, 0, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, pt_thread);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_CANCEL,
+                              pt_thread, ret==0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZucancel, pthread_cancel_intercept,
+          (pthread_t thread), (thread))
+
+static __always_inline
+int pthread_once_intercept(pthread_once_t *once_control,
+                           void (*init_routine)(void))
+{
+   int ret;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   /*
+    * Ignore any data races triggered by the implementation of pthread_once().
+    * Necessary for Darwin. This is not necessary for Linux but doesn't have
+    * any known adverse effects.
+    */
+   DRD_IGNORE_VAR(*once_control);
+   CALL_FN_W_WW(ret, fn, once_control, init_routine);
+   DRD_STOP_IGNORING_VAR(*once_control);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZuonce, pthread_once_intercept,
+          (pthread_once_t *once_control, void (*init_routine)(void)),
+          (once_control, init_routine));
+
+static __always_inline
+int pthread_mutex_init_intercept(pthread_mutex_t *mutex,
+                                 const pthread_mutexattr_t* attr)
+{
+   int ret;
+   int res;
+   OrigFn fn;
+   int mt;
+   VALGRIND_GET_ORIG_FN(fn);
+   mt = PTHREAD_MUTEX_DEFAULT;
+   if (attr)
+      pthread_mutexattr_gettype(attr, &mt);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_INIT,
+                              mutex, DRD_(pthread_to_drd_mutex_type)(mt),
+                              0, 0, 0);
+   CALL_FN_W_WW(ret, fn, mutex, attr);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_INIT,
+                              mutex, 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZumutexZuinit, pthread_mutex_init_intercept,
+          (pthread_mutex_t *mutex, const pthread_mutexattr_t* attr),
+          (mutex, attr));
+
+static __always_inline
+int pthread_mutex_destroy_intercept(pthread_mutex_t* mutex)
+{
+   int ret;
+   int res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY,
+                              mutex, 0, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, mutex);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY,
+                              mutex, DRD_(mutex_type)(mutex), 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZumutexZudestroy, pthread_mutex_destroy_intercept,
+          (pthread_mutex_t *mutex), (mutex));
+
+static __always_inline
+int pthread_mutex_lock_intercept(pthread_mutex_t* mutex)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK,
+                              mutex, DRD_(mutex_type)(mutex), 0, 0, 0);
+   CALL_FN_W_W(ret, fn, mutex);
+   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__POST_MUTEX_LOCK,
+                              mutex, ret == 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZumutexZulock, pthread_mutex_lock_intercept,
+          (pthread_mutex_t *mutex), (mutex));
+
+static __always_inline
+int pthread_mutex_trylock_intercept(pthread_mutex_t* mutex)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK,
+                              mutex, DRD_(mutex_type)(mutex), 1, 0, 0);
+   CALL_FN_W_W(ret, fn, mutex);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK,
+                              mutex, ret == 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZumutexZutrylock, pthread_mutex_trylock_intercept,
+          (pthread_mutex_t *mutex), (mutex));
+
+static __always_inline
+int pthread_mutex_timedlock_intercept(pthread_mutex_t *mutex,
+                                      const struct timespec *abs_timeout)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK,
+                              mutex, DRD_(mutex_type)(mutex), 0, 0, 0);
+   CALL_FN_W_WW(ret, fn, mutex, abs_timeout);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK,
+                              mutex, ret == 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZumutexZutimedlock, pthread_mutex_timedlock_intercept,
+          (pthread_mutex_t *mutex, const struct timespec *abs_timeout),
+          (mutex, abs_timeout));
+
+static __always_inline
+int pthread_mutex_unlock_intercept(pthread_mutex_t *mutex)
+{
+   int ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1,
+                              VG_USERREQ__PRE_MUTEX_UNLOCK,
+                              mutex, DRD_(mutex_type)(mutex), 0, 0, 0);
+   CALL_FN_W_W(ret, fn, mutex);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1,
+                              VG_USERREQ__POST_MUTEX_UNLOCK,
+                              mutex, 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZumutexZuunlock, pthread_mutex_unlock_intercept,
+          (pthread_mutex_t *mutex), (mutex));
+
+static __always_inline
+int pthread_cond_init_intercept(pthread_cond_t* cond,
+                                const pthread_condattr_t* attr)
+{
+   int ret;
+   int res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_INIT,
+                              cond, 0, 0, 0, 0);
+   CALL_FN_W_WW(ret, fn, cond, attr);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_INIT,
+                              cond, 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZucondZuinit, pthread_cond_init_intercept,
+          (pthread_cond_t* cond, const pthread_condattr_t* attr),
+          (cond, attr));
+
+static __always_inline
+int pthread_cond_destroy_intercept(pthread_cond_t* cond)
+{
+   int ret;
+   int res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_DESTROY,
+                              cond, 0, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, cond);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_DESTROY,
+                              cond, 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZucondZudestroy, pthread_cond_destroy_intercept,
+          (pthread_cond_t* cond), (cond));
+
+static __always_inline
+int pthread_cond_wait_intercept(pthread_cond_t *cond, pthread_mutex_t *mutex)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_WAIT,
+                              cond, mutex, DRD_(mutex_type)(mutex), 0, 0);
+   CALL_FN_W_WW(ret, fn, cond, mutex);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_WAIT,
+                              cond, mutex, 1, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZucondZuwait, pthread_cond_wait_intercept,
+          (pthread_cond_t *cond, pthread_mutex_t *mutex),
+          (cond, mutex));
+
+static __always_inline
+int pthread_cond_timedwait_intercept(pthread_cond_t *cond,
+                                     pthread_mutex_t *mutex,
+                                     const struct timespec* abstime)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_WAIT,
+                              cond, mutex, DRD_(mutex_type)(mutex), 0, 0);
+   CALL_FN_W_WWW(ret, fn, cond, mutex, abstime);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_WAIT,
+                              cond, mutex, 1, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZucondZutimedwait, pthread_cond_timedwait_intercept,
+          (pthread_cond_t *cond, pthread_mutex_t *mutex,
+           const struct timespec* abstime),
+          (cond, mutex, abstime));
+
+// NOTE: be careful to intercept only pthread_cond_signal() and not Darwin's
+// pthread_cond_signal_thread_np(). The former accepts one argument; the latter
+// two. Intercepting all pthread_cond_signal* functions will cause only one
+// argument to be passed to pthread_cond_signal_np() and hence will cause this
+// last function to crash.
+
+static __always_inline
+int pthread_cond_signal_intercept(pthread_cond_t* cond)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_SIGNAL,
+                              cond, 0, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, cond);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_SIGNAL,
+                              cond, 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZucondZusignal, pthread_cond_signal_intercept,
+          (pthread_cond_t* cond), (cond));
+
+static __always_inline
+int pthread_cond_broadcast_intercept(pthread_cond_t* cond)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_BROADCAST,
+                              cond, 0, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, cond);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_BROADCAST,
+                              cond, 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZucondZubroadcast, pthread_cond_broadcast_intercept,
+          (pthread_cond_t* cond), (cond));
+
+#if defined(HAVE_PTHREAD_SPIN_LOCK)
+static __always_inline
+int pthread_spin_init_intercept(pthread_spinlock_t *spinlock, int pshared)
+{
+   int ret;
+   int res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK,
+                              spinlock, 0, 0, 0, 0);
+   CALL_FN_W_WW(ret, fn, spinlock, pshared);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK,
+                              spinlock, 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZuspinZuinit, pthread_spin_init_intercept,
+          (pthread_spinlock_t *spinlock, int pshared), (spinlock, pshared));
+
+static __always_inline
+int pthread_spin_destroy_intercept(pthread_spinlock_t *spinlock)
+{
+   int ret;
+   int res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY,
+                              spinlock, 0, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, spinlock);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY,
+                              spinlock, mutex_type_spinlock, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZuspinZudestroy, pthread_spin_destroy_intercept,
+          (pthread_spinlock_t *spinlock), (spinlock));
+
+static __always_inline
+int pthread_spin_lock_intercept(pthread_spinlock_t *spinlock)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK,
+                              spinlock, mutex_type_spinlock, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, spinlock);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK,
+                              spinlock, ret == 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZuspinZulock, pthread_spin_lock_intercept,
+          (pthread_spinlock_t *spinlock), (spinlock));
+
+static __always_inline
+int pthread_spin_trylock_intercept(pthread_spinlock_t *spinlock)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK,
+                              spinlock, mutex_type_spinlock, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, spinlock);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK,
+                              spinlock, ret == 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZuspinZutrylock, pthread_spin_trylock_intercept,
+          (pthread_spinlock_t *spinlock), (spinlock));
+
+static __always_inline
+int pthread_spin_unlock_intercept(pthread_spinlock_t *spinlock)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK,
+                              spinlock, mutex_type_spinlock, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, spinlock);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK,
+                              spinlock, 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZuspinZuunlock, pthread_spin_unlock_intercept,
+          (pthread_spinlock_t *spinlock), (spinlock));
+#endif   // HAVE_PTHREAD_SPIN_LOCK
+
+
+#if defined(HAVE_PTHREAD_BARRIER_INIT)
+static __always_inline
+int pthread_barrier_init_intercept(pthread_barrier_t* barrier,
+                                   const pthread_barrierattr_t* attr,
+                                   unsigned count)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_INIT,
+                              barrier, pthread_barrier, count, 0, 0);
+   CALL_FN_W_WWW(ret, fn, barrier, attr, count);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_INIT,
+                              barrier, pthread_barrier, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZubarrierZuinit, pthread_barrier_init_intercept,
+          (pthread_barrier_t* barrier, const pthread_barrierattr_t* attr,
+           unsigned count), (barrier, attr, count));
+
+static __always_inline
+int pthread_barrier_destroy_intercept(pthread_barrier_t* barrier)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_DESTROY,
+                              barrier, pthread_barrier, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, barrier);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_DESTROY,
+                              barrier, pthread_barrier, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZubarrierZudestroy, pthread_barrier_destroy_intercept,
+          (pthread_barrier_t* barrier), (barrier));
+
+static __always_inline
+int pthread_barrier_wait_intercept(pthread_barrier_t* barrier)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_WAIT,
+                              barrier, pthread_barrier, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, barrier);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_WAIT,
+                              barrier, pthread_barrier,
+                              ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD,
+                              ret == PTHREAD_BARRIER_SERIAL_THREAD, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, pthreadZubarrierZuwait, pthread_barrier_wait_intercept,
+          (pthread_barrier_t* barrier), (barrier));
+#endif   // HAVE_PTHREAD_BARRIER_INIT
+
+
+static __always_inline
+int sem_init_intercept(sem_t *sem, int pshared, unsigned int value)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_INIT,
+                              sem, pshared, value, 0, 0);
+   CALL_FN_W_WWW(ret, fn, sem, pshared, value);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_INIT,
+                              sem, 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, semZuinit, sem_init_intercept,
+          (sem_t *sem, int pshared, unsigned int value), (sem, pshared, value));
+
+static __always_inline
+int sem_destroy_intercept(sem_t *sem)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_DESTROY,
+                              sem, 0, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, sem);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_DESTROY,
+                              sem, 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, semZudestroy, sem_destroy_intercept, (sem_t *sem), (sem));
+
+static __always_inline
+sem_t* sem_open_intercept(const char *name, int oflag, mode_t mode,
+                          unsigned int value)
+{
+   sem_t *ret;
+   int    res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_OPEN,
+                              name, oflag, mode, value, 0);
+   CALL_FN_W_WWWW(ret, fn, name, oflag, mode, value);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_OPEN,
+                              ret != SEM_FAILED ? ret : 0,
+                              name, oflag, mode, value);
+   return ret;
+}
+
+PTH_FUNCS(sem_t *, semZuopen, sem_open_intercept,
+          (const char *name, int oflag, mode_t mode, unsigned int value),
+          (name, oflag, mode, value));
+
+static __always_inline int sem_close_intercept(sem_t *sem)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_CLOSE,
+                              sem, 0, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, sem);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_CLOSE,
+                              sem, 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, semZuclose, sem_close_intercept, (sem_t *sem), (sem));
+
+static __always_inline int sem_wait_intercept(sem_t *sem)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
+                              sem, 0, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, sem);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
+                              sem, ret == 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, semZuwait, sem_wait_intercept, (sem_t *sem), (sem));
+
+static __always_inline int sem_trywait_intercept(sem_t *sem)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
+                              sem, 0, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, sem);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
+                              sem, ret == 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, semZutrywait, sem_trywait_intercept, (sem_t *sem), (sem));
+
+static __always_inline
+int sem_timedwait_intercept(sem_t *sem, const struct timespec *abs_timeout)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
+                              sem, 0, 0, 0, 0);
+   CALL_FN_W_WW(ret, fn, sem, abs_timeout);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
+                              sem, ret == 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, semZutimedwait, sem_timedwait_intercept,
+          (sem_t *sem, const struct timespec *abs_timeout),
+          (sem, abs_timeout));
+
+static __always_inline int sem_post_intercept(sem_t *sem)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST,
+                              sem, 0, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, sem);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST,
+                              sem, ret == 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int, semZupost, sem_post_intercept, (sem_t *sem), (sem));
+
+static __always_inline
+int pthread_rwlock_init_intercept(pthread_rwlock_t* rwlock,
+                                  const pthread_rwlockattr_t* attr)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_INIT,
+                              rwlock, 0, 0, 0, 0);
+   CALL_FN_W_WW(ret, fn, rwlock, attr);
+   return ret;
+}
+
+PTH_FUNCS(int,
+          pthreadZurwlockZuinit, pthread_rwlock_init_intercept,
+          (pthread_rwlock_t* rwlock, const pthread_rwlockattr_t* attr),
+          (rwlock, attr));
+
+static __always_inline
+int pthread_rwlock_destroy_intercept(pthread_rwlock_t* rwlock)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   CALL_FN_W_W(ret, fn, rwlock);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_DESTROY,
+                              rwlock, 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int,
+          pthreadZurwlockZudestroy, pthread_rwlock_destroy_intercept,
+          (pthread_rwlock_t* rwlock), (rwlock));
+
+static __always_inline
+int pthread_rwlock_rdlock_intercept(pthread_rwlock_t* rwlock)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK,
+                              rwlock, 0, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, rwlock);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK,
+                              rwlock, ret == 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int,
+          pthreadZurwlockZurdlock, pthread_rwlock_rdlock_intercept,
+          (pthread_rwlock_t* rwlock), (rwlock));
+
+static __always_inline
+int pthread_rwlock_wrlock_intercept(pthread_rwlock_t* rwlock)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK,
+                              rwlock, 0, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, rwlock);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK,
+                              rwlock, ret == 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int,
+          pthreadZurwlockZuwrlock, pthread_rwlock_wrlock_intercept,
+          (pthread_rwlock_t* rwlock), (rwlock));
+
+static __always_inline
+int pthread_rwlock_timedrdlock_intercept(pthread_rwlock_t* rwlock)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK,
+                              rwlock, 0, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, rwlock);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK,
+                              rwlock, ret == 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int,
+          pthreadZurwlockZutimedrdlock, pthread_rwlock_timedrdlock_intercept,
+          (pthread_rwlock_t* rwlock), (rwlock));
+
+static __always_inline
+int pthread_rwlock_timedwrlock_intercept(pthread_rwlock_t* rwlock)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK,
+                              rwlock, 0, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, rwlock);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK,
+                              rwlock, ret == 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int,
+          pthreadZurwlockZutimedwrlock, pthread_rwlock_timedwrlock_intercept,
+          (pthread_rwlock_t* rwlock), (rwlock));
+
+static __always_inline
+int pthread_rwlock_tryrdlock_intercept(pthread_rwlock_t* rwlock)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK,
+                              rwlock, 0, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, rwlock);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK,
+                              rwlock, ret == 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int,
+          pthreadZurwlockZutryrdlock, pthread_rwlock_tryrdlock_intercept,
+          (pthread_rwlock_t* rwlock), (rwlock));
+
+static __always_inline
+int pthread_rwlock_trywrlock_intercept(pthread_rwlock_t* rwlock)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK,
+                              rwlock, 0, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, rwlock);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK,
+                              rwlock, ret == 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int,
+          pthreadZurwlockZutrywrlock, pthread_rwlock_trywrlock_intercept,
+          (pthread_rwlock_t* rwlock), (rwlock));
+
+static __always_inline
+int pthread_rwlock_unlock_intercept(pthread_rwlock_t* rwlock)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_UNLOCK,
+                              rwlock, 0, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, rwlock);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_UNLOCK,
+                              rwlock, ret == 0, 0, 0, 0);
+   return ret;
+}
+
+PTH_FUNCS(int,
+          pthreadZurwlockZuunlock, pthread_rwlock_unlock_intercept,
+          (pthread_rwlock_t* rwlock), (rwlock));
diff --git a/drd/drd_qtcore_intercepts.c b/drd/drd_qtcore_intercepts.c
new file mode 100644
index 0000000..5a6a5ed
--- /dev/null
+++ b/drd/drd_qtcore_intercepts.c
@@ -0,0 +1,212 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+
+/*--------------------------------------------------------------------*/
+/*--- Client-space code for drd.           drd_qtcore_intercepts.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+/* ---------------------------------------------------------------------
+   ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU.
+
+   These functions are not called directly - they're the targets of code
+   redirection or load notifications (see pub_core_redir.h for info).
+   They're named weirdly so that the intercept code can find them when the
+   shared object is initially loaded.
+
+   Note that this filename has the "drd_" prefix because it can appear
+   in stack traces, and the "drd_" makes it a little clearer that it
+   originates from Valgrind.
+   ------------------------------------------------------------------ */
+
+#include <assert.h>
+#include "drd_clientreq.h"
+#include "pub_tool_redir.h"
+
+
+// Defines.
+
+#define QT4CORE_FUNC(ret_ty, f, args...)                        \
+   ret_ty VG_WRAP_FUNCTION_ZU(libQtCoreZdsoZd4,f)(args);        \
+   ret_ty VG_WRAP_FUNCTION_ZU(libQtCoreZdsoZd4,f)(args)
+
+
+
+//////////////////////////////////////////////////////////////////
+// QMutex intercepts.
+//////////////////////////////////////////////////////////////////
+
+
+typedef enum { qt_nonrecursive = 0, qt_recursive = 1 } qt_mutex_mode;
+
+
+/** Convert a Qt4 mutex type to a DRD mutex type. */
+static MutexT qt_to_drd_mutex_type(qt_mutex_mode mode)
+{
+   switch (mode)
+   {
+   case qt_nonrecursive:
+      return mutex_type_default_mutex;
+   case qt_recursive:
+      return mutex_type_recursive_mutex;
+   }
+   return mutex_type_invalid_mutex;
+}
+
+/** Find out the type of a Qt4 mutex (recursive or not).
+ *  Since it's not possible to do this in a portable way, return
+ *  mutex_type_unknown and let drd_mutex.c look up the real mutex type.
+ */
+static MutexT mutex_type(void* qt4_mutex)
+{
+   return mutex_type_unknown;
+}
+
+
+// QMutex::QMutex(RecursionMode) -- _ZN6QMutexC1ENS_13RecursionModeE,
+QT4CORE_FUNC(void, _ZN6QMutexC1ENS_13RecursionModeE,
+             void* mutex,
+             qt_mutex_mode mode)
+{
+   int    ret;
+   int    res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_INIT,
+                              mutex, qt_to_drd_mutex_type(mode), 0, 0, 0);
+   CALL_FN_W_WW(ret, fn, mutex, mode);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_INIT,
+                              mutex, 0, 0, 0, 0);
+}
+
+// QMutex::QMutex(RecursionMode) -- _ZN6QMutexC2ENS_13RecursionModeE
+QT4CORE_FUNC(void, _ZN6QMutexC2ENS_13RecursionModeE,
+             void* mutex,
+             qt_mutex_mode mode)
+{
+   int    ret;
+   int    res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_INIT,
+                              mutex, qt_to_drd_mutex_type(mode), 0, 0, 0);
+   CALL_FN_W_WW(ret, fn, mutex, mode);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_INIT,
+                              mutex, 0, 0, 0, 0);
+}
+
+// QMutex::~QMutex() -- _ZN6QMutexD1Ev
+QT4CORE_FUNC(void, _ZN6QMutexD1Ev,
+             void* mutex)
+{
+   int    ret;
+   int    res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY,
+                              mutex, 0, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, mutex);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY,
+                              mutex, mutex_type(mutex), 0, 0, 0);
+}
+
+// QMutex::~QMutex() -- _ZN6QMutexD2Ev
+QT4CORE_FUNC(void, _ZN6QMutexD2Ev,
+             void** mutex)
+{
+   int    ret;
+   int    res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY,
+                              mutex, 0, 0, 0, 0);
+   CALL_FN_W_W(ret, fn, mutex);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY,
+                              mutex, mutex_type(mutex), 0, 0, 0);
+}
+
+// QMutex::lock() -- _ZN6QMutex4lockEv
+QT4CORE_FUNC(void, _ZN6QMutex4lockEv,
+             void* mutex)
+{
+   int   ret;
+   int   res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK,
+                              mutex, mutex_type(mutex), 0, 0, 0);
+   CALL_FN_W_W(ret, fn, mutex);
+   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__POST_MUTEX_LOCK,
+                              mutex, 1, 0, 0, 0);
+}
+
+// QMutex::tryLock() -- _ZN6QMutex7tryLockEv
+QT4CORE_FUNC(int, _ZN6QMutex7tryLockEv,
+             void* mutex)
+{
+   int    ret;
+   int    res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK,
+                              mutex, mutex_type(mutex), 1, 0, 0);
+   CALL_FN_W_W(ret, fn, mutex);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK,
+                              mutex, ret, 0, 0, 0);
+   return ret;
+}
+
+// QMutex::tryLock(int) -- _ZN6QMutex7tryLockEi
+QT4CORE_FUNC(int, _ZN6QMutex7tryLockEi,
+             void* mutex,
+             int timeout_ms)
+{
+   int    ret;
+   int    res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK,
+                              mutex, mutex_type(mutex), 1, 0, 0);
+   CALL_FN_W_WW(ret, fn, mutex, timeout_ms);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK,
+                              mutex, ret, 0, 0, 0);
+   return ret;
+}
+
+// QMutex::unlock() -- _ZN6QMutex6unlockEv
+QT4CORE_FUNC(void, _ZN6QMutex6unlockEv,
+             void* mutex)
+{
+   int    ret;
+   int    res;
+   OrigFn fn;
+   VALGRIND_GET_ORIG_FN(fn);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1,
+                              VG_USERREQ__PRE_MUTEX_UNLOCK,
+                              mutex, mutex_type(mutex), 0, 0, 0);
+   CALL_FN_W_W(ret, fn, mutex);
+   VALGRIND_DO_CLIENT_REQUEST(res, -1,
+                              VG_USERREQ__POST_MUTEX_UNLOCK,
+                              mutex, 0, 0, 0, 0);
+}
diff --git a/drd/drd_rwlock.c b/drd/drd_rwlock.c
new file mode 100644
index 0000000..ad2968e
--- /dev/null
+++ b/drd/drd_rwlock.c
@@ -0,0 +1,667 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#include "drd_clientobj.h"
+#include "drd_error.h"
+#include "drd_rwlock.h"
+#include "pub_tool_vki.h"
+#include "pub_tool_errormgr.h"    // VG_(maybe_record_error)()
+#include "pub_tool_libcassert.h"  // tl_assert()
+#include "pub_tool_libcprint.h"   // VG_(message)()
+#include "pub_tool_libcproc.h"    // VG_(read_millisecond_timer)()
+#include "pub_tool_machine.h"     // VG_(get_IP)()
+#include "pub_tool_mallocfree.h"  // VG_(malloc)(), VG_(free)()
+#include "pub_tool_threadstate.h" // VG_(get_running_tid)()
+
+
+/* Local type definitions. */
+
+struct rwlock_thread_info
+{
+   UWord    tid;                 // DrdThreadId.
+   UInt     reader_nesting_count;
+   UInt     writer_nesting_count;
+   // Segment of last unlock call by this thread that unlocked a writer lock.
+   Segment* latest_wrlocked_segment;
+   // Segment of last unlock call by this thread that unlocked a reader lock.
+   Segment* latest_rdlocked_segment;
+};
+
+
+/* Local functions. */
+
+static void rwlock_cleanup(struct rwlock_info* p);
+static void rwlock_delete_thread(struct rwlock_info* const p,
+                                 const DrdThreadId tid);
+
+
+/* Local variables. */
+
+static Bool DRD_(s_trace_rwlock);
+static UInt DRD_(s_exclusive_threshold_ms);
+static UInt DRD_(s_shared_threshold_ms);
+static ULong DRD_(s_rwlock_segment_creation_count);
+
+
+/* Function definitions. */
+
+void DRD_(rwlock_set_trace)(const Bool trace_rwlock)
+{
+   tl_assert(trace_rwlock == False || trace_rwlock == True);
+   DRD_(s_trace_rwlock) = trace_rwlock;
+}
+
+void DRD_(rwlock_set_exclusive_threshold)(const UInt exclusive_threshold_ms)
+{
+   DRD_(s_exclusive_threshold_ms) = exclusive_threshold_ms;
+}
+
+void DRD_(rwlock_set_shared_threshold)(const UInt shared_threshold_ms)
+{
+   DRD_(s_shared_threshold_ms) = shared_threshold_ms;
+}
+
+static Bool DRD_(rwlock_is_rdlocked)(struct rwlock_info* p)
+{
+   struct rwlock_thread_info* q;
+
+   VG_(OSetGen_ResetIter)(p->thread_info);
+   for ( ; (q = VG_(OSetGen_Next)(p->thread_info)) != 0; )
+   {
+      return q->reader_nesting_count > 0;
+   }
+   return False;
+}
+
+static Bool DRD_(rwlock_is_wrlocked)(struct rwlock_info* p)
+{
+   struct rwlock_thread_info* q;
+
+   VG_(OSetGen_ResetIter)(p->thread_info);
+   for ( ; (q = VG_(OSetGen_Next)(p->thread_info)) != 0; )
+   {
+      return q->writer_nesting_count > 0;
+   }
+   return False;
+}
+
+static Bool DRD_(rwlock_is_locked)(struct rwlock_info* p)
+{
+   return DRD_(rwlock_is_rdlocked)(p) || DRD_(rwlock_is_wrlocked)(p);
+}
+
+static Bool DRD_(rwlock_is_rdlocked_by)(struct rwlock_info* p,
+                                        const DrdThreadId tid)
+{
+   const UWord uword_tid = tid;
+   struct rwlock_thread_info* q;
+
+   q = VG_(OSetGen_Lookup)(p->thread_info, &uword_tid);
+   return q && q->reader_nesting_count > 0;
+}
+
+static Bool DRD_(rwlock_is_wrlocked_by)(struct rwlock_info* p,
+                                        const DrdThreadId tid)
+{
+   const UWord uword_tid = tid;
+   struct rwlock_thread_info* q;
+
+   q = VG_(OSetGen_Lookup)(p->thread_info, &uword_tid);
+   return q && q->writer_nesting_count > 0;
+}
+
+static Bool DRD_(rwlock_is_locked_by)(struct rwlock_info* p,
+                                      const DrdThreadId tid)
+{
+   return (DRD_(rwlock_is_rdlocked_by)(p, tid)
+           || DRD_(rwlock_is_wrlocked_by)(p, tid));
+}
+
+/** Either look up or insert a node corresponding to DRD thread id 'tid'. */
+static
+struct rwlock_thread_info*
+DRD_(lookup_or_insert_node)(OSet* oset, const UWord tid)
+{
+   struct rwlock_thread_info* q;
+
+   q = VG_(OSetGen_Lookup)(oset, &tid);
+   if (q == 0)
+   {
+      q = VG_(OSetGen_AllocNode)(oset, sizeof(*q));
+      q->tid                       = tid;
+      q->reader_nesting_count      = 0;
+      q->writer_nesting_count      = 0;
+      q->latest_wrlocked_segment   = 0;
+      q->latest_rdlocked_segment   = 0;
+      VG_(OSetGen_Insert)(oset, q);
+   }
+   tl_assert(q);
+   return q;
+}
+
+/**
+ * Combine the vector clock corresponding to the last unlock operation of
+ * reader-writer lock p into the vector clock of thread 'tid'.
+ */
+static void DRD_(rwlock_combine_other_vc)(struct rwlock_info* const p,
+                                          const DrdThreadId tid,
+                                          const Bool readers_too)
+{
+   struct rwlock_thread_info* q;
+   VectorClock old_vc;
+
+   DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[tid].last->vc);
+   VG_(OSetGen_ResetIter)(p->thread_info);
+   for ( ; (q = VG_(OSetGen_Next)(p->thread_info)) != 0; )
+   {
+      if (q->tid != tid)
+      {
+         if (q->latest_wrlocked_segment)
+         {
+            DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc,
+                             &q->latest_wrlocked_segment->vc);
+         }
+         if (readers_too && q->latest_rdlocked_segment)
+         {
+            DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc,
+                             &q->latest_rdlocked_segment->vc);
+         }
+      }
+   }
+   DRD_(thread_update_conflict_set)(tid, &old_vc);
+   DRD_(vc_cleanup)(&old_vc);
+}
+
+/**
+ * Compare the type of the rwlock specified at initialization time with
+ * the type passed as an argument, and complain if these two types do not
+ * match.
+ */
+static Bool drd_rwlock_check_type(struct rwlock_info* const p,
+                                  const RwLockT rwlock_type)
+{
+   tl_assert(p);
+   /* The code below has to be updated if additional rwlock types are added. */
+   tl_assert(rwlock_type == pthread_rwlock || rwlock_type == user_rwlock);
+   tl_assert(p->rwlock_type == pthread_rwlock || p->rwlock_type == user_rwlock);
+
+   if (p->rwlock_type == rwlock_type)
+      return True;
+
+   {
+      RwlockErrInfo REI = { DRD_(thread_get_running_tid)(), p->a1 };
+      VG_(maybe_record_error)
+         (VG_(get_running_tid)(),
+          RwlockErr,
+          VG_(get_IP)(VG_(get_running_tid)()),
+          rwlock_type == pthread_rwlock
+          ? "Attempt to use a user-defined rwlock as a POSIX rwlock"
+          : "Attempt to use a POSIX rwlock as a user-defined rwlock",
+          &REI);
+   }
+   return False;
+}
+
+/** Initialize the rwlock_info data structure *p. */
+static
+void DRD_(rwlock_initialize)(struct rwlock_info* const p, const Addr rwlock,
+                             const RwLockT rwlock_type)
+{
+   tl_assert(rwlock != 0);
+   tl_assert(p->a1 == rwlock);
+   tl_assert(p->type == ClientRwlock);
+
+   p->cleanup         = (void(*)(DrdClientobj*))rwlock_cleanup;
+   p->delete_thread
+      = (void(*)(DrdClientobj*, DrdThreadId))rwlock_delete_thread;
+   p->rwlock_type     = rwlock_type;
+   p->thread_info     = VG_(OSetGen_Create)(
+      0, 0, VG_(malloc), "drd.rwlock.ri.1", VG_(free));
+   p->acquiry_time_ms = 0;
+   p->acquired_at     = 0;
+}
+
+/** Deallocate the memory that was allocated by rwlock_initialize(). */
+static void rwlock_cleanup(struct rwlock_info* p)
+{
+   struct rwlock_thread_info* q;
+
+   tl_assert(p);
+
+   if (DRD_(s_trace_rwlock))
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] rwlock_destroy     0x%lx\n",
+                   DRD_(thread_get_running_tid)(),
+                   p->a1);
+   }
+
+   if (DRD_(rwlock_is_locked)(p))
+   {
+      RwlockErrInfo REI = { DRD_(thread_get_running_tid)(), p->a1 };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              RwlockErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "Destroying locked rwlock",
+                              &REI);
+   }
+
+   VG_(OSetGen_ResetIter)(p->thread_info);
+   for ( ; (q = VG_(OSetGen_Next)(p->thread_info)) != 0; )
+   {
+      DRD_(sg_put)(q->latest_wrlocked_segment);
+      DRD_(sg_put)(q->latest_rdlocked_segment);
+   }
+
+   VG_(OSetGen_Destroy)(p->thread_info);
+}
+
+static
+struct rwlock_info*
+DRD_(rwlock_get_or_allocate)(const Addr rwlock, const RwLockT rwlock_type)
+{
+   struct rwlock_info* p;
+
+   tl_assert(offsetof(DrdClientobj, rwlock) == 0);
+   p = &(DRD_(clientobj_get)(rwlock, ClientRwlock)->rwlock);
+   if (p)
+   {
+      drd_rwlock_check_type(p, rwlock_type);
+      return p;
+   }
+
+   if (DRD_(clientobj_present)(rwlock, rwlock + 1))
+   {
+      GenericErrInfo GEI = {
+	 .tid  = DRD_(thread_get_running_tid)(),
+	 .addr = rwlock,
+      };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              GenericErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "Not a reader-writer lock",
+                              &GEI);
+      return 0;
+   }
+
+   p = &(DRD_(clientobj_add)(rwlock, ClientRwlock)->rwlock);
+   DRD_(rwlock_initialize)(p, rwlock, rwlock_type);
+   return p;
+}
+
+static struct rwlock_info* DRD_(rwlock_get)(const Addr rwlock)
+{
+   tl_assert(offsetof(DrdClientobj, rwlock) == 0);
+   return &(DRD_(clientobj_get)(rwlock, ClientRwlock)->rwlock);
+}
+
+/** Called before pthread_rwlock_init(). */
+struct rwlock_info* DRD_(rwlock_pre_init)(const Addr rwlock,
+                                          const RwLockT rwlock_type)
+{
+   struct rwlock_info* p;
+
+   if (DRD_(s_trace_rwlock))
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] rwlock_init        0x%lx\n",
+                   DRD_(thread_get_running_tid)(),
+                   rwlock);
+   }
+
+   p = DRD_(rwlock_get)(rwlock);
+
+   if (p)
+	drd_rwlock_check_type(p, rwlock_type);
+
+   if (p)
+   {
+      const ThreadId vg_tid = VG_(get_running_tid)();
+      RwlockErrInfo REI = { DRD_(thread_get_running_tid)(), p->a1 };
+      VG_(maybe_record_error)(vg_tid,
+                              RwlockErr,
+                              VG_(get_IP)(vg_tid),
+                              "Reader-writer lock reinitialization",
+                              &REI);
+      return p;
+   }
+
+   p = DRD_(rwlock_get_or_allocate)(rwlock, rwlock_type);
+
+   return p;
+}
+
+/** Called after pthread_rwlock_destroy(). */
+void DRD_(rwlock_post_destroy)(const Addr rwlock, const RwLockT rwlock_type)
+{
+   struct rwlock_info* p;
+
+   p = DRD_(rwlock_get)(rwlock);
+   if (p == 0)
+   {
+      GenericErrInfo GEI = {
+	 .tid = DRD_(thread_get_running_tid)(),
+	 .addr = rwlock,
+      };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              GenericErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "Not a reader-writer lock",
+                              &GEI);
+      return;
+   }
+
+   drd_rwlock_check_type(p, rwlock_type);
+
+   DRD_(clientobj_remove)(rwlock, ClientRwlock);
+}
+
+/**
+ * Called before pthread_rwlock_rdlock() is invoked. If a data structure for
+ * the client-side object was not yet created, do this now. Also check whether
+ * an attempt is made to lock recursively a synchronization object that must
+ * not be locked recursively.
+ */
+void DRD_(rwlock_pre_rdlock)(const Addr rwlock, const RwLockT rwlock_type)
+{
+   struct rwlock_info* p;
+
+   if (DRD_(s_trace_rwlock))
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] pre_rwlock_rdlock  0x%lx\n",
+                   DRD_(thread_get_running_tid)(),
+                   rwlock);
+   }
+
+   p = DRD_(rwlock_get_or_allocate)(rwlock, rwlock_type);
+   tl_assert(p);
+
+   if (DRD_(rwlock_is_wrlocked_by)(p, DRD_(thread_get_running_tid)()))
+   {
+      VG_(message)(Vg_UserMsg,
+                   "reader-writer lock 0x%lx is already locked for"
+                   " writing by calling thread\n",
+                   p->a1);
+   }
+}
+
+/**
+ * Update rwlock_info state when locking the pthread_rwlock_t mutex.
+ * Note: this function must be called after pthread_rwlock_rdlock() has been
+ * called, or a race condition is triggered !
+ */
+void DRD_(rwlock_post_rdlock)(const Addr rwlock, const RwLockT rwlock_type,
+                              const Bool took_lock)
+{
+   const DrdThreadId drd_tid = DRD_(thread_get_running_tid)();
+   struct rwlock_info* p;
+   struct rwlock_thread_info* q;
+
+   if (DRD_(s_trace_rwlock))
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] post_rwlock_rdlock 0x%lx\n",
+                   drd_tid,
+                   rwlock);
+   }
+
+   p = DRD_(rwlock_get)(rwlock);
+
+   if (! p || ! took_lock)
+      return;
+
+   tl_assert(! DRD_(rwlock_is_wrlocked)(p));
+
+   q = DRD_(lookup_or_insert_node)(p->thread_info, drd_tid);
+   if (++q->reader_nesting_count == 1)
+   {
+      DRD_(thread_new_segment)(drd_tid);
+      DRD_(s_rwlock_segment_creation_count)++;
+      DRD_(rwlock_combine_other_vc)(p, drd_tid, False);
+
+      p->acquiry_time_ms = VG_(read_millisecond_timer)();
+      p->acquired_at     = VG_(record_ExeContext)(VG_(get_running_tid)(), 0);
+   }
+}
+
+/**
+ * Called before pthread_rwlock_wrlock() is invoked. If a data structure for
+ * the client-side object was not yet created, do this now. Also check whether
+ * an attempt is made to lock recursively a synchronization object that must
+ * not be locked recursively.
+ */
+void DRD_(rwlock_pre_wrlock)(const Addr rwlock, const RwLockT rwlock_type)
+{
+   struct rwlock_info* p;
+
+   p = DRD_(rwlock_get)(rwlock);
+
+   if (DRD_(s_trace_rwlock))
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] pre_rwlock_wrlock  0x%lx\n",
+                   DRD_(thread_get_running_tid)(),
+                   rwlock);
+   }
+
+   if (p == 0)
+      p = DRD_(rwlock_get_or_allocate)(rwlock, rwlock_type);
+
+   tl_assert(p);
+
+   if (DRD_(rwlock_is_wrlocked_by)(p, DRD_(thread_get_running_tid)()))
+   {
+      RwlockErrInfo REI = { DRD_(thread_get_running_tid)(), p->a1 };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              RwlockErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "Recursive writer locking not allowed",
+                              &REI);
+   }
+}
+
+/**
+ * Update rwlock_info state when locking the pthread_rwlock_t rwlock.
+ * Note: this function must be called after pthread_rwlock_wrlock() has
+ * finished, or a race condition is triggered !
+ */
+void DRD_(rwlock_post_wrlock)(const Addr rwlock, const RwLockT rwlock_type,
+                              const Bool took_lock)
+{
+   const DrdThreadId drd_tid = DRD_(thread_get_running_tid)();
+   struct rwlock_info* p;
+   struct rwlock_thread_info* q;
+
+   p = DRD_(rwlock_get)(rwlock);
+
+   if (DRD_(s_trace_rwlock))
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] post_rwlock_wrlock 0x%lx\n",
+                   drd_tid,
+                   rwlock);
+   }
+
+   if (! p || ! took_lock)
+      return;
+
+   q = DRD_(lookup_or_insert_node)(p->thread_info,
+                                   DRD_(thread_get_running_tid)());
+   tl_assert(q->writer_nesting_count == 0);
+   q->writer_nesting_count++;
+   tl_assert(q->writer_nesting_count == 1);
+   DRD_(thread_new_segment)(drd_tid);
+   DRD_(s_rwlock_segment_creation_count)++;
+   DRD_(rwlock_combine_other_vc)(p, drd_tid, True);
+   p->acquiry_time_ms = VG_(read_millisecond_timer)();
+   p->acquired_at     = VG_(record_ExeContext)(VG_(get_running_tid)(), 0);
+}
+
+/**
+ * Update rwlock_info state when unlocking the pthread_rwlock_t rwlock.
+ *
+ * @param rwlock Pointer to pthread_rwlock_t data structure in the client space.
+ *
+ * @return New value of the rwlock recursion count.
+ *
+ * @note This function must be called before pthread_rwlock_unlock() is called,
+ *   or a race condition is triggered !
+ */
+void DRD_(rwlock_pre_unlock)(const Addr rwlock, const RwLockT rwlock_type)
+{
+   const DrdThreadId drd_tid = DRD_(thread_get_running_tid)();
+   const ThreadId vg_tid = VG_(get_running_tid)();
+   struct rwlock_info* p;
+   struct rwlock_thread_info* q;
+
+   if (DRD_(s_trace_rwlock))
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] rwlock_unlock      0x%lx\n",
+                   drd_tid,
+                   rwlock);
+   }
+
+   p = DRD_(rwlock_get)(rwlock);
+   if (p == 0)
+   {
+      GenericErrInfo GEI = {
+	 .tid = DRD_(thread_get_running_tid)(),
+	 .addr = rwlock,
+      };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              GenericErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "Not a reader-writer lock",
+                              &GEI);
+      return;
+   }
+
+   drd_rwlock_check_type(p, rwlock_type);
+
+   if (! DRD_(rwlock_is_locked_by)(p, drd_tid))
+   {
+      RwlockErrInfo REI = { DRD_(thread_get_running_tid)(), p->a1 };
+      VG_(maybe_record_error)(vg_tid,
+                              RwlockErr,
+                              VG_(get_IP)(vg_tid),
+                              "Reader-writer lock not locked by calling thread",
+                              &REI);
+      return;
+   }
+   q = DRD_(lookup_or_insert_node)(p->thread_info, drd_tid);
+   tl_assert(q);
+   if (q->reader_nesting_count > 0)
+   {
+      q->reader_nesting_count--;
+      if (q->reader_nesting_count == 0 && DRD_(s_shared_threshold_ms) > 0)
+      {
+         Long held = VG_(read_millisecond_timer)() - p->acquiry_time_ms;
+         if (held > DRD_(s_shared_threshold_ms))
+         {
+            HoldtimeErrInfo HEI
+               = { DRD_(thread_get_running_tid)(),
+                   rwlock, p->acquired_at, held, DRD_(s_shared_threshold_ms) };
+            VG_(maybe_record_error)(vg_tid,
+                                    HoldtimeErr,
+                                    VG_(get_IP)(vg_tid),
+                                    "rwlock",
+                                    &HEI);
+         }
+      }
+      if (q->reader_nesting_count == 0 && q->writer_nesting_count == 0)
+      {
+         /*
+          * This pthread_rwlock_unlock() call really unlocks the rwlock. Save
+          * the current vector clock of the thread such that it is available
+          * when this rwlock is locked again.
+          */
+         DRD_(thread_get_latest_segment)(&q->latest_rdlocked_segment, drd_tid);
+         DRD_(thread_new_segment)(drd_tid);
+         DRD_(s_rwlock_segment_creation_count)++;
+      }
+   }
+   else if (q->writer_nesting_count > 0)
+   {
+      q->writer_nesting_count--;
+      if (q->writer_nesting_count == 0 && DRD_(s_exclusive_threshold_ms) > 0)
+      {
+         Long held = VG_(read_millisecond_timer)() - p->acquiry_time_ms;
+         if (held > DRD_(s_exclusive_threshold_ms))
+         {
+            HoldtimeErrInfo HEI
+               = { DRD_(thread_get_running_tid)(),
+                   rwlock, p->acquired_at, held,
+                   DRD_(s_exclusive_threshold_ms) };
+            VG_(maybe_record_error)(vg_tid,
+                                    HoldtimeErr,
+                                    VG_(get_IP)(vg_tid),
+                                    "rwlock",
+                                    &HEI);
+         }
+      }
+      if (q->reader_nesting_count == 0 && q->writer_nesting_count == 0)
+      {
+         /*
+          * This pthread_rwlock_unlock() call really unlocks the rwlock. Save
+          * the current vector clock of the thread such that it is available
+          * when this rwlock is locked again.
+          */
+         DRD_(thread_get_latest_segment)(&q->latest_wrlocked_segment, drd_tid);
+         DRD_(thread_new_segment)(drd_tid);
+         DRD_(s_rwlock_segment_creation_count)++;
+      }
+   }
+   else
+   {
+      tl_assert(False);
+   }
+}
+
+/** Called when thread tid stops to exist. */
+static void rwlock_delete_thread(struct rwlock_info* const p,
+                                 const DrdThreadId tid)
+{
+   struct rwlock_thread_info* q;
+
+   if (DRD_(rwlock_is_locked_by)(p, tid))
+   {
+      RwlockErrInfo REI = { DRD_(thread_get_running_tid)(), p->a1 };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              RwlockErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "Reader-writer lock still locked at thread exit",
+                              &REI);
+      q = DRD_(lookup_or_insert_node)(p->thread_info, tid);
+      q->reader_nesting_count = 0;
+      q->writer_nesting_count = 0;
+   }
+}
+
+ULong DRD_(get_rwlock_segment_creation_count)(void)
+{
+   return DRD_(s_rwlock_segment_creation_count);
+}
diff --git a/drd/drd_rwlock.h b/drd/drd_rwlock.h
new file mode 100644
index 0000000..855ad3d
--- /dev/null
+++ b/drd/drd_rwlock.h
@@ -0,0 +1,57 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+// Reader-writer lock state information.
+
+
+#ifndef __DRD_RWLOCK_H
+#define __DRD_RWLOCK_H
+
+
+#include "drd_clientobj.h"        // struct rwlock_info
+#include "drd_thread.h"           // DrdThreadId
+#include "pub_tool_basics.h"      // Addr
+
+
+struct rwlock_info;
+
+
+void DRD_(rwlock_set_trace)(const Bool trace_rwlock);
+void DRD_(rwlock_set_exclusive_threshold)(const UInt exclusive_threshold_ms);
+void DRD_(rwlock_set_shared_threshold)(const UInt shared_threshold_ms);
+struct rwlock_info* DRD_(rwlock_pre_init)(const Addr rwlock,
+                                          const RwLockT rwlock_type);
+void DRD_(rwlock_post_destroy)(const Addr rwlock, const RwLockT rwlock_type);
+void DRD_(rwlock_pre_rdlock)(const Addr rwlock, const RwLockT rwlock_type);
+void DRD_(rwlock_post_rdlock)(const Addr rwlock, const RwLockT rwlock_type,
+                              const Bool took_lock);
+void DRD_(rwlock_pre_wrlock)(const Addr rwlock, const RwLockT rwlock_type);
+void DRD_(rwlock_post_wrlock)(const Addr rwlock, const RwLockT rwlock_type,
+                              const Bool took_lock);
+void DRD_(rwlock_pre_unlock)(const Addr rwlock, const RwLockT rwlock_type);
+ULong DRD_(get_rwlock_segment_creation_count)(void);
+
+
+#endif /* __DRD_RWLOCK_H */
diff --git a/drd/drd_segment.c b/drd/drd_segment.c
new file mode 100644
index 0000000..e4a0680
--- /dev/null
+++ b/drd/drd_segment.c
@@ -0,0 +1,252 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#include "drd_error.h"
+#include "drd_segment.h"
+#include "drd_thread.h"
+#include "pub_tool_basics.h"      // Addr, SizeT
+#include "pub_tool_libcassert.h"  // tl_assert()
+#include "pub_tool_libcbase.h"    // VG_(strlen)()
+#include "pub_tool_libcprint.h"   // VG_(printf)()
+#include "pub_tool_machine.h"     // VG_(get_SP)()
+#include "pub_tool_mallocfree.h"  // VG_(malloc)(), VG_(free)()
+#include "pub_tool_threadstate.h" // VG_INVALID_THREADID
+
+
+/* Local variables. */
+
+static ULong s_segment_merge_count;
+static ULong s_segments_created_count;
+static ULong s_segments_alive_count;
+static ULong s_max_segments_alive_count;
+static Bool s_trace_segment;
+
+
+/* Function definitions. */
+
+/**
+ * Initialize the memory 'sg' points at.
+ *
+ * @note The creator and created thread ID's may be equal.
+ * @note This function copies the vector clock of thread 'creator', a technique
+ *   also known as clock snooping. This will only work reliably if the thread
+ *   that called pthread_create() waits until the created thread has copied
+ *   the vector clock.
+ */
+static void sg_init(Segment* const sg,
+                    const DrdThreadId creator,
+                    const DrdThreadId created)
+{
+   Segment* creator_sg;
+   ThreadId vg_created = DRD_(DrdThreadIdToVgThreadId)(created);
+
+   tl_assert(sg);
+   tl_assert(creator == DRD_INVALID_THREADID
+             || DRD_(IsValidDrdThreadId)(creator));
+
+   creator_sg = (creator != DRD_INVALID_THREADID
+                 ? DRD_(thread_get_segment)(creator) : 0);
+
+   sg->next = 0;
+   sg->prev = 0;
+   sg->tid = created;
+   sg->refcnt = 1;
+
+   if (vg_created != VG_INVALID_THREADID && VG_(get_SP)(vg_created) != 0)
+      sg->stacktrace = VG_(record_ExeContext)(vg_created, 0);
+   else
+      sg->stacktrace = 0;
+
+   if (creator_sg)
+      DRD_(vc_copy)(&sg->vc, &creator_sg->vc);
+   else
+      DRD_(vc_init)(&sg->vc, 0, 0);
+   DRD_(vc_increment)(&sg->vc, created);
+   DRD_(bm_init)(&sg->bm);
+
+   if (s_trace_segment)
+   {
+      char* vc;
+
+      vc = DRD_(vc_aprint)(&sg->vc);
+      VG_(message)(Vg_DebugMsg, "New segment for thread %d with vc %s\n",
+                   created, vc);
+      VG_(free)(vc);
+   }
+}
+
+/** Deallocate the memory that was allocated by sg_init(). */
+static void DRD_(sg_cleanup)(Segment* const sg)
+{
+   tl_assert(sg);
+   tl_assert(sg->refcnt == 0);
+
+   DRD_(vc_cleanup)(&sg->vc);
+   DRD_(bm_cleanup)(&sg->bm);
+}
+
+/** Allocate and initialize a new segment. */
+Segment* DRD_(sg_new)(const DrdThreadId creator, const DrdThreadId created)
+{
+   Segment* sg;
+
+   s_segments_created_count++;
+   s_segments_alive_count++;
+   if (s_max_segments_alive_count < s_segments_alive_count)
+      s_max_segments_alive_count = s_segments_alive_count;
+
+   sg = VG_(malloc)("drd.segment.sn.1", sizeof(*sg));
+   tl_assert(sg);
+   sg_init(sg, creator, created);
+   return sg;
+}
+
+static void DRD_(sg_delete)(Segment* const sg)
+{
+   if (DRD_(sg_get_trace)())
+   {
+      char* vc;
+
+      vc = DRD_(vc_aprint)(&sg->vc);
+      VG_(message)(Vg_DebugMsg, "Discarding the segment with vector clock %s\n",
+                   vc);
+      VG_(free)(vc);
+   }
+
+   s_segments_alive_count--;
+
+   tl_assert(sg);
+   DRD_(sg_cleanup)(sg);
+   VG_(free)(sg);
+}
+
+/** Increment the reference count of the specified segment. */
+Segment* DRD_(sg_get)(Segment* const sg)
+{
+   tl_assert(sg);
+
+   sg->refcnt++;
+   return sg;
+}
+
+/**
+ * Decrement the reference count of the specified segment and deallocate the
+ * segment if the reference count became zero.
+ */
+void DRD_(sg_put)(Segment* const sg)
+{
+   if (sg == 0)
+      return;
+
+   if (s_trace_segment)
+   {
+      char* vc;
+
+      vc = DRD_(vc_aprint)(&sg->vc);
+      VG_(message)(Vg_DebugMsg,
+                   "Decrementing segment reference count %d -> %d with vc %s\n",
+                   sg->refcnt, sg->refcnt - 1, vc);
+      VG_(free)(vc);
+   }
+
+   tl_assert(sg->refcnt >= 1);
+
+   if (--sg->refcnt == 0)
+   {
+      DRD_(sg_delete)(sg);
+   }
+}
+
+/** Merge sg1 and sg2 into sg1. */
+void DRD_(sg_merge)(Segment* const sg1, Segment* const sg2)
+{
+   tl_assert(sg1);
+   tl_assert(sg1->refcnt == 1);
+   tl_assert(sg2);
+   tl_assert(sg2->refcnt == 1);
+
+   if (s_trace_segment)
+   {
+      char *vc1, *vc2;
+
+      vc1 = DRD_(vc_aprint)(&sg1->vc);
+      vc2 = DRD_(vc_aprint)(&sg2->vc);
+
+      VG_(message)(Vg_DebugMsg,
+		   "Merging segments with vector clocks %s and %s\n", vc1, vc2);
+      VG_(free)(vc1);
+      VG_(free)(vc2);
+   }
+
+   s_segment_merge_count++;
+
+   // Keep sg1->stacktrace.
+   // Keep sg1->vc.
+   // Merge sg2->bm into sg1->bm.
+   DRD_(bm_merge2)(&sg1->bm, &sg2->bm);
+}
+
+/** Print the vector clock and the bitmap of the specified segment. */
+void DRD_(sg_print)(Segment* const sg)
+{
+   tl_assert(sg);
+   VG_(printf)("vc: ");
+   DRD_(vc_print)(&sg->vc);
+   VG_(printf)("\n");
+   DRD_(bm_print)(&sg->bm);
+}
+
+/** Query whether segment tracing has been enabled. */
+Bool DRD_(sg_get_trace)(void)
+{
+   return s_trace_segment;
+}
+
+/** Enable or disable segment tracing. */
+void DRD_(sg_set_trace)(Bool const trace_segment)
+{
+   tl_assert(trace_segment == False || trace_segment == True);
+   s_trace_segment = trace_segment;
+}
+
+ULong DRD_(sg_get_segments_created_count)(void)
+{
+   return s_segments_created_count;
+}
+
+ULong DRD_(sg_get_segments_alive_count)(void)
+{
+   return s_segments_alive_count;
+}
+
+ULong DRD_(sg_get_max_segments_alive_count)(void)
+{
+   return s_max_segments_alive_count;
+}
+
+ULong DRD_(sg_get_segment_merge_count)(void)
+{
+   return s_segment_merge_count;
+}
diff --git a/drd/drd_segment.h b/drd/drd_segment.h
new file mode 100644
index 0000000..b90e9f3
--- /dev/null
+++ b/drd/drd_segment.h
@@ -0,0 +1,100 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#ifndef __SEGMENT_H
+#define __SEGMENT_H
+
+
+/*
+ * Segments and segment lists. A segment represents information about
+ * a contiguous group of statements of a specific thread. There is a vector
+ * clock associated with each segment.
+ */
+
+
+#include "drd_vc.h"
+#include "pub_drd_bitmap.h"
+#include "pub_tool_execontext.h" // ExeContext
+#include "pub_tool_stacktrace.h" // StackTrace
+
+
+typedef struct segment
+{
+   /** Pointers to next and previous segments executed by the same thread. */
+   struct segment*    next;
+   struct segment*    prev;
+   DrdThreadId        tid;
+   /** Reference count: number of pointers that point to this segment. */
+   int                refcnt;
+   /** Stack trace of the first instruction of the segment. */
+   ExeContext*        stacktrace;
+   /** Vector clock associated with the segment. */
+   VectorClock        vc;
+   /**
+    * Bitmap representing the memory accesses by the instructions associated
+    * with the segment.
+    */
+   struct bitmap      bm;
+} Segment;
+
+
+Segment* DRD_(sg_new)(const DrdThreadId creator, const DrdThreadId created);
+static int DRD_(sg_get_refcnt)(const Segment* const sg);
+Segment* DRD_(sg_get)(Segment* const sg);
+void DRD_(sg_put)(Segment* const sg);
+static struct bitmap* DRD_(sg_bm)(Segment* const sg);
+void DRD_(sg_merge)(Segment* const sg1, Segment* const sg2);
+void DRD_(sg_print)(Segment* const sg);
+Bool DRD_(sg_get_trace)(void);
+void DRD_(sg_set_trace)(const Bool trace_segment);
+ULong DRD_(sg_get_segments_created_count)(void);
+ULong DRD_(sg_get_segments_alive_count)(void);
+ULong DRD_(sg_get_max_segments_alive_count)(void);
+ULong DRD_(sg_get_segment_merge_count)(void);
+
+
+/** Query the reference count of the specified segment. */
+static __inline__ int DRD_(sg_get_refcnt)(const Segment* const sg)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(sg);
+#endif
+
+   return sg->refcnt;
+}
+
+/** Return the pointer to the bitmap of the segment. */
+static __inline__ struct bitmap* DRD_(sg_bm)(Segment* const sg)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(sg);
+#endif
+
+   return &sg->bm;
+}
+
+
+
+#endif // __SEGMENT_H
diff --git a/drd/drd_semaphore.c b/drd/drd_semaphore.c
new file mode 100644
index 0000000..388b3b2
--- /dev/null
+++ b/drd/drd_semaphore.c
@@ -0,0 +1,470 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#include "drd_clientobj.h"
+#include "drd_error.h"
+#include "drd_semaphore.h"
+#include "drd_suppression.h"
+#include "pub_tool_errormgr.h"    // VG_(maybe_record_error)()
+#include "pub_tool_libcassert.h"  // tl_assert()
+#include "pub_tool_libcprint.h"   // VG_(printf)()
+#include "pub_tool_machine.h"     // VG_(get_IP)()
+#include "pub_tool_mallocfree.h"  // VG_(malloc), VG_(free)
+#include "pub_tool_threadstate.h" // VG_(get_running_tid)()
+
+
+/* Local functions. */
+
+static void semaphore_cleanup(struct semaphore_info* p);
+
+
+/* Local variables. */
+
+static Bool s_trace_semaphore;
+static ULong s_semaphore_segment_creation_count;
+
+
+/* Function definitions. */
+
+/** Push a segment at the end of the queue 'p->last_sem_post_seg'. */
+static void drd_segment_push(struct semaphore_info* p, Segment* sg)
+{
+   Word n;
+
+   tl_assert(sg);
+   n = VG_(addToXA)(p->last_sem_post_seg, &sg);
+#if 0
+   VG_(message)(Vg_UserMsg, "0x%lx push: added at position %ld/%ld",
+                p->a1, n, VG_(sizeXA)(p->last_sem_post_seg));
+#endif
+   tl_assert(*(Segment**)VG_(indexXA)(p->last_sem_post_seg, n) == sg);
+}
+
+/** Pop a segment from the beginning of the queue 'p->last_sem_post_seg'. */
+static Segment* drd_segment_pop(struct semaphore_info* p)
+{
+   Word sz;
+   Segment* sg;
+
+   sz = VG_(sizeXA)(p->last_sem_post_seg);
+#if 0
+   VG_(message)(Vg_UserMsg, "0x%lx pop:  removed from position %ld/%ld",
+                p->a1, sz - 1, sz);
+#endif
+   sg = 0;
+   if (sz > 0)
+   {
+      sg = *(Segment**)VG_(indexXA)(p->last_sem_post_seg, sz - 1);
+      tl_assert(sg);
+      VG_(dropTailXA)(p->last_sem_post_seg, 1);
+   }
+   return sg;
+}
+
+/** Enable or disable tracing of semaphore actions. */
+void DRD_(semaphore_set_trace)(const Bool trace_semaphore)
+{
+   s_trace_semaphore = trace_semaphore;
+}
+
+/**
+ * Initialize the memory 'p' points at as a semaphore_info structure for the
+ * client semaphore at client addres 'semaphore'.
+ */
+static
+void drd_semaphore_initialize(struct semaphore_info* const p,
+                              const Addr semaphore)
+{
+   tl_assert(semaphore != 0);
+   tl_assert(p->a1 == semaphore);
+   tl_assert(p->type == ClientSemaphore);
+
+   p->cleanup           = (void(*)(DrdClientobj*))semaphore_cleanup;
+   p->delete_thread     = 0;
+   p->waits_to_skip     = 0;
+   p->value             = 0;
+   p->waiters           = 0;
+   p->last_sem_post_tid = DRD_INVALID_THREADID;
+   p->last_sem_post_seg = VG_(newXA)(VG_(malloc), "drd.sg-stack",
+                                     VG_(free), sizeof(Segment*));
+}
+
+/**
+ * Free the memory that was allocated by semaphore_initialize(). Called by
+ * DRD_(clientobj_remove)().
+ */
+static void semaphore_cleanup(struct semaphore_info* p)
+{
+   Segment* sg;
+
+   if (p->waiters > 0)
+   {
+      SemaphoreErrInfo sei = { DRD_(thread_get_running_tid)(), p->a1 };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              SemaphoreErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "Destruction of semaphore that is being waited"
+                              " upon",
+                              &sei);
+   }
+   while ((sg = drd_segment_pop(p)))
+      DRD_(sg_put)(sg);
+   VG_(deleteXA)(p->last_sem_post_seg);
+}
+
+/**
+ * Return a pointer to the structure with information about the specified
+ * client semaphore. Allocate a new structure if such a structure did not
+ * yet exist.
+ */
+static
+struct semaphore_info*
+drd_semaphore_get_or_allocate(const Addr semaphore)
+{
+   struct semaphore_info *p;
+
+   tl_assert(offsetof(DrdClientobj, semaphore) == 0);
+   p = &(DRD_(clientobj_get)(semaphore, ClientSemaphore)->semaphore);
+   if (p == 0)
+   {
+      tl_assert(offsetof(DrdClientobj, semaphore) == 0);
+      p = &(DRD_(clientobj_add)(semaphore, ClientSemaphore)->semaphore);
+      drd_semaphore_initialize(p, semaphore);
+   }
+   return p;
+}
+
+/**
+ * Return a pointer to the structure with information about the specified
+ * client semaphore, or null if no such structure was found.
+ */
+static struct semaphore_info* semaphore_get(const Addr semaphore)
+{
+   tl_assert(offsetof(DrdClientobj, semaphore) == 0);
+   return &(DRD_(clientobj_get)(semaphore, ClientSemaphore)->semaphore);
+}
+
+/** Called before sem_init(). */
+struct semaphore_info* DRD_(semaphore_init)(const Addr semaphore,
+                                            const Word pshared,
+                                            const UInt value)
+{
+   struct semaphore_info* p;
+   Segment* sg;
+
+   if (s_trace_semaphore)
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] sem_init      0x%lx value %u\n",
+                   DRD_(thread_get_running_tid)(),
+                   semaphore,
+                   value);
+   }
+   p = semaphore_get(semaphore);
+   if (p)
+   {
+      const ThreadId vg_tid = VG_(get_running_tid)();
+      SemaphoreErrInfo SEI = { DRD_(thread_get_running_tid)(), semaphore };
+      VG_(maybe_record_error)(vg_tid,
+                              SemaphoreErr,
+                              VG_(get_IP)(vg_tid),
+                              "Semaphore reinitialization",
+                              &SEI);
+      // Remove all segments from the segment stack.
+      while ((sg = drd_segment_pop(p)))
+      {
+         DRD_(sg_put)(sg);
+      }
+   }
+   else
+   {
+#if defined(VGO_darwin)
+      const ThreadId vg_tid = VG_(get_running_tid)();
+      GenericErrInfo GEI = { DRD_(thread_get_running_tid)(), NULL };
+      VG_(maybe_record_error)(vg_tid,
+			      GenericErr,
+			      VG_(get_IP)(vg_tid),
+			      "sem_init() is not yet supported on Darwin",
+			      &GEI);
+      return NULL;
+#else
+      p = drd_semaphore_get_or_allocate(semaphore);
+#endif
+   }
+   tl_assert(p);
+   p->waits_to_skip = value;
+   p->value         = value;
+   return p;
+}
+
+/** Called after sem_destroy(). */
+void DRD_(semaphore_destroy)(const Addr semaphore)
+{
+   struct semaphore_info* p;
+
+   p = semaphore_get(semaphore);
+
+   if (s_trace_semaphore)
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] sem_destroy   0x%lx value %u\n",
+                   DRD_(thread_get_running_tid)(),
+                   semaphore,
+                   p ? p->value : 0);
+   }
+
+   if (p == 0)
+   {
+      GenericErrInfo GEI = {
+	 .tid  = DRD_(thread_get_running_tid)(),
+	 .addr = semaphore,
+      };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              GenericErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "Not a semaphore",
+                              &GEI);
+      return;
+   }
+
+   DRD_(clientobj_remove)(semaphore, ClientSemaphore);
+}
+
+/** Called after sem_open(). */
+struct semaphore_info* DRD_(semaphore_open)(const Addr semaphore,
+                                            const Char* name, const Word oflag,
+                                            const Word mode, const UInt value)
+{
+   struct semaphore_info* p;
+   Segment* sg;
+
+   if (s_trace_semaphore)
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] sem_open      0x%lx name %s"
+                   " oflag %#lx mode %#lo value %u\n",
+                   DRD_(thread_get_running_tid)(),
+                   semaphore, name, oflag, mode, value);
+   }
+
+   /* Return if the sem_open() call failed. */
+   if (! semaphore)
+      return NULL;
+
+   p = semaphore_get(semaphore);
+   if (p)
+   {
+      const ThreadId vg_tid = VG_(get_running_tid)();
+      SemaphoreErrInfo SEI = { DRD_(thread_get_running_tid)(), semaphore };
+      VG_(maybe_record_error)(vg_tid,
+                              SemaphoreErr,
+                              VG_(get_IP)(vg_tid),
+                              "Semaphore reinitialization",
+                              &SEI);
+      // Remove all segments from the segment stack.
+      while ((sg = drd_segment_pop(p)))
+      {
+         DRD_(sg_put)(sg);
+      }
+   }
+   else
+   {
+      p = drd_semaphore_get_or_allocate(semaphore);
+   }
+   tl_assert(p);
+   p->waits_to_skip = value;
+   p->value         = value;
+   return p;
+}
+
+/** Called before sem_close(). */
+void DRD_(semaphore_close)(const Addr semaphore)
+{
+   struct semaphore_info* p;
+
+   p = semaphore_get(semaphore);
+
+   if (s_trace_semaphore)
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] sem_close     0x%lx value %u\n",
+                   DRD_(thread_get_running_tid)(),
+                   semaphore,
+                   p ? p->value : 0);
+   }
+
+   if (p == 0)
+   {
+      GenericErrInfo GEI = {
+	 .tid  = DRD_(thread_get_running_tid)(),
+	 .addr = semaphore,
+      };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              GenericErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "Not a semaphore",
+                              &GEI);
+      return;
+   }
+
+   DRD_(clientobj_remove)(semaphore, ClientSemaphore);
+}
+
+/** Called before sem_wait(). */
+void DRD_(semaphore_pre_wait)(const Addr semaphore)
+{
+   struct semaphore_info* p;
+
+   tl_assert(semaphore < semaphore + 1);
+   p = drd_semaphore_get_or_allocate(semaphore);
+   tl_assert(p);
+   p->waiters++;
+
+   if ((Word)(p->waiters) <= 0)
+   {
+      SemaphoreErrInfo sei = { DRD_(thread_get_running_tid)(), semaphore };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              SemaphoreErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "Invalid semaphore",
+                              &sei);
+   }
+}
+
+/**
+ * Called after sem_wait() finished.
+ * @note Do not rely on the value of 'waited' -- some glibc versions do
+ *       not set it correctly.
+ */
+void DRD_(semaphore_post_wait)(const DrdThreadId tid, const Addr semaphore,
+                               const Bool waited)
+{
+   struct semaphore_info* p;
+   Segment* sg;
+
+   p = semaphore_get(semaphore);
+   if (s_trace_semaphore)
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] sem_wait      0x%lx value %u -> %u\n",
+                   DRD_(thread_get_running_tid)(),
+                   semaphore,
+                   p ? p->value : 0,
+                   p ? p->value - 1 : 0);
+   }
+
+   if (p)
+   {
+      p->waiters--;
+      p->value--;
+   }
+
+   /*
+    * Note: if another thread destroyed and reinitialized a semaphore while
+    * the current thread was waiting in sem_wait, p->waiters may have been
+    * set to zero by drd_semaphore_initialize() after
+    * DRD_(semaphore_pre_wait)() has finished before
+    * DRD_(semaphore_post_wait)() has been called.
+    */
+   if (p == NULL || (Int)(p->value) < 0 || (Word)(p->waiters) < 0)
+   {
+      SemaphoreErrInfo sei = { DRD_(thread_get_running_tid)(), semaphore };
+      VG_(maybe_record_error)(VG_(get_running_tid)(),
+                              SemaphoreErr,
+                              VG_(get_IP)(VG_(get_running_tid)()),
+                              "Invalid semaphore",
+                              &sei);
+      return;
+   }
+
+   if (p->waits_to_skip > 0)
+      p->waits_to_skip--;
+   else
+   {
+      sg = drd_segment_pop(p);
+      tl_assert(sg);
+      if (sg)
+      {
+         if (p->last_sem_post_tid != tid
+             && p->last_sem_post_tid != DRD_INVALID_THREADID)
+         {
+            DRD_(thread_new_segment_and_combine_vc)(tid, sg);
+         }
+         else
+            DRD_(thread_new_segment)(tid);
+         s_semaphore_segment_creation_count++;
+         DRD_(sg_put)(sg);
+      }
+   }
+}
+
+/** Called before sem_post(). */
+void DRD_(semaphore_pre_post)(const DrdThreadId tid, const Addr semaphore)
+{
+   struct semaphore_info* p;
+   Segment* sg;
+
+   p = drd_semaphore_get_or_allocate(semaphore);
+   p->value++;
+
+   if (s_trace_semaphore)
+   {
+      VG_(message)(Vg_UserMsg,
+                   "[%d] sem_post      0x%lx value %u -> %u\n",
+                   DRD_(thread_get_running_tid)(),
+                   semaphore,
+                   p->value - 1, p->value);
+   }
+
+   p->last_sem_post_tid = tid;
+   sg = 0;
+   DRD_(thread_get_latest_segment)(&sg, tid);
+   tl_assert(sg);
+   drd_segment_push(p, sg);
+   DRD_(thread_new_segment)(tid);
+   s_semaphore_segment_creation_count++;
+}
+
+/** Called after sem_post() finished. */
+void DRD_(semaphore_post_post)(const DrdThreadId tid, const Addr semaphore,
+                               const Bool succeeded)
+{
+   /*
+    * Note: it is hard to implement the sem_post() wrapper correctly in
+    * case sem_post() returns an error code. This is because handling this
+    * case correctly requires restoring the vector clock associated with
+    * the semaphore to its original value here. In order to do that without
+    * introducing a race condition, extra locking has to be added around
+    * each semaphore call. Such extra locking would have to be added in
+    * drd_pthread_intercepts.c. However, it is hard to implement
+    * synchronization in drd_pthread_intercepts.c in a portable way without
+    * calling already redirected functions.
+    */
+}
+
+ULong DRD_(get_semaphore_segment_creation_count)(void)
+{
+   return s_semaphore_segment_creation_count;
+}
diff --git a/drd/drd_semaphore.h b/drd/drd_semaphore.h
new file mode 100644
index 0000000..8b0b7f3
--- /dev/null
+++ b/drd/drd_semaphore.h
@@ -0,0 +1,58 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+// Semaphore state information: owner thread and recursion count.
+
+
+#ifndef __DRD_SEMAPHORE_H
+#define __DRD_SEMAPHORE_H
+
+
+#include "drd_thread.h"           // DrdThreadId
+#include "pub_tool_basics.h"      // Addr
+
+
+struct semaphore_info;
+
+
+void DRD_(semaphore_set_trace)(const Bool trace_semaphore);
+struct semaphore_info* DRD_(semaphore_init)(const Addr semaphore,
+                                            const Word pshared,
+                                            const UInt value);
+void DRD_(semaphore_destroy)(const Addr semaphore);
+struct semaphore_info* DRD_(semaphore_open)(const Addr semaphore,
+                                            const Char* name, const Word oflag,
+                                            const Word mode, const UInt value);
+void DRD_(semaphore_close)(const Addr semaphore);
+void DRD_(semaphore_pre_wait)(const Addr semaphore);
+void DRD_(semaphore_post_wait)(const DrdThreadId tid, const Addr semaphore,
+                               const Bool waited);
+void DRD_(semaphore_pre_post)(const DrdThreadId tid, const Addr semaphore);
+void DRD_(semaphore_post_post)(const DrdThreadId tid, const Addr semaphore,
+                               const Bool waited);
+ULong DRD_(get_semaphore_segment_creation_count)(void);
+
+
+#endif /* __DRD_SEMAPHORE_H */
diff --git a/drd/drd_strmem_intercepts.c b/drd/drd_strmem_intercepts.c
new file mode 100644
index 0000000..1a87f42
--- /dev/null
+++ b/drd/drd_strmem_intercepts.c
@@ -0,0 +1,75 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+
+/*--------------------------------------------------------------------*/
+/*--- Replacements for strlen() and strnlen(), which run on the    ---*/
+/*--- simulated CPU.                                               ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+  This file is part of DRD, a heavyweight Valgrind tool for
+  detecting threading errors. The code below has been extracted
+  from memchec/mc_replace_strmem.c, which has the following copyright
+  notice:
+
+  Copyright (C) 2000-2010 Julian Seward
+  jseward@acm.org
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "pub_tool_basics.h"
+#include "pub_tool_hashtable.h"
+#include "pub_tool_redir.h"
+#include "pub_tool_tooliface.h"
+#include "valgrind.h"
+
+
+#define STRNLEN(soname, fnname)                                         \
+   SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ); \
+   SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ) \
+   {                                                                    \
+      SizeT i = 0;                                                      \
+      while (i < n && str[i] != 0) i++;                                 \
+      return i;                                                         \
+   }
+
+STRNLEN(VG_Z_LIBC_SONAME, strnlen)
+
+
+// Note that this replacement often doesn't get used because gcc inlines
+// calls to strlen() with its own built-in version.  This can be very
+// confusing if you aren't expecting it.  Other small functions in this file
+// may also be inline by gcc.
+#define STRLEN(soname, fnname)                                          \
+   SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str );      \
+   SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str )       \
+   {                                                                    \
+      SizeT i = 0;                                                      \
+      while (str[i] != 0) i++;                                          \
+      return i;                                                         \
+   }
+
+STRLEN(VG_Z_LIBC_SONAME,          strlen)
+#if defined(VGO_linux)
+STRLEN(VG_Z_LD_LINUX_SO_2,        strlen)
+STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
+#endif
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
diff --git a/drd/drd_suppression.c b/drd/drd_suppression.c
new file mode 100644
index 0000000..eb4f44e
--- /dev/null
+++ b/drd/drd_suppression.c
@@ -0,0 +1,166 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#include "drd_suppression.h"
+#include "pub_drd_bitmap.h"
+#include "pub_tool_libcassert.h"  // tl_assert()
+#include "pub_tool_stacktrace.h"  // VG_(get_and_pp_StackTrace)()
+#include "pub_tool_threadstate.h" // VG_(get_running_tid)()
+#include "pub_tool_libcprint.h"   // Vg_DebugMsg
+
+
+/* Global variables. */
+
+Bool DRD_(g_any_address_traced) = False;
+
+
+/* Local variables. */
+
+static struct bitmap* DRD_(s_suppressed);
+static struct bitmap* DRD_(s_traced);
+static Bool DRD_(s_trace_suppression);
+
+
+/* Function definitions. */
+
+void DRD_(suppression_set_trace)(const Bool trace_suppression)
+{
+   DRD_(s_trace_suppression) = trace_suppression;
+}
+
+void DRD_(suppression_init)(void)
+{
+   tl_assert(DRD_(s_suppressed) == 0);
+   tl_assert(DRD_(s_traced)     == 0);
+   DRD_(s_suppressed) = DRD_(bm_new)();
+   DRD_(s_traced)     = DRD_(bm_new)();
+   tl_assert(DRD_(s_suppressed));
+   tl_assert(DRD_(s_traced));
+}
+
+void DRD_(start_suppression)(const Addr a1, const Addr a2,
+                             const char* const reason)
+{
+   if (DRD_(s_trace_suppression))
+   {
+      VG_(message)(Vg_DebugMsg, "start suppression of 0x%lx sz %ld (%s)\n",
+                   a1, a2 - a1, reason);
+   }
+
+   tl_assert(a1 <= a2);
+   DRD_(bm_access_range_store)(DRD_(s_suppressed), a1, a2);
+}
+
+void DRD_(finish_suppression)(const Addr a1, const Addr a2)
+{
+   if (DRD_(s_trace_suppression))
+   {
+      VG_(message)(Vg_DebugMsg, "finish suppression of 0x%lx sz %ld\n",
+                   a1, a2 - a1);
+      VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), 12);
+   }
+
+   tl_assert(a1 <= a2);
+   DRD_(bm_clear_store)(DRD_(s_suppressed), a1, a2);
+}
+
+/**
+ * Return true if data race detection suppression has been requested for all
+ * bytes in the range a1 .. a2 - 1 inclusive. Return false in case the range
+ * is only partially suppressed or not suppressed at all.
+ */
+Bool DRD_(is_suppressed)(const Addr a1, const Addr a2)
+{
+   return DRD_(bm_has)(DRD_(s_suppressed), a1, a2, eStore);
+}
+
+/**
+ * Return true if data race detection suppression has been requested for any
+ * of the bytes in the range a1 .. a2 - 1 inclusive. Return false in case none
+ * of the bytes in the specified range is suppressed.
+ */
+Bool DRD_(is_any_suppressed)(const Addr a1, const Addr a2)
+{
+   return DRD_(bm_has_any_store)(DRD_(s_suppressed), a1, a2);
+}
+
+void DRD_(mark_hbvar)(const Addr a1)
+{
+   DRD_(bm_access_range_load)(DRD_(s_suppressed), a1, a1 + 1);
+}
+
+Bool DRD_(range_contains_suppression_or_hbvar)(const Addr a1, const Addr a2)
+{
+   return DRD_(bm_has_any_access)(DRD_(s_suppressed), a1, a2);
+}
+
+void DRD_(start_tracing_address_range)(const Addr a1, const Addr a2)
+{
+   tl_assert(a1 <= a2);
+
+   DRD_(bm_access_range_load)(DRD_(s_traced), a1, a2);
+   if (! DRD_(g_any_address_traced))
+   {
+      DRD_(g_any_address_traced) = True;
+   }
+}
+
+void DRD_(stop_tracing_address_range)(const Addr a1, const Addr a2)
+{
+   tl_assert(a1 <= a2);
+
+   DRD_(bm_clear_load)(DRD_(s_traced), a1, a2);
+   if (DRD_(g_any_address_traced))
+   {
+      DRD_(g_any_address_traced)
+         = DRD_(bm_has_any_load)(DRD_(s_traced), 0, ~(Addr)0);
+   }
+}
+
+Bool DRD_(is_any_traced)(const Addr a1, const Addr a2)
+{
+   return DRD_(bm_has_any_load)(DRD_(s_traced), a1, a2);
+}
+
+void DRD_(suppression_stop_using_mem)(const Addr a1, const Addr a2)
+{
+   if (DRD_(s_trace_suppression))
+   {
+      Addr b;
+      for (b = a1; b < a2; b++)
+      {
+         if (DRD_(bm_has_1)(DRD_(s_suppressed), b, eStore))
+         {
+            VG_(message)(Vg_DebugMsg,
+                         "stop_using_mem(0x%lx, %ld) finish suppression of"
+                         " 0x%lx\n", a1, a2 - a1, b);
+         }
+      }
+   }
+   tl_assert(a1);
+   tl_assert(a1 <= a2);
+   DRD_(bm_clear)(DRD_(s_suppressed), a1, a2);
+   DRD_(bm_clear)(DRD_(s_traced), a1, a2);
+}
diff --git a/drd/drd_suppression.h b/drd/drd_suppression.h
new file mode 100644
index 0000000..40e0f4c
--- /dev/null
+++ b/drd/drd_suppression.h
@@ -0,0 +1,34 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+#ifndef __PUB_CORE_DRD_H
+#define __PUB_CORE_DRD_H
+
+
+#include "drd_basics.h"
+#include "pub_tool_basics.h"
+
+
+extern Bool DRD_(g_any_address_traced);
+
+
+void DRD_(suppression_set_trace)(const Bool trace_suppression);
+void DRD_(suppression_init)(void);
+void DRD_(start_suppression)(const Addr a1, const Addr a2,
+                             const char* const reason);
+void DRD_(finish_suppression)(const Addr a1, const Addr a2);
+Bool DRD_(is_suppressed)(const Addr a1, const Addr a2);
+Bool DRD_(is_any_suppressed)(const Addr a1, const Addr a2);
+void DRD_(mark_hbvar)(const Addr a1);
+Bool DRD_(range_contains_suppression_or_hbvar)(const Addr a1, const Addr a2);
+void DRD_(start_tracing_address_range)(const Addr a1, const Addr a2);
+void DRD_(stop_tracing_address_range)(const Addr a1, const Addr a2);
+Bool DRD_(is_any_traced)(const Addr a1, const Addr a2);
+void DRD_(suppression_stop_using_mem)(const Addr a1, const Addr a2);
+
+
+static __inline__ Bool DRD_(any_address_is_traced)(void)
+{
+   return DRD_(g_any_address_traced);
+}
+
+
+#endif // __PUB_CORE_DRD_H
diff --git a/drd/drd_thread.c b/drd/drd_thread.c
new file mode 100644
index 0000000..909bb45
--- /dev/null
+++ b/drd/drd_thread.c
@@ -0,0 +1,1639 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#include "drd_error.h"
+#include "drd_barrier.h"
+#include "drd_clientobj.h"
+#include "drd_cond.h"
+#include "drd_mutex.h"
+#include "drd_segment.h"
+#include "drd_semaphore.h"
+#include "drd_suppression.h"
+#include "drd_thread.h"
+#include "pub_tool_vki.h"
+#include "pub_tool_basics.h"      // Addr, SizeT
+#include "pub_tool_libcassert.h"  // tl_assert()
+#include "pub_tool_libcbase.h"    // VG_(strlen)()
+#include "pub_tool_libcprint.h"   // VG_(printf)()
+#include "pub_tool_libcproc.h"    // VG_(getenv)()
+#include "pub_tool_machine.h"
+#include "pub_tool_mallocfree.h"  // VG_(malloc)(), VG_(free)()
+#include "pub_tool_options.h"     // VG_(clo_backtrace_size)
+#include "pub_tool_threadstate.h" // VG_(get_pthread_id)()
+
+
+
+/* Local functions. */
+
+static void thread_append_segment(const DrdThreadId tid, Segment* const sg);
+static void thread_discard_segment(const DrdThreadId tid, Segment* const sg);
+static void thread_compute_conflict_set(struct bitmap** conflict_set,
+                                        const DrdThreadId tid);
+static Bool thread_conflict_set_up_to_date(const DrdThreadId tid);
+
+
+/* Local variables. */
+
+static ULong    s_context_switch_count;
+static ULong    s_discard_ordered_segments_count;
+static ULong    s_compute_conflict_set_count;
+static ULong    s_update_conflict_set_count;
+static ULong    s_update_conflict_set_new_sg_count;
+static ULong    s_update_conflict_set_sync_count;
+static ULong    s_update_conflict_set_join_count;
+static ULong    s_conflict_set_bitmap_creation_count;
+static ULong    s_conflict_set_bitmap2_creation_count;
+static ThreadId s_vg_running_tid  = VG_INVALID_THREADID;
+DrdThreadId     DRD_(g_drd_running_tid) = DRD_INVALID_THREADID;
+ThreadInfo      DRD_(g_threadinfo)[DRD_N_THREADS];
+struct bitmap*  DRD_(g_conflict_set);
+static Bool     s_trace_context_switches = False;
+static Bool     s_trace_conflict_set = False;
+static Bool     s_trace_conflict_set_bm = False;
+static Bool     s_trace_fork_join = False;
+static Bool     s_segment_merging = True;
+static Bool     s_new_segments_since_last_merge;
+static int      s_segment_merge_interval = 10;
+
+
+/* Function definitions. */
+
+/** Enables/disables context switch tracing. */
+void DRD_(thread_trace_context_switches)(const Bool t)
+{
+   tl_assert(t == False || t == True);
+   s_trace_context_switches = t;
+}
+
+/** Enables/disables conflict set tracing. */
+void DRD_(thread_trace_conflict_set)(const Bool t)
+{
+   tl_assert(t == False || t == True);
+   s_trace_conflict_set = t;
+}
+
+/** Enables/disables conflict set bitmap tracing. */
+void DRD_(thread_trace_conflict_set_bm)(const Bool t)
+{
+   tl_assert(t == False || t == True);
+   s_trace_conflict_set_bm = t;
+}
+
+/** Report whether fork/join tracing is enabled. */
+Bool DRD_(thread_get_trace_fork_join)(void)
+{
+   return s_trace_fork_join;
+}
+
+/** Enables/disables fork/join tracing. */
+void DRD_(thread_set_trace_fork_join)(const Bool t)
+{
+   tl_assert(t == False || t == True);
+   s_trace_fork_join = t;
+}
+
+/** Enables/disables segment merging. */
+void DRD_(thread_set_segment_merging)(const Bool m)
+{
+   tl_assert(m == False || m == True);
+   s_segment_merging = m;
+}
+
+/** Get the segment merging interval. */
+int DRD_(thread_get_segment_merge_interval)(void)
+{
+   return s_segment_merge_interval;
+}
+
+/** Set the segment merging interval. */
+void DRD_(thread_set_segment_merge_interval)(const int i)
+{
+   s_segment_merge_interval = i;
+}
+
+/**
+ * Convert Valgrind's ThreadId into a DrdThreadId.
+ *
+ * @return DRD thread ID upon success and DRD_INVALID_THREADID if the passed
+ *         Valgrind ThreadId does not yet exist.
+ */
+DrdThreadId DRD_(VgThreadIdToDrdThreadId)(const ThreadId tid)
+{
+   int i;
+
+   if (tid == VG_INVALID_THREADID)
+      return DRD_INVALID_THREADID;
+
+   for (i = 1; i < DRD_N_THREADS; i++)
+   {
+      if (DRD_(g_threadinfo)[i].vg_thread_exists == True
+          && DRD_(g_threadinfo)[i].vg_threadid == tid)
+      {
+         return i;
+      }
+   }
+
+   return DRD_INVALID_THREADID;
+}
+
+/** Allocate a new DRD thread ID for the specified Valgrind thread ID. */
+static DrdThreadId DRD_(VgThreadIdToNewDrdThreadId)(const ThreadId tid)
+{
+   int i;
+
+   tl_assert(DRD_(VgThreadIdToDrdThreadId)(tid) == DRD_INVALID_THREADID);
+
+   for (i = 1; i < DRD_N_THREADS; i++)
+   {
+      if (DRD_(g_threadinfo)[i].vg_thread_exists == False
+          && DRD_(g_threadinfo)[i].posix_thread_exists == False
+          && DRD_(g_threadinfo)[i].detached_posix_thread == False)
+      {
+         tl_assert(! DRD_(IsValidDrdThreadId)(i));
+
+         DRD_(g_threadinfo)[i].vg_thread_exists = True;
+         DRD_(g_threadinfo)[i].vg_threadid   = tid;
+         DRD_(g_threadinfo)[i].pt_threadid   = INVALID_POSIX_THREADID;
+         DRD_(g_threadinfo)[i].stack_min     = 0;
+         DRD_(g_threadinfo)[i].stack_min_min = 0;
+         DRD_(g_threadinfo)[i].stack_startup = 0;
+         DRD_(g_threadinfo)[i].stack_max     = 0;
+         DRD_(thread_set_name)(i, "");
+         DRD_(g_threadinfo)[i].on_alt_stack        = False;
+         DRD_(g_threadinfo)[i].is_recording_loads  = True;
+         DRD_(g_threadinfo)[i].is_recording_stores = True;
+         DRD_(g_threadinfo)[i].pthread_create_nesting_level = 0;
+         DRD_(g_threadinfo)[i].synchr_nesting = 0;
+         tl_assert(DRD_(g_threadinfo)[i].first == 0);
+         tl_assert(DRD_(g_threadinfo)[i].last == 0);
+
+         tl_assert(DRD_(IsValidDrdThreadId)(i));
+
+         return i;
+      }
+   }
+
+   VG_(printf)(
+"\nSorry, but the maximum number of threads supported by DRD has been exceeded."
+"Aborting.\n");
+
+   tl_assert(False);
+
+   return DRD_INVALID_THREADID;
+}
+
+/** Convert a POSIX thread ID into a DRD thread ID. */
+DrdThreadId DRD_(PtThreadIdToDrdThreadId)(const PThreadId tid)
+{
+   int i;
+
+   if (tid != INVALID_POSIX_THREADID)
+   {
+      for (i = 1; i < DRD_N_THREADS; i++)
+      {
+         if (DRD_(g_threadinfo)[i].posix_thread_exists
+             && DRD_(g_threadinfo)[i].pt_threadid == tid)
+         {
+            return i;
+         }
+      }
+   }
+   return DRD_INVALID_THREADID;
+}
+
+/** Convert a DRD thread ID into a Valgrind thread ID. */
+ThreadId DRD_(DrdThreadIdToVgThreadId)(const DrdThreadId tid)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+
+   return (DRD_(g_threadinfo)[tid].vg_thread_exists
+           ? DRD_(g_threadinfo)[tid].vg_threadid
+           : VG_INVALID_THREADID);
+}
+
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+/**
+ * Sanity check of the doubly linked list of segments referenced by a
+ * ThreadInfo struct.
+ * @return True if sane, False if not.
+ */
+static Bool DRD_(sane_ThreadInfo)(const ThreadInfo* const ti)
+{
+   Segment* p;
+
+   for (p = ti->first; p; p = p->next) {
+      if (p->next && p->next->prev != p)
+         return False;
+      if (p->next == 0 && p != ti->last)
+         return False;
+   }
+   for (p = ti->last; p; p = p->prev) {
+      if (p->prev && p->prev->next != p)
+         return False;
+      if (p->prev == 0 && p != ti->first)
+         return False;
+   }
+   return True;
+}
+#endif
+
+/**
+ * Create the first segment for a newly started thread.
+ *
+ * This function is called from the handler installed via
+ * VG_(track_pre_thread_ll_create)(). The Valgrind core invokes this handler
+ * from the context of the creator thread, before the new thread has been
+ * created.
+ *
+ * @param[in] creator    DRD thread ID of the creator thread.
+ * @param[in] vg_created Valgrind thread ID of the created thread.
+ *
+ * @return DRD thread ID of the created thread.
+ */
+DrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator,
+                                    const ThreadId vg_created)
+{
+   DrdThreadId created;
+
+   tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_created) == DRD_INVALID_THREADID);
+   created = DRD_(VgThreadIdToNewDrdThreadId)(vg_created);
+   tl_assert(0 <= (int)created && created < DRD_N_THREADS
+             && created != DRD_INVALID_THREADID);
+
+   tl_assert(DRD_(g_threadinfo)[created].first == 0);
+   tl_assert(DRD_(g_threadinfo)[created].last == 0);
+   /* Create an initial segment for the newly created thread. */
+   thread_append_segment(created, DRD_(sg_new)(creator, created));
+
+   return created;
+}
+
+/**
+ * Initialize DRD_(g_threadinfo)[] for a newly created thread. Must be called
+ * after the thread has been created and before any client instructions are run
+ * on the newly created thread, e.g. from the handler installed via
+ * VG_(track_pre_thread_first_insn)().
+ *
+ * @param[in] vg_created Valgrind thread ID of the newly created thread.
+ *
+ * @return DRD thread ID for the new thread.
+ */
+DrdThreadId DRD_(thread_post_create)(const ThreadId vg_created)
+{
+   const DrdThreadId created = DRD_(VgThreadIdToDrdThreadId)(vg_created);
+
+   tl_assert(0 <= (int)created && created < DRD_N_THREADS
+             && created != DRD_INVALID_THREADID);
+
+   DRD_(g_threadinfo)[created].stack_max
+      = VG_(thread_get_stack_max)(vg_created);
+   DRD_(g_threadinfo)[created].stack_startup
+      = DRD_(g_threadinfo)[created].stack_max;
+   DRD_(g_threadinfo)[created].stack_min
+      = DRD_(g_threadinfo)[created].stack_max;
+   DRD_(g_threadinfo)[created].stack_min_min
+      = DRD_(g_threadinfo)[created].stack_max;
+   DRD_(g_threadinfo)[created].stack_size
+      = VG_(thread_get_stack_size)(vg_created);
+   tl_assert(DRD_(g_threadinfo)[created].stack_max != 0);
+
+   return created;
+}
+
+/**
+ * Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just
+ * after thread drd_joiner joined thread drd_joinee.
+ */
+void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
+{
+   tl_assert(DRD_(IsValidDrdThreadId)(drd_joiner));
+   tl_assert(DRD_(IsValidDrdThreadId)(drd_joinee));
+
+   DRD_(thread_new_segment)(drd_joiner);
+   DRD_(thread_combine_vc_join)(drd_joiner, drd_joinee);
+   DRD_(thread_new_segment)(drd_joinee);
+
+   if (s_trace_fork_join)
+   {
+      const ThreadId joiner = DRD_(DrdThreadIdToVgThreadId)(drd_joiner);
+      const unsigned msg_size = 256;
+      char* msg;
+
+      msg = VG_(malloc)("drd.main.dptj.1", msg_size);
+      tl_assert(msg);
+      VG_(snprintf)(msg, msg_size,
+                    "drd_post_thread_join joiner = %d, joinee = %d",
+                    drd_joiner, drd_joinee);
+      if (joiner)
+      {
+         char* vc;
+
+         vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(drd_joiner));
+         VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg),
+                       ", new vc: %s", vc);
+         VG_(free)(vc);
+      }
+      VG_(message)(Vg_DebugMsg, "%s\n", msg);
+      VG_(free)(msg);
+   }
+
+   if (!  DRD_(get_check_stack_accesses)())
+   {
+      DRD_(finish_suppression)(DRD_(thread_get_stack_max)(drd_joinee)
+                               - DRD_(thread_get_stack_size)(drd_joinee),
+                               DRD_(thread_get_stack_max)(drd_joinee));
+   }
+   DRD_(clientobj_delete_thread)(drd_joinee);
+   DRD_(thread_delete)(drd_joinee);
+}
+
+/**
+ * NPTL hack: NPTL allocates the 'struct pthread' on top of the stack,
+ * and accesses this data structure from multiple threads without locking.
+ * Any conflicting accesses in the range stack_startup..stack_max will be
+ * ignored.
+ */
+void DRD_(thread_set_stack_startup)(const DrdThreadId tid,
+                                    const Addr stack_startup)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   tl_assert(DRD_(g_threadinfo)[tid].stack_min <= stack_startup);
+   tl_assert(stack_startup <= DRD_(g_threadinfo)[tid].stack_max);
+   DRD_(g_threadinfo)[tid].stack_startup = stack_startup;
+}
+
+/** Return the stack pointer for the specified thread. */
+Addr DRD_(thread_get_stack_min)(const DrdThreadId tid)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   return DRD_(g_threadinfo)[tid].stack_min;
+}
+
+/**
+ * Return the lowest value that was ever assigned to the stack pointer
+ * for the specified thread.
+ */
+Addr DRD_(thread_get_stack_min_min)(const DrdThreadId tid)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   return DRD_(g_threadinfo)[tid].stack_min_min;
+}
+
+/** Return the top address for the stack of the specified thread. */
+Addr DRD_(thread_get_stack_max)(const DrdThreadId tid)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   return DRD_(g_threadinfo)[tid].stack_max;
+}
+
+/** Return the maximum stack size for the specified thread. */
+SizeT DRD_(thread_get_stack_size)(const DrdThreadId tid)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   return DRD_(g_threadinfo)[tid].stack_size;
+}
+
+Bool DRD_(thread_get_on_alt_stack)(const DrdThreadId tid)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   return DRD_(g_threadinfo)[tid].on_alt_stack;
+}
+
+void DRD_(thread_set_on_alt_stack)(const DrdThreadId tid,
+                                   const Bool on_alt_stack)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   tl_assert(on_alt_stack == !!on_alt_stack);
+   DRD_(g_threadinfo)[tid].on_alt_stack = on_alt_stack;
+}
+
+Int DRD_(thread_get_threads_on_alt_stack)(void)
+{
+   int i, n = 0;
+
+   for (i = 1; i < DRD_N_THREADS; i++)
+      n += DRD_(g_threadinfo)[i].on_alt_stack;
+   return n;
+}
+
+/**
+ * Clean up thread-specific data structures. Call this just after
+ * pthread_join().
+ */
+void DRD_(thread_delete)(const DrdThreadId tid)
+{
+   Segment* sg;
+   Segment* sg_prev;
+
+   tl_assert(DRD_(IsValidDrdThreadId)(tid));
+
+   tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 0);
+   for (sg = DRD_(g_threadinfo)[tid].last; sg; sg = sg_prev)
+   {
+      sg_prev = sg->prev;
+      sg->prev = 0;
+      sg->next = 0;
+      DRD_(sg_put)(sg);
+   }
+   DRD_(g_threadinfo)[tid].vg_thread_exists = False;
+   DRD_(g_threadinfo)[tid].posix_thread_exists = False;
+   tl_assert(DRD_(g_threadinfo)[tid].detached_posix_thread == False);
+   DRD_(g_threadinfo)[tid].first = 0;
+   DRD_(g_threadinfo)[tid].last = 0;
+
+   tl_assert(! DRD_(IsValidDrdThreadId)(tid));
+}
+
+/**
+ * Called after a thread performed its last memory access and before
+ * thread_delete() is called. Note: thread_delete() is only called for
+ * joinable threads, not for detached threads.
+ */
+void DRD_(thread_finished)(const DrdThreadId tid)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+
+   DRD_(g_threadinfo)[tid].vg_thread_exists = False;
+
+   if (DRD_(g_threadinfo)[tid].detached_posix_thread)
+   {
+      /*
+       * Once a detached thread has finished, its stack is deallocated and
+       * should no longer be taken into account when computing the conflict set.
+       */
+      DRD_(g_threadinfo)[tid].stack_min = DRD_(g_threadinfo)[tid].stack_max;
+
+      /*
+       * For a detached thread, calling pthread_exit() invalidates the
+       * POSIX thread ID associated with the detached thread. For joinable
+       * POSIX threads however, the POSIX thread ID remains live after the
+       * pthread_exit() call until pthread_join() is called.
+       */
+      DRD_(g_threadinfo)[tid].posix_thread_exists = False;
+   }
+}
+
+/** Called just before pthread_cancel(). */
+void DRD_(thread_pre_cancel)(const DrdThreadId tid)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
+
+   DRD_(g_threadinfo)[tid].synchr_nesting = 0;
+}
+
+/**
+ * Store the POSIX thread ID for the specified thread.
+ *
+ * @note This function can be called two times for the same thread -- see also
+ * the comment block preceding the pthread_create() wrapper in
+ * drd_pthread_intercepts.c.
+ */
+void DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   tl_assert(DRD_(g_threadinfo)[tid].pt_threadid == INVALID_POSIX_THREADID
+             || DRD_(g_threadinfo)[tid].pt_threadid == ptid);
+   tl_assert(ptid != INVALID_POSIX_THREADID);
+   DRD_(g_threadinfo)[tid].posix_thread_exists = True;
+   DRD_(g_threadinfo)[tid].pt_threadid         = ptid;
+}
+
+/** Returns true for joinable threads and false for detached threads. */
+Bool DRD_(thread_get_joinable)(const DrdThreadId tid)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   return ! DRD_(g_threadinfo)[tid].detached_posix_thread;
+}
+
+/** Store the thread mode: joinable or detached. */
+void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   tl_assert(!! joinable == joinable);
+   tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
+
+   DRD_(g_threadinfo)[tid].detached_posix_thread = ! joinable;
+}
+
+/** Tells DRD that the calling thread is about to enter pthread_create(). */
+void DRD_(thread_entering_pthread_create)(const DrdThreadId tid)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
+   tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level >= 0);
+
+   DRD_(g_threadinfo)[tid].pthread_create_nesting_level++;
+}
+
+/** Tells DRD that the calling thread has left pthread_create(). */
+void DRD_(thread_left_pthread_create)(const DrdThreadId tid)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   tl_assert(DRD_(g_threadinfo)[tid].pt_threadid != INVALID_POSIX_THREADID);
+   tl_assert(DRD_(g_threadinfo)[tid].pthread_create_nesting_level > 0);
+
+   DRD_(g_threadinfo)[tid].pthread_create_nesting_level--;
+}
+
+/** Obtain the thread number and the user-assigned thread name. */
+const char* DRD_(thread_get_name)(const DrdThreadId tid)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+
+   return DRD_(g_threadinfo)[tid].name;
+}
+
+/** Set the name of the specified thread. */
+void DRD_(thread_set_name)(const DrdThreadId tid, const char* const name)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+
+   if (name == NULL || name[0] == 0)
+      VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
+                    sizeof(DRD_(g_threadinfo)[tid].name),
+                    "Thread %d",
+                    tid);
+   else
+      VG_(snprintf)(DRD_(g_threadinfo)[tid].name,
+                    sizeof(DRD_(g_threadinfo)[tid].name),
+                    "Thread %d (%s)",
+                    tid, name);
+   DRD_(g_threadinfo)[tid].name[sizeof(DRD_(g_threadinfo)[tid].name) - 1] = 0;
+}
+
+/**
+ * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
+ * conflict set.
+ */
+void DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid)
+{
+   tl_assert(vg_tid != VG_INVALID_THREADID);
+
+   if (vg_tid != s_vg_running_tid)
+   {
+      DRD_(thread_set_running_tid)(vg_tid,
+                                   DRD_(VgThreadIdToDrdThreadId)(vg_tid));
+   }
+
+   tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
+   tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
+}
+
+/**
+ * Update s_vg_running_tid, DRD_(g_drd_running_tid) and recalculate the
+ * conflict set.
+ */
+void DRD_(thread_set_running_tid)(const ThreadId vg_tid,
+                                  const DrdThreadId drd_tid)
+{
+   tl_assert(vg_tid != VG_INVALID_THREADID);
+   tl_assert(drd_tid != DRD_INVALID_THREADID);
+
+   if (vg_tid != s_vg_running_tid)
+   {
+      if (s_trace_context_switches
+          && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID)
+      {
+         VG_(message)(Vg_DebugMsg,
+                      "Context switch from thread %d to thread %d;"
+                      " segments: %llu\n",
+                      DRD_(g_drd_running_tid), drd_tid,
+                      DRD_(sg_get_segments_alive_count)());
+      }
+      s_vg_running_tid = vg_tid;
+      DRD_(g_drd_running_tid) = drd_tid;
+      thread_compute_conflict_set(&DRD_(g_conflict_set), drd_tid);
+      s_context_switch_count++;
+   }
+
+   tl_assert(s_vg_running_tid != VG_INVALID_THREADID);
+   tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
+}
+
+/**
+ * Increase the synchronization nesting counter. Must be called before the
+ * client calls a synchronization function.
+ */
+int DRD_(thread_enter_synchr)(const DrdThreadId tid)
+{
+   tl_assert(DRD_(IsValidDrdThreadId)(tid));
+   return DRD_(g_threadinfo)[tid].synchr_nesting++;
+}
+
+/**
+ * Decrease the synchronization nesting counter. Must be called after the
+ * client left a synchronization function.
+ */
+int DRD_(thread_leave_synchr)(const DrdThreadId tid)
+{
+   tl_assert(DRD_(IsValidDrdThreadId)(tid));
+   tl_assert(DRD_(g_threadinfo)[tid].synchr_nesting >= 1);
+   return --DRD_(g_threadinfo)[tid].synchr_nesting;
+}
+
+/** Returns the synchronization nesting counter. */
+int DRD_(thread_get_synchr_nesting_count)(const DrdThreadId tid)
+{
+   tl_assert(DRD_(IsValidDrdThreadId)(tid));
+   return DRD_(g_threadinfo)[tid].synchr_nesting;
+}
+
+/** Append a new segment at the end of the segment list. */
+static
+void thread_append_segment(const DrdThreadId tid, Segment* const sg)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
+#endif
+
+   sg->prev = DRD_(g_threadinfo)[tid].last;
+   sg->next = 0;
+   if (DRD_(g_threadinfo)[tid].last)
+      DRD_(g_threadinfo)[tid].last->next = sg;
+   DRD_(g_threadinfo)[tid].last = sg;
+   if (DRD_(g_threadinfo)[tid].first == 0)
+      DRD_(g_threadinfo)[tid].first = sg;
+
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
+#endif
+}
+
+/**
+ * Remove a segment from the segment list of thread threadid, and free the
+ * associated memory.
+ */
+static
+void thread_discard_segment(const DrdThreadId tid, Segment* const sg)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
+#endif
+
+   if (sg->prev)
+      sg->prev->next = sg->next;
+   if (sg->next)
+      sg->next->prev = sg->prev;
+   if (sg == DRD_(g_threadinfo)[tid].first)
+      DRD_(g_threadinfo)[tid].first = sg->next;
+   if (sg == DRD_(g_threadinfo)[tid].last)
+      DRD_(g_threadinfo)[tid].last = sg->prev;
+   DRD_(sg_put)(sg);
+
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[tid]));
+#endif
+}
+
+/**
+ * Returns a pointer to the vector clock of the most recent segment associated
+ * with thread 'tid'.
+ */
+VectorClock* DRD_(thread_get_vc)(const DrdThreadId tid)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   tl_assert(DRD_(g_threadinfo)[tid].last);
+   return &DRD_(g_threadinfo)[tid].last->vc;
+}
+
+/**
+ * Return the latest segment of thread 'tid' and increment its reference count.
+ */
+void DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid)
+{
+   tl_assert(sg);
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   tl_assert(DRD_(g_threadinfo)[tid].last);
+
+   DRD_(sg_put)(*sg);
+   *sg = DRD_(sg_get)(DRD_(g_threadinfo)[tid].last);
+}
+
+/**
+ * Compute the minimum of all latest vector clocks of all threads
+ * (Michiel Ronsse calls this "clock snooping" in his papers about DIOTA).
+ *
+ * @param vc pointer to a vectorclock, holds result upon return.
+ */
+static void DRD_(thread_compute_minimum_vc)(VectorClock* vc)
+{
+   unsigned i;
+   Bool first;
+   Segment* latest_sg;
+
+   first = True;
+   for (i = 0; i < DRD_N_THREADS; i++)
+   {
+      latest_sg = DRD_(g_threadinfo)[i].last;
+      if (latest_sg)
+      {
+         if (first)
+            DRD_(vc_assign)(vc, &latest_sg->vc);
+         else
+            DRD_(vc_min)(vc, &latest_sg->vc);
+         first = False;
+      }
+   }
+}
+
+/**
+ * Compute the maximum of all latest vector clocks of all threads.
+ *
+ * @param vc pointer to a vectorclock, holds result upon return.
+ */
+static void DRD_(thread_compute_maximum_vc)(VectorClock* vc)
+{
+   unsigned i;
+   Bool first;
+   Segment* latest_sg;
+
+   first = True;
+   for (i = 0; i < DRD_N_THREADS; i++)
+   {
+      latest_sg = DRD_(g_threadinfo)[i].last;
+      if (latest_sg)
+      {
+         if (first)
+            DRD_(vc_assign)(vc, &latest_sg->vc);
+         else
+            DRD_(vc_combine)(vc, &latest_sg->vc);
+         first = False;
+      }
+   }
+}
+
+/**
+ * Discard all segments that have a defined order against the latest vector
+ * clock of all threads -- these segments can no longer be involved in a
+ * data race.
+ */
+static void thread_discard_ordered_segments(void)
+{
+   unsigned i;
+   VectorClock thread_vc_min;
+
+   s_discard_ordered_segments_count++;
+
+   DRD_(vc_init)(&thread_vc_min, 0, 0);
+   DRD_(thread_compute_minimum_vc)(&thread_vc_min);
+   if (DRD_(sg_get_trace)())
+   {
+      char *vc_min, *vc_max;
+      VectorClock thread_vc_max;
+
+      DRD_(vc_init)(&thread_vc_max, 0, 0);
+      DRD_(thread_compute_maximum_vc)(&thread_vc_max);
+      vc_min = DRD_(vc_aprint)(&thread_vc_min);
+      vc_max = DRD_(vc_aprint)(&thread_vc_max);
+      VG_(message)(Vg_DebugMsg,
+                   "Discarding ordered segments -- min vc is %s, max vc is %s\n",
+                   vc_min, vc_max);
+      VG_(free)(vc_min);
+      VG_(free)(vc_max);
+      DRD_(vc_cleanup)(&thread_vc_max);
+   }
+
+   for (i = 0; i < DRD_N_THREADS; i++)
+   {
+      Segment* sg;
+      Segment* sg_next;
+      for (sg = DRD_(g_threadinfo)[i].first;
+           sg && (sg_next = sg->next) && DRD_(vc_lte)(&sg->vc, &thread_vc_min);
+           sg = sg_next)
+      {
+         thread_discard_segment(i, sg);
+      }
+   }
+   DRD_(vc_cleanup)(&thread_vc_min);
+}
+
+/**
+ * An implementation of the property 'equiv(sg1, sg2)' as defined in the paper
+ * by Mark Christiaens e.a. The property equiv(sg1, sg2) holds if and only if
+ * all segments in the set CS are ordered consistently against both sg1 and
+ * sg2. The set CS is defined as the set of segments that can immediately
+ * precede future segments via inter-thread synchronization operations. In
+ * DRD the set CS consists of the latest segment of each thread combined with
+ * all segments for which the reference count is strictly greater than one.
+ * The code below is an optimized version of the following:
+ *
+ * for (i = 0; i < DRD_N_THREADS; i++)
+ * {
+ *    Segment* sg;
+ *
+ *    for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
+ *    {
+ *       if (sg == DRD_(g_threadinfo)[i].last || DRD_(sg_get_refcnt)(sg) > 1)
+ *       {
+ *          if (   DRD_(vc_lte)(&sg1->vc, &sg->vc)
+ *              != DRD_(vc_lte)(&sg2->vc, &sg->vc)
+ *              || DRD_(vc_lte)(&sg->vc, &sg1->vc)
+ *              != DRD_(vc_lte)(&sg->vc, &sg2->vc))
+ *          {
+ *             return False;
+ *          }
+ *       }
+ *    }
+ * }
+ */
+static Bool thread_consistent_segment_ordering(const DrdThreadId tid,
+                                               Segment* const sg1,
+                                               Segment* const sg2)
+{
+   unsigned i;
+
+   tl_assert(sg1->next);
+   tl_assert(sg2->next);
+   tl_assert(sg1->next == sg2);
+   tl_assert(DRD_(vc_lte)(&sg1->vc, &sg2->vc));
+
+   for (i = 0; i < DRD_N_THREADS; i++)
+   {
+      Segment* sg;
+
+      for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
+      {
+         if (! sg->next || DRD_(sg_get_refcnt)(sg) > 1)
+         {
+            if (DRD_(vc_lte)(&sg2->vc, &sg->vc))
+               break;
+            if (DRD_(vc_lte)(&sg1->vc, &sg->vc))
+               return False;
+         }
+      }
+      for (sg = DRD_(g_threadinfo)[i].last; sg; sg = sg->prev)
+      {
+         if (! sg->next || DRD_(sg_get_refcnt)(sg) > 1)
+         {
+            if (DRD_(vc_lte)(&sg->vc, &sg1->vc))
+               break;
+            if (DRD_(vc_lte)(&sg->vc, &sg2->vc))
+               return False;
+         }
+      }
+   }
+   return True;
+}
+
+/**
+ * Merge all segments that may be merged without triggering false positives
+ * or discarding real data races. For the theoretical background of segment
+ * merging, see also the following paper: Mark Christiaens, Michiel Ronsse
+ * and Koen De Bosschere. Bounding the number of segment histories during
+ * data race detection. Parallel Computing archive, Volume 28, Issue 9,
+ * pp 1221-1238, September 2002. This paper contains a proof that merging
+ * consecutive segments for which the property equiv(s1,s2) holds can be
+ * merged without reducing the accuracy of datarace detection. Furthermore
+ * it is also proven that the total number of all segments will never grow
+ * unbounded if all segments s1, s2 for which equiv(s1, s2) holds are merged
+ * every time a new segment is created. The property equiv(s1, s2) is defined
+ * as follows: equiv(s1, s2) <=> for all segments in the set CS, the vector
+ * clocks of segments s and s1 are ordered in the same way as those of segments
+ * s and s2. The set CS is defined as the set of existing segments s that have
+ * the potential to conflict with not yet created segments, either because the
+ * segment s is the latest segment of a thread or because it can become the
+ * immediate predecessor of a new segment due to a synchronization operation.
+ */
+static void thread_merge_segments(void)
+{
+   unsigned i;
+
+   s_new_segments_since_last_merge = 0;
+
+   for (i = 0; i < DRD_N_THREADS; i++)
+   {
+      Segment* sg;
+
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+      tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
+#endif
+
+      for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
+      {
+         if (DRD_(sg_get_refcnt)(sg) == 1
+             && sg->next
+             && DRD_(sg_get_refcnt)(sg->next) == 1
+             && sg->next->next
+             && thread_consistent_segment_ordering(i, sg, sg->next))
+         {
+            /* Merge sg and sg->next into sg. */
+            DRD_(sg_merge)(sg, sg->next);
+            thread_discard_segment(i, sg->next);
+         }
+      }
+
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+      tl_assert(DRD_(sane_ThreadInfo)(&DRD_(g_threadinfo)[i]));
+#endif
+   }
+}
+
+/**
+ * Create a new segment for the specified thread, and discard any segments
+ * that cannot cause races anymore.
+ */
+void DRD_(thread_new_segment)(const DrdThreadId tid)
+{
+   Segment* last_sg;
+   Segment* new_sg;
+
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
+
+   last_sg = DRD_(g_threadinfo)[tid].last;
+   new_sg = DRD_(sg_new)(tid, tid);
+   thread_append_segment(tid, new_sg);
+   if (tid == DRD_(g_drd_running_tid) && last_sg)
+   {
+      DRD_(thread_update_conflict_set)(tid, &last_sg->vc);
+      s_update_conflict_set_new_sg_count++;
+   }
+
+   tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
+
+   if (s_segment_merging
+       && ++s_new_segments_since_last_merge >= s_segment_merge_interval)
+   {
+      thread_discard_ordered_segments();
+      thread_merge_segments();
+   }
+}
+
+/** Call this function after thread 'joiner' joined thread 'joinee'. */
+void DRD_(thread_combine_vc_join)(DrdThreadId joiner, DrdThreadId joinee)
+{
+   tl_assert(joiner != joinee);
+   tl_assert(0 <= (int)joiner && joiner < DRD_N_THREADS
+             && joiner != DRD_INVALID_THREADID);
+   tl_assert(0 <= (int)joinee && joinee < DRD_N_THREADS
+             && joinee != DRD_INVALID_THREADID);
+   tl_assert(DRD_(g_threadinfo)[joiner].last);
+   tl_assert(DRD_(g_threadinfo)[joinee].last);
+
+   if (DRD_(sg_get_trace)())
+   {
+      char *str1, *str2;
+      str1 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joiner].last->vc);
+      str2 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joinee].last->vc);
+      VG_(message)(Vg_DebugMsg, "Before join: joiner %s, joinee %s\n",
+                   str1, str2);
+      VG_(free)(str1);
+      VG_(free)(str2);
+   }
+   if (joiner == DRD_(g_drd_running_tid))
+   {
+      VectorClock old_vc;
+
+      DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[joiner].last->vc);
+      DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc,
+                       &DRD_(g_threadinfo)[joinee].last->vc);
+      DRD_(thread_update_conflict_set)(joiner, &old_vc);
+      s_update_conflict_set_join_count++;
+      DRD_(vc_cleanup)(&old_vc);
+   }
+   else
+   {
+      DRD_(vc_combine)(&DRD_(g_threadinfo)[joiner].last->vc,
+                       &DRD_(g_threadinfo)[joinee].last->vc);
+   }
+
+   thread_discard_ordered_segments();
+
+   if (DRD_(sg_get_trace)())
+   {
+      char* str;
+      str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[joiner].last->vc);
+      VG_(message)(Vg_DebugMsg, "After join: %s\n", str);
+      VG_(free)(str);
+   }
+}
+
+/**
+ * Update the vector clock of the last segment of thread tid with the
+ * the vector clock of segment sg.
+ */
+static void thread_combine_vc_sync(DrdThreadId tid, const Segment* sg)
+{
+   const VectorClock* const vc = &sg->vc;
+
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   tl_assert(DRD_(g_threadinfo)[tid].last);
+   tl_assert(sg);
+   tl_assert(vc);
+
+   if (tid != sg->tid)
+   {
+      VectorClock old_vc;
+
+      DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[tid].last->vc);
+      DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, vc);
+      if (DRD_(sg_get_trace)())
+      {
+         char *str1, *str2;
+         str1 = DRD_(vc_aprint)(&old_vc);
+         str2 = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
+         VG_(message)(Vg_DebugMsg, "thread %d: vc %s -> %s\n", tid, str1, str2);
+         VG_(free)(str1);
+         VG_(free)(str2);
+      }
+
+      thread_discard_ordered_segments();
+
+      DRD_(thread_update_conflict_set)(tid, &old_vc);
+      s_update_conflict_set_sync_count++;
+
+      DRD_(vc_cleanup)(&old_vc);
+   }
+   else
+   {
+      tl_assert(DRD_(vc_lte)(vc, &DRD_(g_threadinfo)[tid].last->vc));
+   }
+}
+
+/**
+ * Create a new segment for thread tid and update the vector clock of the last
+ * segment of this thread with the the vector clock of segment sg. Call this
+ * function after thread tid had to wait because of thread synchronization
+ * until the memory accesses in the segment sg finished.
+ */
+void DRD_(thread_new_segment_and_combine_vc)(DrdThreadId tid, const Segment* sg)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
+   tl_assert(sg);
+
+   thread_append_segment(tid, DRD_(sg_new)(tid, tid));
+
+   thread_combine_vc_sync(tid, sg);
+
+   if (s_segment_merging
+       && ++s_new_segments_since_last_merge >= s_segment_merge_interval)
+   {
+      thread_discard_ordered_segments();
+      thread_merge_segments();
+   }
+}
+
+/**
+ * Call this function whenever a thread is no longer using the memory
+ * [ a1, a2 [, e.g. because of a call to free() or a stack pointer
+ * increase.
+ */
+void DRD_(thread_stop_using_mem)(const Addr a1, const Addr a2,
+                                 const Bool dont_clear_access)
+{
+   DrdThreadId other_user;
+   unsigned i;
+
+   /* For all threads, mark the range [ a1, a2 [ as no longer in use. */
+   other_user = DRD_INVALID_THREADID;
+   for (i = 0; i < DRD_N_THREADS; i++)
+   {
+      Segment* p;
+      for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
+      {
+         if (other_user == DRD_INVALID_THREADID
+             && i != DRD_(g_drd_running_tid))
+         {
+            if (UNLIKELY((!dont_clear_access
+                          && DRD_(bm_test_and_clear)(DRD_(sg_bm)(p), a1, a2))
+                         || (dont_clear_access
+                             && DRD_(bm_has_any_access)(DRD_(sg_bm)(p), a1, a2))
+                         ))
+            {
+               other_user = i;
+            }
+            continue;
+         }
+         if (!dont_clear_access)
+            DRD_(bm_clear)(DRD_(sg_bm)(p), a1, a2);
+      }
+   }
+
+   /*
+    * If any other thread had accessed memory in [ a1, a2 [, update the
+    * conflict set.
+    */
+   if (other_user != DRD_INVALID_THREADID
+       && DRD_(bm_has_any_access)(DRD_(g_conflict_set), a1, a2))
+   {
+      thread_compute_conflict_set(&DRD_(g_conflict_set),
+                                  DRD_(thread_get_running_tid)());
+   }
+}
+
+/** Specify whether memory loads should be recorded. */
+void DRD_(thread_set_record_loads)(const DrdThreadId tid, const Bool enabled)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   tl_assert(enabled == !! enabled);
+
+   DRD_(g_threadinfo)[tid].is_recording_loads = enabled;
+}
+
+/** Specify whether memory stores should be recorded. */
+void DRD_(thread_set_record_stores)(const DrdThreadId tid, const Bool enabled)
+{
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   tl_assert(enabled == !! enabled);
+
+   DRD_(g_threadinfo)[tid].is_recording_stores = enabled;
+}
+
+/**
+ * Print the segment information for all threads.
+ *
+ * This function is only used for debugging purposes.
+ */
+void DRD_(thread_print_all)(void)
+{
+   unsigned i;
+   Segment* p;
+
+   for (i = 0; i < DRD_N_THREADS; i++)
+   {
+      if (DRD_(g_threadinfo)[i].first)
+      {
+         VG_(printf)("**************\n"
+                     "* thread %3d (%d/%d/%d/0x%lx/%d) *\n"
+                     "**************\n",
+                     i,
+                     DRD_(g_threadinfo)[i].vg_thread_exists,
+                     DRD_(g_threadinfo)[i].vg_threadid,
+                     DRD_(g_threadinfo)[i].posix_thread_exists,
+                     DRD_(g_threadinfo)[i].pt_threadid,
+                     DRD_(g_threadinfo)[i].detached_posix_thread);
+         for (p = DRD_(g_threadinfo)[i].first; p; p = p->next)
+         {
+            DRD_(sg_print)(p);
+         }
+      }
+   }
+}
+
+/** Show a call stack involved in a data race. */
+static void show_call_stack(const DrdThreadId tid,
+                            const Char* const msg,
+                            ExeContext* const callstack)
+{
+   const ThreadId vg_tid = DRD_(DrdThreadIdToVgThreadId)(tid);
+
+   VG_(message)(Vg_UserMsg, "%s (thread %d)\n", msg, tid);
+
+   if (vg_tid != VG_INVALID_THREADID)
+   {
+      if (callstack)
+      {
+         VG_(pp_ExeContext)(callstack);
+      }
+      else
+      {
+         VG_(get_and_pp_StackTrace)(vg_tid, VG_(clo_backtrace_size));
+      }
+   }
+   else
+   {
+      VG_(message)(Vg_UserMsg,
+                   "   (thread finished, call stack no longer available)\n");
+   }
+}
+
+/** Print information about the segments involved in a data race. */
+static void
+thread_report_conflicting_segments_segment(const DrdThreadId tid,
+                                           const Addr addr,
+                                           const SizeT size,
+                                           const BmAccessTypeT access_type,
+                                           const Segment* const p)
+{
+   unsigned i;
+
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   tl_assert(p);
+
+   for (i = 0; i < DRD_N_THREADS; i++)
+   {
+      if (i != tid)
+      {
+         Segment* q;
+         for (q = DRD_(g_threadinfo)[i].last; q; q = q->prev)
+         {
+            /*
+             * Since q iterates over the segments of thread i in order of
+             * decreasing vector clocks, if q->vc <= p->vc, then
+             * q->next->vc <= p->vc will also hold. Hence, break out of the
+             * loop once this condition is met.
+             */
+            if (DRD_(vc_lte)(&q->vc, &p->vc))
+               break;
+            if (! DRD_(vc_lte)(&p->vc, &q->vc))
+            {
+               if (DRD_(bm_has_conflict_with)(DRD_(sg_bm)(q), addr, addr + size,
+                                              access_type))
+               {
+                  tl_assert(q->stacktrace);
+                  show_call_stack(i,        "Other segment start",
+                                  q->stacktrace);
+                  show_call_stack(i,        "Other segment end",
+                                  q->next ? q->next->stacktrace : 0);
+               }
+            }
+         }
+      }
+   }
+}
+
+/** Print information about all segments involved in a data race. */
+void DRD_(thread_report_conflicting_segments)(const DrdThreadId tid,
+                                              const Addr addr,
+                                              const SizeT size,
+                                              const BmAccessTypeT access_type)
+{
+   Segment* p;
+
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+
+   for (p = DRD_(g_threadinfo)[tid].first; p; p = p->next)
+   {
+      if (DRD_(bm_has)(DRD_(sg_bm)(p), addr, addr + size, access_type))
+      {
+         thread_report_conflicting_segments_segment(tid, addr, size,
+                                                    access_type, p);
+      }
+   }
+}
+
+/**
+ * Verify whether the conflict set for thread tid is up to date. Only perform
+ * the check if the environment variable DRD_VERIFY_CONFLICT_SET has been set.
+ */
+static Bool thread_conflict_set_up_to_date(const DrdThreadId tid)
+{
+   static int do_verify_conflict_set = -1;
+   Bool result;
+   struct bitmap* computed_conflict_set = 0;
+
+   if (do_verify_conflict_set < 0)
+      do_verify_conflict_set = VG_(getenv)("DRD_VERIFY_CONFLICT_SET") != 0;
+
+   if (do_verify_conflict_set == 0)
+      return True;
+
+   thread_compute_conflict_set(&computed_conflict_set, tid);
+   result = DRD_(bm_equal)(DRD_(g_conflict_set), computed_conflict_set);
+   if (! result)
+   {
+      VG_(printf)("actual conflict set:\n");
+      DRD_(bm_print)(DRD_(g_conflict_set));
+      VG_(printf)("\n");
+      VG_(printf)("computed conflict set:\n");
+      DRD_(bm_print)(computed_conflict_set);
+      VG_(printf)("\n");
+   }
+   DRD_(bm_delete)(computed_conflict_set);
+   return result;
+}
+
+/**
+ * Compute the conflict set: a bitmap that represents the union of all memory
+ * accesses of all segments that are unordered to the current segment of the
+ * thread tid.
+ */
+static void thread_compute_conflict_set(struct bitmap** conflict_set,
+                                        const DrdThreadId tid)
+{
+   Segment* p;
+
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   tl_assert(tid == DRD_(g_drd_running_tid));
+
+   s_compute_conflict_set_count++;
+   s_conflict_set_bitmap_creation_count
+      -= DRD_(bm_get_bitmap_creation_count)();
+   s_conflict_set_bitmap2_creation_count
+      -= DRD_(bm_get_bitmap2_creation_count)();
+
+   if (*conflict_set)
+   {
+      DRD_(bm_cleanup)(*conflict_set);
+      DRD_(bm_init)(*conflict_set);
+   }
+   else
+   {
+      *conflict_set = DRD_(bm_new)();
+   }
+
+   if (s_trace_conflict_set)
+   {
+      char* str;
+
+      str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
+      VG_(message)(Vg_DebugMsg,
+                   "computing conflict set for thread %d with vc %s\n",
+                   tid, str);
+      VG_(free)(str);
+   }
+
+   p = DRD_(g_threadinfo)[tid].last;
+   {
+      unsigned j;
+
+      if (s_trace_conflict_set)
+      {
+         char* vc;
+
+         vc = DRD_(vc_aprint)(&p->vc);
+         VG_(message)(Vg_DebugMsg, "conflict set: thread [%d] at vc %s\n",
+                      tid, vc);
+         VG_(free)(vc);
+      }
+
+      for (j = 0; j < DRD_N_THREADS; j++)
+      {
+         if (j != tid && DRD_(IsValidDrdThreadId)(j))
+         {
+            Segment* q;
+            for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
+            {
+               if (! DRD_(vc_lte)(&q->vc, &p->vc)
+                   && ! DRD_(vc_lte)(&p->vc, &q->vc))
+               {
+                  if (s_trace_conflict_set)
+                  {
+                     char* str;
+
+                     str = DRD_(vc_aprint)(&q->vc);
+                     VG_(message)(Vg_DebugMsg,
+                                  "conflict set: [%d] merging segment %s\n",
+                                  j, str);
+                     VG_(free)(str);
+                  }
+                  DRD_(bm_merge2)(*conflict_set, DRD_(sg_bm)(q));
+               }
+               else
+               {
+                  if (s_trace_conflict_set)
+                  {
+                     char* str;
+
+                     str = DRD_(vc_aprint)(&q->vc);
+                     VG_(message)(Vg_DebugMsg,
+                                  "conflict set: [%d] ignoring segment %s\n",
+                                  j, str);
+                     VG_(free)(str);
+                  }
+               }
+            }
+         }
+      }
+   }
+
+   s_conflict_set_bitmap_creation_count
+      += DRD_(bm_get_bitmap_creation_count)();
+   s_conflict_set_bitmap2_creation_count
+      += DRD_(bm_get_bitmap2_creation_count)();
+
+   if (s_trace_conflict_set_bm)
+   {
+      VG_(message)(Vg_DebugMsg, "[%d] new conflict set:\n", tid);
+      DRD_(bm_print)(*conflict_set);
+      VG_(message)(Vg_DebugMsg, "[%d] end of new conflict set.\n", tid);
+   }
+}
+
+/**
+ * Update the conflict set after the vector clock of thread tid has been
+ * updated from old_vc to its current value, either because a new segment has
+ * been created or because of a synchronization operation.
+ */
+void DRD_(thread_update_conflict_set)(const DrdThreadId tid,
+                                      const VectorClock* const old_vc)
+{
+   const VectorClock* new_vc;
+   Segment* p;
+   unsigned j;
+
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   tl_assert(old_vc);
+   tl_assert(tid == DRD_(g_drd_running_tid));
+   tl_assert(DRD_(g_conflict_set));
+
+   if (s_trace_conflict_set)
+   {
+      char* str;
+
+      str = DRD_(vc_aprint)(&DRD_(g_threadinfo)[tid].last->vc);
+      VG_(message)(Vg_DebugMsg,
+                   "updating conflict set for thread %d with vc %s\n",
+                   tid, str);
+      VG_(free)(str);
+   }
+
+   new_vc = &DRD_(g_threadinfo)[tid].last->vc;
+
+   DRD_(bm_unmark)(DRD_(g_conflict_set));
+
+   for (j = 0; j < DRD_N_THREADS; j++)
+   {
+      Segment* q;
+
+      if (j == tid || ! DRD_(IsValidDrdThreadId)(j))
+         continue;
+
+      for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
+      {
+         const int included_in_old_conflict_set
+            = ! DRD_(vc_lte)(&q->vc, old_vc)
+            && ! DRD_(vc_lte)(old_vc, &q->vc);
+         const int included_in_new_conflict_set
+            = ! DRD_(vc_lte)(&q->vc, new_vc)
+            && ! DRD_(vc_lte)(new_vc, &q->vc);
+         if (included_in_old_conflict_set != included_in_new_conflict_set)
+         {
+            if (s_trace_conflict_set)
+            {
+               char* str;
+
+               str = DRD_(vc_aprint)(&q->vc);
+               VG_(message)(Vg_DebugMsg,
+                            "conflict set: [%d] merging segment %s\n", j, str);
+               VG_(free)(str);
+            }
+            DRD_(bm_mark)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
+         }
+         else
+         {
+            if (s_trace_conflict_set)
+            {
+               char* str;
+
+               str = DRD_(vc_aprint)(&q->vc);
+               VG_(message)(Vg_DebugMsg,
+                            "conflict set: [%d] ignoring segment %s\n", j, str);
+               VG_(free)(str);
+            }
+         }
+      }
+   }
+
+   DRD_(bm_clear_marked)(DRD_(g_conflict_set));
+
+   p = DRD_(g_threadinfo)[tid].last;
+   {
+      for (j = 0; j < DRD_N_THREADS; j++)
+      {
+         if (j != tid && DRD_(IsValidDrdThreadId)(j))
+         {
+            Segment* q;
+            for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
+            {
+               if (! DRD_(vc_lte)(&q->vc, &p->vc)
+                   && ! DRD_(vc_lte)(&p->vc, &q->vc))
+               {
+                  DRD_(bm_merge2_marked)(DRD_(g_conflict_set), DRD_(sg_bm)(q));
+               }
+            }
+         }
+      }
+   }
+
+   DRD_(bm_remove_cleared_marked)(DRD_(g_conflict_set));
+
+   s_update_conflict_set_count++;
+
+   if (s_trace_conflict_set_bm)
+   {
+      VG_(message)(Vg_DebugMsg, "[%d] updated conflict set:\n", tid);
+      DRD_(bm_print)(DRD_(g_conflict_set));
+      VG_(message)(Vg_DebugMsg, "[%d] end of updated conflict set.\n", tid);
+   }
+
+   tl_assert(thread_conflict_set_up_to_date(DRD_(g_drd_running_tid)));
+}
+
+/** Report the number of context switches performed. */
+ULong DRD_(thread_get_context_switch_count)(void)
+{
+   return s_context_switch_count;
+}
+
+/** Report the number of ordered segments that have been discarded. */
+ULong DRD_(thread_get_discard_ordered_segments_count)(void)
+{
+   return s_discard_ordered_segments_count;
+}
+
+/** Return how many times the conflict set has been updated entirely. */
+ULong DRD_(thread_get_compute_conflict_set_count)()
+{
+   return s_compute_conflict_set_count;
+}
+
+/** Return how many times the conflict set has been updated partially. */
+ULong DRD_(thread_get_update_conflict_set_count)(void)
+{
+   return s_update_conflict_set_count;
+}
+
+/**
+ * Return how many times the conflict set has been updated partially
+ * because a new segment has been created.
+ */
+ULong DRD_(thread_get_update_conflict_set_new_sg_count)(void)
+{
+   return s_update_conflict_set_new_sg_count;
+}
+
+/**
+ * Return how many times the conflict set has been updated partially
+ * because of combining vector clocks due to synchronization operations
+ * other than reader/writer lock or barrier operations.
+ */
+ULong DRD_(thread_get_update_conflict_set_sync_count)(void)
+{
+   return s_update_conflict_set_sync_count;
+}
+
+/**
+ * Return how many times the conflict set has been updated partially
+ * because of thread joins.
+ */
+ULong DRD_(thread_get_update_conflict_set_join_count)(void)
+{
+   return s_update_conflict_set_join_count;
+}
+
+/**
+ * Return the number of first-level bitmaps that have been created during
+ * conflict set updates.
+ */
+ULong DRD_(thread_get_conflict_set_bitmap_creation_count)(void)
+{
+   return s_conflict_set_bitmap_creation_count;
+}
+
+/**
+ * Return the number of second-level bitmaps that have been created during
+ * conflict set updates.
+ */
+ULong DRD_(thread_get_conflict_set_bitmap2_creation_count)(void)
+{
+   return s_conflict_set_bitmap2_creation_count;
+}
diff --git a/drd/drd_thread.h b/drd/drd_thread.h
new file mode 100644
index 0000000..cb4853b
--- /dev/null
+++ b/drd/drd_thread.h
@@ -0,0 +1,355 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#ifndef __THREAD_H
+#define __THREAD_H
+
+
+/* Include directives. */
+
+#include "drd_basics.h"
+#include "drd_segment.h"
+#include "pub_drd_bitmap.h"
+#include "pub_tool_libcassert.h"  /* tl_assert()        */
+#include "pub_tool_stacktrace.h"  /* typedef StackTrace */
+#include "pub_tool_threadstate.h" /* VG_N_THREADS       */
+
+
+/* Defines. */
+
+/** Maximum number of threads DRD keeps information about. */
+#define DRD_N_THREADS VG_N_THREADS
+
+/** A number different from any valid DRD thread ID. */
+#define DRD_INVALID_THREADID 0
+
+/**
+ * A number different from any valid POSIX thread ID.
+ *
+ * @note The PThreadId typedef and the INVALID_POSIX_THREADID depend on the
+ * operating system and threading library in use. PThreadId must contain at
+ * least as many bits as pthread_t, and INVALID_POSIX_THREADID
+ * must be a value that will never be returned by pthread_self().
+ */
+#define INVALID_POSIX_THREADID ((PThreadId)0)
+
+
+/* Type definitions. */
+
+/**
+ * POSIX thread ID. The type PThreadId must be at least as wide as
+ * pthread_t.
+ */
+typedef UWord PThreadId;
+
+/** Per-thread information managed by DRD. */
+typedef struct
+{
+   Segment*  first;         /**< Pointer to first segment. */
+   Segment*  last;          /**< Pointer to last segment. */
+   ThreadId  vg_threadid;   /**< Valgrind thread ID. */
+   PThreadId pt_threadid;   /**< POSIX thread ID. */
+   Addr      stack_min_min; /**< Lowest value stack pointer ever had. */
+   Addr      stack_min;     /**< Current stack pointer. */
+   Addr      stack_startup; /**<Stack pointer after pthread_create() finished.*/
+   Addr      stack_max;     /**< Top of stack. */
+   SizeT     stack_size;    /**< Maximum size of stack. */
+   char      name[64];      /**< User-assigned thread name. */
+   Bool      on_alt_stack;
+   /** Indicates whether the Valgrind core knows about this thread. */
+   Bool      vg_thread_exists;
+   /** Indicates whether there is an associated POSIX thread ID. */
+   Bool      posix_thread_exists;
+   /**
+    * If true, indicates that there is a corresponding POSIX thread ID and
+    * a corresponding OS thread that is detached.
+    */
+   Bool      detached_posix_thread;
+   /** Wether recording of memory load accesses is currently enabled. */
+   Bool      is_recording_loads;
+   /** Wether recording of memory load accesses is currently enabled. */
+   Bool      is_recording_stores;
+   /** pthread_create() nesting level. */
+   Int       pthread_create_nesting_level;
+   /** Nesting level of synchronization functions called by the client. */
+   Int       synchr_nesting;
+} ThreadInfo;
+
+
+/*
+ * Local variables of drd_thread.c that are declared here such that these
+ * can be accessed by inline functions.
+ */
+
+/**
+ * DRD thread ID of the currently running thread. It is crucial for correct
+ * operation of DRD that this number is always in sync with
+ * VG_(get_running_tid)().
+ */
+extern DrdThreadId    DRD_(g_drd_running_tid);
+/** Per-thread information managed by DRD. */
+extern ThreadInfo     DRD_(g_threadinfo)[DRD_N_THREADS];
+/** Conflict set for the currently running thread. */
+extern struct bitmap* DRD_(g_conflict_set);
+
+
+/* Function declarations. */
+
+void DRD_(thread_trace_context_switches)(const Bool t);
+void DRD_(thread_trace_conflict_set)(const Bool t);
+void DRD_(thread_trace_conflict_set_bm)(const Bool t);
+Bool DRD_(thread_get_trace_fork_join)(void);
+void DRD_(thread_set_trace_fork_join)(const Bool t);
+void DRD_(thread_set_segment_merging)(const Bool m);
+int DRD_(thread_get_segment_merge_interval)(void);
+void DRD_(thread_set_segment_merge_interval)(const int i);
+
+DrdThreadId DRD_(VgThreadIdToDrdThreadId)(const ThreadId tid);
+DrdThreadId DRD_(NewVgThreadIdToDrdThreadId)(const ThreadId tid);
+DrdThreadId DRD_(PtThreadIdToDrdThreadId)(const PThreadId tid);
+ThreadId DRD_(DrdThreadIdToVgThreadId)(const DrdThreadId tid);
+DrdThreadId DRD_(thread_pre_create)(const DrdThreadId creator,
+                                    const ThreadId vg_created);
+DrdThreadId DRD_(thread_post_create)(const ThreadId vg_created);
+void DRD_(thread_post_join)(DrdThreadId drd_joiner, DrdThreadId drd_joinee);
+void DRD_(thread_delete)(const DrdThreadId tid);
+void DRD_(thread_finished)(const DrdThreadId tid);
+void DRD_(thread_pre_cancel)(const DrdThreadId tid);
+void DRD_(thread_set_stack_startup)(const DrdThreadId tid,
+                                    const Addr stack_startup);
+Addr DRD_(thread_get_stack_min)(const DrdThreadId tid);
+Addr DRD_(thread_get_stack_min_min)(const DrdThreadId tid);
+Addr DRD_(thread_get_stack_max)(const DrdThreadId tid);
+SizeT DRD_(thread_get_stack_size)(const DrdThreadId tid);
+Bool DRD_(thread_get_on_alt_stack)(const DrdThreadId tid);
+void DRD_(thread_set_on_alt_stack)(const DrdThreadId tid,
+                                   const Bool on_alt_stack);
+Int DRD_(thread_get_threads_on_alt_stack)(void);
+void DRD_(thread_set_pthreadid)(const DrdThreadId tid, const PThreadId ptid);
+Bool DRD_(thread_get_joinable)(const DrdThreadId tid);
+void DRD_(thread_set_joinable)(const DrdThreadId tid, const Bool joinable);
+void DRD_(thread_entering_pthread_create)(const DrdThreadId tid);
+void DRD_(thread_left_pthread_create)(const DrdThreadId tid);
+const char* DRD_(thread_get_name)(const DrdThreadId tid);
+void DRD_(thread_set_name)(const DrdThreadId tid, const char* const name);
+void DRD_(thread_set_vg_running_tid)(const ThreadId vg_tid);
+void DRD_(thread_set_running_tid)(const ThreadId vg_tid,
+                                  const DrdThreadId drd_tid);
+int DRD_(thread_enter_synchr)(const DrdThreadId tid);
+int DRD_(thread_leave_synchr)(const DrdThreadId tid);
+int DRD_(thread_get_synchr_nesting_count)(const DrdThreadId tid);
+void DRD_(thread_new_segment)(const DrdThreadId tid);
+VectorClock* DRD_(thread_get_vc)(const DrdThreadId tid);
+void DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid);
+void DRD_(thread_combine_vc_join)(const DrdThreadId joiner,
+                                  const DrdThreadId joinee);
+void DRD_(thread_new_segment_and_combine_vc)(DrdThreadId tid,
+                                             const Segment* sg);
+void DRD_(thread_update_conflict_set)(const DrdThreadId tid,
+                                      const VectorClock* const old_vc);
+
+void DRD_(thread_stop_using_mem)(const Addr a1, const Addr a2,
+                                 const Bool dont_clear_access);
+void DRD_(thread_set_record_loads)(const DrdThreadId tid, const Bool enabled);
+void DRD_(thread_set_record_stores)(const DrdThreadId tid, const Bool enabled);
+void DRD_(thread_print_all)(void);
+void DRD_(thread_report_races)(const DrdThreadId tid);
+void DRD_(thread_report_races_segment)(const DrdThreadId tid,
+                                       const Segment* const p);
+void DRD_(thread_report_all_races)(void);
+void DRD_(thread_report_conflicting_segments)(const DrdThreadId tid,
+                                              const Addr addr,
+                                              const SizeT size,
+                                              const BmAccessTypeT access_type);
+ULong DRD_(thread_get_context_switch_count)(void);
+ULong DRD_(thread_get_report_races_count)(void);
+ULong DRD_(thread_get_discard_ordered_segments_count)(void);
+ULong DRD_(thread_get_compute_conflict_set_count)(void);
+ULong DRD_(thread_get_update_conflict_set_count)(void);
+ULong DRD_(thread_get_update_conflict_set_new_sg_count)(void);
+ULong DRD_(thread_get_update_conflict_set_sync_count)(void);
+ULong DRD_(thread_get_update_conflict_set_join_count)(void);
+ULong DRD_(thread_get_conflict_set_bitmap_creation_count)(void);
+ULong DRD_(thread_get_conflict_set_bitmap2_creation_count)(void);
+
+
+/* Inline function definitions. */
+
+/**
+ * Whether or not the specified DRD thread ID is valid.
+ *
+ * A DRD thread ID is valid if and only if the following conditions are met:
+ * - The ID is a valid index of the DRD_(g_threadinfo)[] array.
+ * - The ID is not equal to DRD_INVALID_THREADID.
+ * - The ID refers either to a thread known by the Valgrind core, a joinable
+ *   thread that has not yet been joined or a detached thread.
+ */
+static __inline__
+Bool DRD_(IsValidDrdThreadId)(const DrdThreadId tid)
+{
+   return (0 <= (int)tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID
+           && ! (DRD_(g_threadinfo)[tid].vg_thread_exists == False
+                 && DRD_(g_threadinfo)[tid].posix_thread_exists == False
+                 && DRD_(g_threadinfo)[tid].detached_posix_thread == False));
+}
+
+/** Returns the DRD thread ID of the currently running thread. */
+static __inline__
+DrdThreadId DRD_(thread_get_running_tid)(void)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
+#endif
+   return DRD_(g_drd_running_tid);
+}
+
+/** Returns a pointer to the conflict set for the currently running thread. */
+static __inline__
+struct bitmap* DRD_(thread_get_conflict_set)(void)
+{
+   return DRD_(g_conflict_set);
+}
+
+/**
+ * Reports whether or not the currently running client thread is executing code
+ * inside the pthread_create() function.
+ */
+static __inline__
+Bool DRD_(running_thread_inside_pthread_create)(void)
+{
+   return (DRD_(g_threadinfo)[DRD_(g_drd_running_tid)]
+           .pthread_create_nesting_level > 0);
+}
+
+/**
+ * Reports whether or not recording of memory loads is enabled for the
+ * currently running client thread.
+ */
+static __inline__
+Bool DRD_(running_thread_is_recording_loads)(void)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(0 <= (int)DRD_(g_drd_running_tid)
+             && DRD_(g_drd_running_tid) < DRD_N_THREADS
+             && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
+#endif
+   return (DRD_(g_threadinfo)[DRD_(g_drd_running_tid)].synchr_nesting == 0
+           && DRD_(g_threadinfo)[DRD_(g_drd_running_tid)].is_recording_loads);
+}
+
+/**
+ * Reports whether or not recording memory stores is enabled for the
+ * currently running client thread.
+ */
+static __inline__
+Bool DRD_(running_thread_is_recording_stores)(void)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(0 <= (int)DRD_(g_drd_running_tid)
+             && DRD_(g_drd_running_tid) < DRD_N_THREADS
+             && DRD_(g_drd_running_tid) != DRD_INVALID_THREADID);
+#endif
+   return (DRD_(g_threadinfo)[DRD_(g_drd_running_tid)].synchr_nesting == 0
+           && DRD_(g_threadinfo)[DRD_(g_drd_running_tid)].is_recording_stores);
+}
+
+/**
+ * Update the information about the lowest stack address that has ever been
+ * accessed by a thread.
+ */
+static __inline__
+void DRD_(thread_set_stack_min)(const DrdThreadId tid, const Addr stack_min)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(0 <= (int)tid
+             && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+#endif
+   DRD_(g_threadinfo)[tid].stack_min = stack_min;
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   /* This function can be called after the thread has been created but */
+   /* before drd_post_thread_create() has filled in stack_max.          */
+   tl_assert(DRD_(g_threadinfo)[tid].stack_min
+             < DRD_(g_threadinfo)[tid].stack_max
+             || DRD_(g_threadinfo)[tid].stack_max == 0);
+#endif
+   if (UNLIKELY(stack_min < DRD_(g_threadinfo)[tid].stack_min_min))
+   {
+      DRD_(g_threadinfo)[tid].stack_min_min = stack_min;
+   }
+}
+
+/**
+ * Return true if and only if the specified address is on the stack of the
+ * currently scheduled thread.
+ */
+static __inline__
+Bool DRD_(thread_address_on_stack)(const Addr a)
+{
+   return (DRD_(g_threadinfo)[DRD_(g_drd_running_tid)].stack_min <= a
+           && a < DRD_(g_threadinfo)[DRD_(g_drd_running_tid)].stack_max);
+}
+
+/**
+ * Return true if and only if the specified address is on the stack of any
+ * thread.
+ */
+static __inline__
+Bool DRD_(thread_address_on_any_stack)(const Addr a)
+{
+   int i;
+
+   for (i = 1; i < DRD_N_THREADS; i++)
+   {
+      if (DRD_(g_threadinfo)[i].vg_thread_exists
+          && DRD_(g_threadinfo)[i].stack_min <= a
+          && a < DRD_(g_threadinfo)[i].stack_max)
+      {
+         return True;
+      }
+   }
+   return False;
+}
+
+/** Return a pointer to the latest segment for the specified thread. */
+static __inline__
+Segment* DRD_(thread_get_segment)(const DrdThreadId tid)
+{
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+   tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
+             && tid != DRD_INVALID_THREADID);
+   tl_assert(DRD_(g_threadinfo)[tid].last);
+#endif
+   return DRD_(g_threadinfo)[tid].last;
+}
+
+/** Return a pointer to the latest segment for the running thread. */
+static __inline__
+Segment* DRD_(running_thread_get_segment)(void)
+{
+   return DRD_(thread_get_segment)(DRD_(g_drd_running_tid));
+}
+
+#endif /* __THREAD_H */
diff --git a/drd/drd_thread_bitmap.h b/drd/drd_thread_bitmap.h
new file mode 100644
index 0000000..596a773
--- /dev/null
+++ b/drd/drd_thread_bitmap.h
@@ -0,0 +1,191 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#ifndef __DRD_THREAD_BITMAP_H
+#define __DRD_THREAD_BITMAP_H
+
+
+#include "drd_bitmap.h"
+#include "drd_thread.h" /* running_thread_get_segment() */
+#include "pub_drd_bitmap.h"
+
+
+static __inline__
+Bool bm_access_load_1_triggers_conflict(const Addr a1)
+{
+   DRD_(bm_access_load_1)(DRD_(sg_bm)(DRD_(running_thread_get_segment)()), a1);
+   return DRD_(bm_load_1_has_conflict_with)(DRD_(thread_get_conflict_set)(),
+                                            a1);
+}
+
+static __inline__
+Bool bm_access_load_2_triggers_conflict(const Addr a1)
+{
+   if ((a1 & 1) == 0)
+   {
+      bm_access_aligned_load(DRD_(sg_bm)(DRD_(running_thread_get_segment)()), a1, 2);
+      return bm_aligned_load_has_conflict_with(DRD_(thread_get_conflict_set)(),
+                                               a1, 2);
+   }
+   else
+   {
+      DRD_(bm_access_range)(DRD_(sg_bm)(DRD_(running_thread_get_segment)()),
+                            a1, a1 + 2, eLoad);
+      return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(),
+                                        a1, a1 + 2, eLoad);
+   }
+}
+
+static __inline__
+Bool bm_access_load_4_triggers_conflict(const Addr a1)
+{
+   if ((a1 & 3) == 0)
+   {
+      bm_access_aligned_load(DRD_(sg_bm)(DRD_(running_thread_get_segment)()), a1, 4);
+      return bm_aligned_load_has_conflict_with(DRD_(thread_get_conflict_set)(),
+                                               a1, 4);
+   }
+   else
+   {
+      DRD_(bm_access_range)(DRD_(sg_bm)(DRD_(running_thread_get_segment)()),
+                            a1, a1 + 4, eLoad);
+      return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(),
+                                        a1, a1 + 4, eLoad);
+   }
+}
+
+static __inline__
+Bool bm_access_load_8_triggers_conflict(const Addr a1)
+{
+   if ((a1 & 7) == 0)
+   {
+      bm_access_aligned_load(DRD_(sg_bm)(DRD_(running_thread_get_segment)()), a1, 8);
+      return bm_aligned_load_has_conflict_with(DRD_(thread_get_conflict_set)(),
+                                               a1, 8);
+   }
+   else if ((a1 & 3) == 0)
+   {
+      bm_access_aligned_load(DRD_(sg_bm)(DRD_(running_thread_get_segment)()), a1 + 0, 4);
+      bm_access_aligned_load(DRD_(sg_bm)(DRD_(running_thread_get_segment)()), a1 + 4, 4);
+      return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(),
+                                        a1, a1 + 8, eLoad);
+   }
+   else
+   {
+      DRD_(bm_access_range)(DRD_(sg_bm)(DRD_(running_thread_get_segment)()),
+                            a1, a1 + 8, eLoad);
+      return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(),
+                                        a1, a1 + 8, eLoad);
+   }
+}
+
+static __inline__
+Bool bm_access_load_triggers_conflict(const Addr a1, const Addr a2)
+{
+   DRD_(bm_access_range_load)(DRD_(sg_bm)(DRD_(running_thread_get_segment)()), a1, a2);
+   return DRD_(bm_load_has_conflict_with)(DRD_(thread_get_conflict_set)(),
+                                          a1, a2);
+}
+
+static __inline__
+Bool bm_access_store_1_triggers_conflict(const Addr a1)
+{
+   DRD_(bm_access_store_1)(DRD_(sg_bm)(DRD_(running_thread_get_segment)()), a1);
+   return DRD_(bm_store_1_has_conflict_with)(DRD_(thread_get_conflict_set)(),
+                                             a1);
+}
+
+static __inline__
+Bool bm_access_store_2_triggers_conflict(const Addr a1)
+{
+   if ((a1 & 1) == 0)
+   {
+      bm_access_aligned_store(DRD_(sg_bm)(DRD_(running_thread_get_segment)()), a1, 2);
+      return bm_aligned_store_has_conflict_with(DRD_(thread_get_conflict_set)(),
+                                                a1, 2);
+   }
+   else
+   {
+      DRD_(bm_access_range)(DRD_(sg_bm)(DRD_(running_thread_get_segment)()),
+                            a1, a1 + 2, eStore);
+      return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(),
+                                        a1, a1 + 2, eStore);
+   }
+}
+
+static __inline__
+Bool bm_access_store_4_triggers_conflict(const Addr a1)
+{
+   if ((a1 & 3) == 0)
+   {
+      bm_access_aligned_store(DRD_(sg_bm)(DRD_(running_thread_get_segment)()), a1, 4);
+      return bm_aligned_store_has_conflict_with(DRD_(thread_get_conflict_set)(),
+                                                a1, 4);
+   }
+   else
+   {
+      DRD_(bm_access_range)(DRD_(sg_bm)(DRD_(running_thread_get_segment)()),
+                            a1, a1 + 4, eStore);
+      return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(),
+                                        a1, a1 + 4, eStore);
+   }
+}
+
+static __inline__
+Bool bm_access_store_8_triggers_conflict(const Addr a1)
+{
+   if ((a1 & 7) == 0)
+   {
+      bm_access_aligned_store(DRD_(sg_bm)(DRD_(running_thread_get_segment)()), a1, 8);
+      return bm_aligned_store_has_conflict_with(DRD_(thread_get_conflict_set)(),
+                                                a1, 8);
+   }
+   else if ((a1 & 3) == 0)
+   {
+      bm_access_aligned_store(DRD_(sg_bm)(DRD_(running_thread_get_segment)()),
+                              a1 + 0, 4);
+      bm_access_aligned_store(DRD_(sg_bm)(DRD_(running_thread_get_segment)()),
+                              a1 + 4, 4);
+      return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(),
+                                        a1, a1 + 8, eStore);
+   }
+   else
+   {
+      DRD_(bm_access_range)(DRD_(sg_bm)(DRD_(running_thread_get_segment)()),
+                            a1, a1 + 8, eStore);
+      return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(),
+                                        a1, a1 + 8, eStore);
+   }
+}
+
+static __inline__
+Bool bm_access_store_triggers_conflict(const Addr a1, const Addr a2)
+{
+   DRD_(bm_access_range_store)(DRD_(sg_bm)(DRD_(running_thread_get_segment)()), a1, a2);
+   return DRD_(bm_store_has_conflict_with)(DRD_(thread_get_conflict_set)(),
+                                           a1, a2);
+}
+
+#endif // __DRD_THREAD_BITMAP_H
diff --git a/drd/drd_vc.c b/drd/drd_vc.c
new file mode 100644
index 0000000..d90d66f
--- /dev/null
+++ b/drd/drd_vc.c
@@ -0,0 +1,374 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#include "drd_vc.h"
+#include "pub_tool_basics.h"      // Addr, SizeT
+#include "pub_tool_libcassert.h"  // tl_assert()
+#include "pub_tool_libcbase.h"    // VG_(memcpy)
+#include "pub_tool_libcprint.h"   // VG_(printf)
+#include "pub_tool_mallocfree.h"  // VG_(malloc), VG_(free)
+
+
+/* Local function declarations. */
+
+static
+void DRD_(vc_reserve)(VectorClock* const vc, const unsigned new_capacity);
+
+
+/* Function definitions. */
+
+/**
+ * Initialize the memory 'vc' points at as a vector clock with size 'size'.
+ * If the pointer 'vcelem' is not null, it is assumed to be an array with
+ * 'size' elements and it becomes the initial value of the vector clock.
+ */
+void DRD_(vc_init)(VectorClock* const vc,
+                   const VCElem* const vcelem,
+                   const unsigned size)
+{
+   tl_assert(vc);
+   vc->size = 0;
+   vc->capacity = 0;
+   vc->vc = 0;
+   DRD_(vc_reserve)(vc, size);
+   tl_assert(size == 0 || vc->vc != 0);
+   if (vcelem)
+   {
+      VG_(memcpy)(vc->vc, vcelem, size * sizeof(vcelem[0]));
+      vc->size = size;
+   }
+}
+
+/** Reset vc to the empty vector clock. */
+void DRD_(vc_cleanup)(VectorClock* const vc)
+{
+   DRD_(vc_reserve)(vc, 0);
+}
+
+/** Copy constructor -- initializes *new. */
+void DRD_(vc_copy)(VectorClock* const new, const VectorClock* const rhs)
+{
+   DRD_(vc_init)(new, rhs->vc, rhs->size);
+}
+
+/** Assignment operator -- *lhs is already a valid vector clock. */
+void DRD_(vc_assign)(VectorClock* const lhs, const VectorClock* const rhs)
+{
+   DRD_(vc_cleanup)(lhs);
+   DRD_(vc_copy)(lhs, rhs);
+}
+
+/** Increment the clock of thread 'tid' in vector clock 'vc'. */
+void DRD_(vc_increment)(VectorClock* const vc, DrdThreadId const tid)
+{
+   unsigned i;
+   for (i = 0; i < vc->size; i++)
+   {
+      if (vc->vc[i].threadid == tid)
+      {
+         typeof(vc->vc[i].count) const oldcount = vc->vc[i].count;
+         vc->vc[i].count++;
+         // Check for integer overflow.
+         tl_assert(oldcount < vc->vc[i].count);
+         return;
+      }
+   }
+
+   /*
+    * The specified thread ID does not yet exist in the vector clock
+    * -- insert it.
+    */
+   {
+      const VCElem vcelem = { tid, 1 };
+      VectorClock vc2;
+      DRD_(vc_init)(&vc2, &vcelem, 1);
+      DRD_(vc_combine)(vc, &vc2);
+      DRD_(vc_cleanup)(&vc2);
+   }
+}
+
+/**
+ * @return True if vector clocks vc1 and vc2 are ordered, and false otherwise.
+ * Order is as imposed by thread synchronization actions ("happens before").
+ */
+Bool DRD_(vc_ordered)(const VectorClock* const vc1,
+                      const VectorClock* const vc2)
+{
+   return DRD_(vc_lte)(vc1, vc2) || DRD_(vc_lte)(vc2, vc1);
+}
+
+/** Compute elementwise minimum. */
+void DRD_(vc_min)(VectorClock* const result, const VectorClock* const rhs)
+{
+   unsigned i;
+   unsigned j;
+
+   tl_assert(result);
+   tl_assert(rhs);
+
+   DRD_(vc_check)(result);
+
+   /* Next, combine both vector clocks into one. */
+   i = 0;
+   for (j = 0; j < rhs->size; j++)
+   {
+      while (i < result->size && result->vc[i].threadid < rhs->vc[j].threadid)
+      {
+         /* Thread ID is missing in second vector clock. Clear the count. */
+         result->vc[i].count = 0;
+         i++;
+      }
+      if (i >= result->size)
+      {
+         break;
+      }
+      if (result->vc[i].threadid <= rhs->vc[j].threadid)
+      {
+         /* The thread ID is present in both vector clocks. Compute the */
+         /* minimum of vc[i].count and vc[j].count. */
+         tl_assert(result->vc[i].threadid == rhs->vc[j].threadid);
+         if (rhs->vc[j].count < result->vc[i].count)
+         {
+            result->vc[i].count = rhs->vc[j].count;
+         }
+      }
+   }
+   DRD_(vc_check)(result);
+}
+
+/**
+ * Compute elementwise maximum.
+ */
+void DRD_(vc_combine)(VectorClock* const result, const VectorClock* const rhs)
+{
+   unsigned i;
+   unsigned j;
+   unsigned shared;
+   unsigned new_size;
+
+   tl_assert(result);
+   tl_assert(rhs);
+
+   // First count the number of shared thread id's.
+   j = 0;
+   shared = 0;
+   for (i = 0; i < result->size; i++)
+   {
+      while (j < rhs->size && rhs->vc[j].threadid < result->vc[i].threadid)
+         j++;
+      if (j >= rhs->size)
+         break;
+      if (result->vc[i].threadid == rhs->vc[j].threadid)
+         shared++;
+   }
+
+   DRD_(vc_check)(result);
+
+   new_size = result->size + rhs->size - shared;
+   if (new_size > result->capacity)
+      DRD_(vc_reserve)(result, new_size);
+
+   DRD_(vc_check)(result);
+
+   // Next, combine both vector clocks into one.
+   i = 0;
+   for (j = 0; j < rhs->size; j++)
+   {
+      /* First of all, skip those clocks in result->vc[] for which there */
+      /* is no corresponding clock in rhs->vc[].                         */
+      while (i < result->size && result->vc[i].threadid < rhs->vc[j].threadid)
+      {
+         i++;
+      }
+      /* If the end of *result is met, append rhs->vc[j] to *result. */
+      if (i >= result->size)
+      {
+         result->size++;
+         result->vc[i] = rhs->vc[j];
+      }
+      /* If clock rhs->vc[j] is not in *result, insert it. */
+      else if (result->vc[i].threadid > rhs->vc[j].threadid)
+      {
+         unsigned k;
+         for (k = result->size; k > i; k--)
+         {
+            result->vc[k] = result->vc[k - 1];
+         }
+         result->size++;
+         result->vc[i] = rhs->vc[j];
+      }
+      /* Otherwise, both *result and *rhs have a clock for thread            */
+      /* result->vc[i].threadid == rhs->vc[j].threadid. Compute the maximum. */
+      else
+      {
+         tl_assert(result->vc[i].threadid == rhs->vc[j].threadid);
+         if (rhs->vc[j].count > result->vc[i].count)
+         {
+            result->vc[i].count = rhs->vc[j].count;
+         }
+      }
+   }
+   DRD_(vc_check)(result);
+   tl_assert(result->size == new_size);
+}
+
+/** Print the contents of vector clock 'vc'. */
+void DRD_(vc_print)(const VectorClock* const vc)
+{
+   char* str;
+
+   if ((str = DRD_(vc_aprint)(vc)) != NULL)
+   {
+      VG_(printf)("%s", str);
+      VG_(free)(str);
+   }
+}
+
+/**
+ * Print the contents of vector clock 'vc' to a newly allocated string.
+ * The caller must call VG_(free)() on the return value of this function.
+ */
+char* DRD_(vc_aprint)(const VectorClock* const vc)
+{
+   unsigned i;
+   unsigned reserved;
+   unsigned size;
+   char* str = 0;
+
+   tl_assert(vc);
+   reserved = 64;
+   size = 0;
+   str = VG_(realloc)("drd.vc.aprint.1", str, reserved);
+   if (! str)
+      return str;
+   size += VG_(snprintf)(str, reserved, "[");
+   for (i = 0; i < vc->size; i++)
+   {
+      tl_assert(vc->vc);
+      if (VG_(strlen)(str) + 32 > reserved)
+      {
+         reserved *= 2;
+         str = VG_(realloc)("drd.vc.aprint.2", str, reserved);
+         if (! str)
+            return str;
+      }
+      size += VG_(snprintf)(str + size, reserved - size,
+                            "%s %d: %d", i > 0 ? "," : "",
+                            vc->vc[i].threadid, vc->vc[i].count);
+   }
+   size += VG_(snprintf)(str + size, reserved - size, " ]");
+
+   return str;
+}
+
+/**
+ * Invariant test.
+ *
+ * The function below tests whether the following two conditions are
+ * satisfied:
+ * - size <= capacity.
+ * - Vector clock elements are stored in thread ID order.
+ *
+ * If one of these conditions is not met, an assertion failure is triggered.
+ */
+void DRD_(vc_check)(const VectorClock* const vc)
+{
+   unsigned i;
+   tl_assert(vc->size <= vc->capacity);
+   for (i = 1; i < vc->size; i++)
+   {
+      tl_assert(vc->vc[i-1].threadid < vc->vc[i].threadid);
+   }
+}
+
+/**
+ * Change the size of the memory block pointed at by vc->vc.
+ * Changes capacity, but does not change size. If the size of the memory
+ * block is increased, the newly allocated memory is not initialized.
+ */
+static
+void DRD_(vc_reserve)(VectorClock* const vc, const unsigned new_capacity)
+{
+   tl_assert(vc);
+   tl_assert(vc->capacity > VC_PREALLOCATED
+             || vc->vc == 0
+             || vc->vc == vc->preallocated);
+
+   if (new_capacity > vc->capacity)
+   {
+      if (vc->vc && vc->capacity > VC_PREALLOCATED)
+      {
+         tl_assert(vc->vc
+                   && vc->vc != vc->preallocated
+                   && vc->capacity > VC_PREALLOCATED);
+         vc->vc = VG_(realloc)("drd.vc.vr.1",
+                               vc->vc, new_capacity * sizeof(vc->vc[0]));
+      }
+      else if (vc->vc && new_capacity > VC_PREALLOCATED)
+      {
+         tl_assert((vc->vc == 0 || vc->vc == vc->preallocated)
+                   && new_capacity > VC_PREALLOCATED
+                   && vc->capacity <= VC_PREALLOCATED);
+         vc->vc = VG_(malloc)("drd.vc.vr.2",
+                              new_capacity * sizeof(vc->vc[0]));
+         VG_(memcpy)(vc->vc, vc->preallocated,
+                     vc->capacity * sizeof(vc->vc[0]));
+      }
+      else if (vc->vc)
+      {
+         tl_assert(vc->vc == vc->preallocated
+                   && new_capacity <= VC_PREALLOCATED
+                   && vc->capacity <= VC_PREALLOCATED);
+      }
+      else if (new_capacity > VC_PREALLOCATED)
+      {
+         tl_assert(vc->vc == 0
+                   && new_capacity > VC_PREALLOCATED
+                   && vc->capacity == 0);
+         vc->vc = VG_(malloc)("drd.vc.vr.3",
+                              new_capacity * sizeof(vc->vc[0]));
+      }
+      else
+      {
+         tl_assert(vc->vc == 0
+                   && new_capacity <= VC_PREALLOCATED
+                   && vc->capacity == 0);
+         vc->vc = vc->preallocated;
+      }
+      vc->capacity = new_capacity;
+   }
+   else if (new_capacity == 0 && vc->vc)
+   {
+      if (vc->capacity > VC_PREALLOCATED)
+         VG_(free)(vc->vc);
+      vc->vc = 0;
+      vc->capacity = 0;
+   }
+
+   tl_assert(new_capacity == 0 || vc->vc != 0);
+   tl_assert(vc->capacity > VC_PREALLOCATED
+             || vc->vc == 0
+             || vc->vc == vc->preallocated);
+}
diff --git a/drd/drd_vc.h b/drd/drd_vc.h
new file mode 100644
index 0000000..a7d67d0
--- /dev/null
+++ b/drd/drd_vc.h
@@ -0,0 +1,128 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#ifndef __DRD_VC_H
+#define __DRD_VC_H
+
+
+/*
+ * DRD vector clock implementation:
+ * - One counter per thread.
+ * - A vector clock is implemented as multiple pairs of (thread id, counter).
+ * - Pairs are stored in an array sorted by thread id.
+ *
+ * Semantics:
+ * - Each time a thread performs an action that implies an ordering between
+ *   intra-thread events, the counter of that thread is incremented.
+ * - Vector clocks are compared by comparing all counters of all threads.
+ * - When a thread synchronization action is performed that guarantees that
+ *   new actions of the current thread are executed after the actions of the
+ *   other thread, the vector clock of the synchronization object and the
+ *   current thread are combined (by taking the component-wise maximum).
+ * - A vector clock is incremented during actions such as
+ *   pthread_create(), pthread_mutex_unlock(), sem_post(). (Actions where
+ *   an inter-thread ordering "arrow" starts).
+ */
+
+
+#include "pub_tool_basics.h"     /* Addr, SizeT */
+#include "drd_basics.h"          /* DrdThreadId */
+#include "pub_tool_libcassert.h" /* tl_assert() */
+
+
+#define VC_PREALLOCATED 8
+
+
+/** Vector clock element. */
+typedef struct
+{
+   DrdThreadId threadid;
+   UInt        count;
+} VCElem;
+
+typedef struct
+{
+   unsigned capacity; /**< number of elements allocated for array vc. */
+   unsigned size;     /**< number of elements used of array vc. */
+   VCElem*  vc;       /**< vector clock elements. */
+   VCElem   preallocated[VC_PREALLOCATED];
+} VectorClock;
+
+
+void DRD_(vc_init)(VectorClock* const vc,
+                   const VCElem* const vcelem,
+                   const unsigned size);
+void DRD_(vc_cleanup)(VectorClock* const vc);
+void DRD_(vc_copy)(VectorClock* const new, const VectorClock* const rhs);
+void DRD_(vc_assign)(VectorClock* const lhs, const VectorClock* const rhs);
+void DRD_(vc_increment)(VectorClock* const vc, DrdThreadId const tid);
+static __inline__
+Bool DRD_(vc_lte)(const VectorClock* const vc1,
+                  const VectorClock* const vc2);
+Bool DRD_(vc_ordered)(const VectorClock* const vc1,
+                      const VectorClock* const vc2);
+void DRD_(vc_min)(VectorClock* const result,
+                  const VectorClock* const rhs);
+void DRD_(vc_combine)(VectorClock* const result,
+                      const VectorClock* const rhs);
+void DRD_(vc_print)(const VectorClock* const vc);
+char* DRD_(vc_aprint)(const VectorClock* const vc);
+void DRD_(vc_check)(const VectorClock* const vc);
+void DRD_(vc_test)(void);
+
+
+
+/**
+ * @return True if all thread id's that are present in vc1 also exist in
+ *    vc2, and if additionally all corresponding counters in v2 are higher or
+ *    equal.
+ */
+static __inline__
+Bool DRD_(vc_lte)(const VectorClock* const vc1, const VectorClock* const vc2)
+{
+   unsigned i;
+   unsigned j = 0;
+
+   for (i = 0; i < vc1->size; i++)
+   {
+      while (j < vc2->size && vc2->vc[j].threadid < vc1->vc[i].threadid)
+         j++;
+      if (j >= vc2->size || vc2->vc[j].threadid > vc1->vc[i].threadid)
+         return False;
+#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
+      /*
+       * This assert statement has been commented out because of performance
+       * reasons.
+       */
+      tl_assert(j < vc2->size && vc2->vc[j].threadid == vc1->vc[i].threadid);
+#endif
+      if (vc1->vc[i].count > vc2->vc[j].count)
+         return False;
+   }
+   return True;
+}
+
+
+#endif /* __DRD_VC_H */
diff --git a/drd/pub_drd_bitmap.h b/drd/pub_drd_bitmap.h
new file mode 100644
index 0000000..761a049
--- /dev/null
+++ b/drd/pub_drd_bitmap.h
@@ -0,0 +1,154 @@
+/* -*- mode: C; c-basic-offset: 3; -*- */
+/*
+  This file is part of drd, a thread error detector.
+
+  Copyright (C) 2006-2010 Bart Van Assche <bvanassche@acm.org>.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+
+/*
+ * A bitmap is a data structure that contains information about which
+ * addresses have been accessed for reading or writing within a given
+ * segment.
+ */
+
+
+#ifndef __PUB_DRD_BITMAP_H
+#define __PUB_DRD_BITMAP_H
+
+
+#include "drd_basics.h"      /* DRD_() */
+#include "pub_tool_basics.h" /* Addr, SizeT */
+#include "pub_tool_oset.h"   /* struct _OSet */
+
+
+/* Defines. */
+
+#define LHS_R (1<<0)
+#define LHS_W (1<<1)
+#define RHS_R (1<<2)
+#define RHS_W (1<<3)
+#define HAS_RACE(a) ((((a) & RHS_W) && ((a) & (LHS_R | LHS_W)))         \
+                     || (((a) & LHS_W) && ((a) & (RHS_R | RHS_W))))
+
+
+/* Forward declarations. */
+
+struct bitmap;
+
+
+/* Datatype definitions. */
+
+typedef enum { eLoad, eStore, eStart, eEnd } BmAccessTypeT;
+
+struct bm_cache_elem
+{
+   Addr            a1;
+   struct bitmap2* bm2;
+};
+
+#define DRD_BITMAP_N_CACHE_ELEM 4
+
+/* Complete bitmap. */
+struct bitmap
+{
+   struct bm_cache_elem cache[DRD_BITMAP_N_CACHE_ELEM];
+   OSet*                oset;
+};
+
+
+/* Function declarations. */
+
+struct bitmap* DRD_(bm_new)(void);
+void DRD_(bm_delete)(struct bitmap* const bm);
+void DRD_(bm_init)(struct bitmap* const bm);
+void DRD_(bm_cleanup)(struct bitmap* const bm);
+void DRD_(bm_access_range)(struct bitmap* const bm,
+                           const Addr a1, const Addr a2,
+                           const BmAccessTypeT access_type);
+void DRD_(bm_access_range_load)(struct bitmap* const bm,
+                                const Addr a1, const Addr a2);
+void DRD_(bm_access_load_1)(struct bitmap* const bm, const Addr a1);
+void DRD_(bm_access_load_2)(struct bitmap* const bm, const Addr a1);
+void DRD_(bm_access_load_4)(struct bitmap* const bm, const Addr a1);
+void DRD_(bm_access_load_8)(struct bitmap* const bm, const Addr a1);
+void DRD_(bm_access_range_store)(struct bitmap* const bm,
+                                 const Addr a1, const Addr a2);
+void DRD_(bm_access_store_1)(struct bitmap* const bm, const Addr a1);
+void DRD_(bm_access_store_2)(struct bitmap* const bm, const Addr a1);
+void DRD_(bm_access_store_4)(struct bitmap* const bm, const Addr a1);
+void DRD_(bm_access_store_8)(struct bitmap* const bm, const Addr a1);
+Bool DRD_(bm_has)(struct bitmap* const bm,
+                  const Addr a1, const Addr a2,
+                  const BmAccessTypeT access_type);
+Bool DRD_(bm_has_any_load)(struct bitmap* const bm,
+                           const Addr a1, const Addr a2);
+Bool DRD_(bm_has_any_store)(struct bitmap* const bm,
+                            const Addr a1, const Addr a2);
+Bool DRD_(bm_has_any_access)(struct bitmap* const bm,
+                             const Addr a1, const Addr a2);
+Bool DRD_(bm_has_1)(struct bitmap* const bm,
+                    const Addr address, const BmAccessTypeT access_type);
+void DRD_(bm_clear)(struct bitmap* const bm,
+                    const Addr a1, const Addr a2);
+void DRD_(bm_clear_load)(struct bitmap* const bm,
+                         const Addr a1, const Addr a2);
+void DRD_(bm_clear_store)(struct bitmap* const bm,
+                          const Addr a1, const Addr a2);
+Bool DRD_(bm_test_and_clear)(struct bitmap* const bm,
+                             const Addr a1, const Addr a2);
+Bool DRD_(bm_has_conflict_with)(struct bitmap* const bm,
+                                const Addr a1, const Addr a2,
+                                const BmAccessTypeT access_type);
+Bool DRD_(bm_load_1_has_conflict_with)(struct bitmap* const bm, const Addr a1);
+Bool DRD_(bm_load_2_has_conflict_with)(struct bitmap* const bm, const Addr a1);
+Bool DRD_(bm_load_4_has_conflict_with)(struct bitmap* const bm, const Addr a1);
+Bool DRD_(bm_load_8_has_conflict_with)(struct bitmap* const bm, const Addr a1);
+Bool DRD_(bm_load_has_conflict_with)(struct bitmap* const bm,
+                                     const Addr a1, const Addr a2);
+Bool DRD_(bm_store_1_has_conflict_with)(struct bitmap* const bm,const Addr a1);
+Bool DRD_(bm_store_2_has_conflict_with)(struct bitmap* const bm,const Addr a1);
+Bool DRD_(bm_store_4_has_conflict_with)(struct bitmap* const bm,const Addr a1);
+Bool DRD_(bm_store_8_has_conflict_with)(struct bitmap* const bm,const Addr a1);
+Bool DRD_(bm_store_has_conflict_with)(struct bitmap* const bm,
+                                      const Addr a1, const Addr a2);
+Bool DRD_(bm_equal)(struct bitmap* const lhs, struct bitmap* const rhs);
+void DRD_(bm_swap)(struct bitmap* const bm1, struct bitmap* const bm2);
+void DRD_(bm_merge2)(struct bitmap* const lhs, struct bitmap* const rhs);
+void DRD_(bm_unmark)(struct bitmap* bm);
+Bool DRD_(bm_is_marked)(struct bitmap* bm, const Addr a);
+void DRD_(bm_mark)(struct bitmap* bm1, struct bitmap* bm2);
+void DRD_(bm_clear_marked)(struct bitmap* bm);
+void DRD_(bm_merge2_marked)(struct bitmap* const lhs, struct bitmap* const rhs);
+void DRD_(bm_remove_cleared_marked)(struct bitmap* bm);
+int DRD_(bm_has_races)(struct bitmap* const bm1,
+                       struct bitmap* const bm2);
+void DRD_(bm_report_races)(ThreadId const tid1, ThreadId const tid2,
+                           struct bitmap* const bm1,
+                           struct bitmap* const bm2);
+void DRD_(bm_print)(struct bitmap* bm);
+ULong DRD_(bm_get_bitmap_creation_count)(void);
+ULong DRD_(bm_get_bitmap2_creation_count)(void);
+ULong DRD_(bm_get_bitmap2_merge_count)(void);
+
+void* DRD_(bm2_alloc_node)(HChar* const ec, const SizeT szB);
+void  DRD_(bm2_free_node)(void* const bm2);
+
+#endif /* __PUB_DRD_BITMAP_H */
diff --git a/drd/scripts/download-and-build-splash2.in b/drd/scripts/download-and-build-splash2.in
new file mode 100755
index 0000000..cb9809d
--- /dev/null
+++ b/drd/scripts/download-and-build-splash2.in
@@ -0,0 +1,172 @@
+#!/bin/bash
+
+downloads="$HOME/software/downloads"
+
+if [ ! -e /usr/include/tiffio.h ]; then
+  echo "Error: could not find file tiffio.h. Please install libtiff4-dev."
+  exit 1
+fi
+
+export LC_ALL=C
+
+mkdir -p "${downloads}"
+
+cd "$(dirname $0)/.."
+
+if [ -e splash2 ]; then
+  echo "Error: a directory with the name splash2 already exists. Please"
+  echo "remove it before running this script, or run this script in another"
+  echo "directory."
+  exit 1
+fi
+
+(
+  cd "$downloads"
+  if [ ! -e splash2.tar.gz ]; then
+    wget -q http://www-flash.stanford.edu/apps/SPLASH/splash2.tar.gz
+  fi
+  if [ ! -e splash2-modified.patch.gz ]; then
+    wget -q http://www.capsl.udel.edu/splash/splash2-modified.patch.gz
+  fi
+)
+
+tar zxf $downloads/splash2.tar.gz
+cd splash2
+gzip -cd < "$downloads/splash2-modified.patch.gz" | patch -p1 -s
+patch -p1 -s <<'EOF'
+diff -ru orig/splash2/codes/apps/radiosity/display.C splash2/codes/apps/radiosity/display.C
+--- orig/splash2/codes/apps/radiosity/display.C	2008-05-25 10:38:52.000000000 +0200
++++ splash2/codes/apps/radiosity/display.C	2008-05-25 10:37:51.000000000 +0200
+@@ -14,6 +14,7 @@
+ /*                                                                       */
+ /*************************************************************************/
+ 
++#include <math.h>
+ #include <stdio.h>
+ 
+ EXTERN_ENV;
+--- orig/splash2/codes/apps/radiosity/Makefile	2008-05-25 10:38:52.000000000 +0200
++++ splash2/codes/apps/radiosity/Makefile	2008-05-25 13:05:36.000000000 +0200
+@@ -15,7 +15,7 @@
+ 
+ LOADLIBES = glibdumb/glib.a glibps/glibps.a
+ 
+-$(TARGET): $(OBJS)
++$(TARGET): $(OBJS) $(LOADLIBES)
+ 	$(CC) $(OBJS) $(CFLAGS) $(LOADLIBES) -o $(TARGET) $(LDFLAGS)
+ 
+ radiosity.h: patch.h model.h parallel.h task.h
+@@ -29,3 +29,7 @@
+ visible.c: visible.C $(HS)
+ rad_tools.c: rad_tools.C $(HS)
+ room_model.c: room_model.C $(HS)
++glibdumb/glib.a:
++	make -C glibdumb glib.a
++glibps/glibps.a:
++	make -C glibps glibps.a
+diff -ru orig/splash2/codes/apps/raytrace/rltotiff/Makefile splash2/codes/apps/raytrace/rltotiff/Makefile
+--- orig/splash2/codes/apps/raytrace/rltotiff/Makefile	2008-05-25 10:38:52.000000000 +0200
++++ splash2/codes/apps/raytrace/rltotiff/Makefile	2008-05-25 10:31:57.000000000 +0200
+@@ -4,6 +4,3 @@
+ include ../../../Makefile.config
+ 
+ LDFLAGS := $(LDFLAGS) -ltiff
+-
+-clean:
+-	rm -rf $(OBJS) $(TARGET)
+EOF
+
+
+patch -p1 -s <<EOF
+diff -ru orig/splash2/codes/Makefile.config splash2/codes/Makefile.config
+--- orig/splash2/codes/Makefile.config	2008-05-25 10:38:52.000000000 +0200
++++ splash2/codes/Makefile.config	2008-05-25 10:14:25.000000000 +0200
+@@ -1,5 +1,5 @@
+-CC := gcc
++CC := @CC@
+-CFLAGS := -O3 -pthread -D_POSIX_C_SOURCE=200112
++CFLAGS := -g3 -m32 -O3 -pthread -D_POSIX_C_SOURCE=200112
+ #CFLAGS := -g3 -pthread -D_POSIX_C_SOURCE=200112
+ CFLAGS := \$(CFLAGS) -Wall -W -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wdisabled-optimization
+ CFLAGS := \$(CFLAGS) -Wpadded -Winline -Wpointer-arith -Wsign-compare -Wendif-labels
+@@ -5,8 +5,8 @@
+ CFLAGS := \$(CFLAGS) -Wpadded -Winline -Wpointer-arith -Wsign-compare -Wendif-labels
+ LDFLAGS := -lm
+ 
+-BASEDIR := \$(HOME)/splash2/codes
+-MACROS := \$(BASEDIR)/null_macros/c.m4.null
++BASEDIR := ${PWD}/codes
++MACROS := \$(BASEDIR)/null_macros/c.m4.null.POSIX_BARRIER
+ M4 := m4 -s -Ulen -Uindex
+ 
+ x = *
+--- orig/splash2/codes/apps/radiosity/elemman.C	2008-07-13 20:24:35.000000000 +0200
++++ splash2/codes/apps/radiosity/elemman.C	2008-07-13 20:45:15.000000000 +0200
+@@ -24,6 +24,7 @@
+ 
+ 
+ #include <stdio.h>
++#include "drd.h"
+ 
+ EXTERN_ENV;
+ 
+@@ -707,6 +708,12 @@ void process_rays(Element *e, long proce
+     e->n_interactions = 0 ;
+     UNLOCK(e->elem_lock->lock);
+ 
++    {
++      Interaction* p;
++      for (p = i_list; p; p = p->next)
++	DRD_IGNORE_VAR(*p);
++    }
++
+     /* For each interaction, do BF-error-analysis */
+     bf_error_analysis_list( e, i_list, process_id ) ;
+ 
+--- orig/splash2/codes/apps/radiosity/rad_main.C	2008-07-13 20:24:35.000000000 +0200
++++ splash2/codes/apps/radiosity/rad_main.C	2008-07-13 20:50:01.000000000 +0200
+@@ -30,6 +30,7 @@
+ #include <panel.h>
+ #endif
+ #endif
++#include "drd.h"
+ 
+ /* ANL macro initialization */
+ 
+@@ -1084,6 +1085,18 @@ void init_global(long process_id)
+     /* Initialize statistical info */
+     init_stat_info(process_id) ;
+ 
++    {
++      int i;
++
++      DRD_IGNORE_VAR(global->pbar_count);
++      for (i = 0;
++	   i < sizeof(global->task_queue) / sizeof(global->task_queue[0]);
++	   i++)
++	{
++	  DRD_IGNORE_VAR(global->task_queue[i].n_tasks);
++	}
++      DRD_IGNORE_VAR(global->element_buf);
++    }
+ }
+ 
+ 
+--- orig/splash2/codes/apps/radiosity/Makefile	2008-07-13 20:24:35.000000000 +0200
++++ splash2/codes/apps/radiosity/Makefile	2008-07-13 20:09:27.000000000 +0200
+@@ -6,7 +6,7 @@ HS = model.h parallel.h patch.h radiosit
+ 
+ include ../../Makefile.config
+ 
+-CFLAGS := \$(CFLAGS) -I./glibdumb -I./glibps
++CFLAGS := \$(CFLAGS) -I./glibdumb -I./glibps -I../../../../../drd -I../../../../../include
+ 
+ #CCOPTS = -I -float -I/usr/include \$(CFLAGS)
+ #LDFLAGS = -lm -lpthread
+EOF
+
+for m in $(find codes -name Makefile)
+do
+  echo "==== $m ===="
+  make -s -C $(dirname $m)
+done
diff --git a/drd/tests/Makefile.am b/drd/tests/Makefile.am
new file mode 100644
index 0000000..31c0163
--- /dev/null
+++ b/drd/tests/Makefile.am
@@ -0,0 +1,414 @@
+
+include $(top_srcdir)/Makefile.tool-tests.am
+
+dist_noinst_SCRIPTS =		    \
+	compare_error_count_with    \
+	filter_error_summary	    \
+	filter_stderr               \
+	filter_stderr_and_thread_no \
+	run_openmp_test             \
+	supported_libpthread	    \
+	supported_sem_init
+
+noinst_HEADERS =                                    \
+	tsan_thread_wrappers_pthread.h		    \
+	unified_annotations.h
+
+EXTRA_DIST =                                        \
+	annotate_barrier.stderr.exp		    \
+	annotate_barrier.vgtest			    \
+	annotate_hb_err.stderr.exp		    \
+	annotate_hb_err.vgtest			    \
+	annotate_hb_race.stderr.exp		    \
+	annotate_hb_race.vgtest			    \
+	annotate_hbefore.stderr.exp		    \
+	annotate_hbefore.vgtest			    \
+	annotate_order_1.stderr.exp		    \
+	annotate_order_1.vgtest			    \
+	annotate_order_2.stderr.exp		    \
+	annotate_order_2.vgtest			    \
+	annotate_order_3.stderr.exp		    \
+	annotate_order_3.vgtest			    \
+	annotate_publish_hg.stderr.exp		    \
+	annotate_publish_hg.vgtest		    \
+	annotate_smart_pointer.stderr.exp	    \
+	annotate_smart_pointer.vgtest		    \
+	annotate_spinlock.stderr.exp		    \
+	annotate_spinlock.vgtest		    \
+	annotate_rwlock.stderr.exp		    \
+	annotate_rwlock.vgtest			    \
+	annotate_rwlock_hg.stderr.exp		    \
+	annotate_rwlock_hg.vgtest		    \
+	annotate_ignore_read.stderr.exp		    \
+	annotate_ignore_read.vgtest		    \
+	annotate_ignore_rw.stderr.exp		    \
+	annotate_ignore_rw.vgtest		    \
+	annotate_ignore_rw2.stderr.exp		    \
+	annotate_ignore_rw2.vgtest		    \
+	annotate_ignore_write.stderr.exp	    \
+	annotate_ignore_write.vgtest		    \
+	annotate_ignore_write2.stderr.exp	    \
+	annotate_ignore_write2.vgtest		    \
+	annotate_trace_memory.stderr.exp	    \
+	annotate_trace_memory.vgtest		    \
+	annotate_static.stderr.exp	            \
+	annotate_static.vgtest		            \
+	atomic_var.stderr.exp			    \
+	atomic_var.vgtest			    \
+	bar_bad.stderr.exp			    \
+	bar_bad.vgtest				    \
+	bar_trivial.stderr.exp			    \
+	bar_trivial.stdout.exp			    \
+	bar_trivial.vgtest			    \
+	boost_thread.stderr.exp			    \
+	boost_thread.vgtest			    \
+	bug-235681.stderr.exp			    \
+	bug-235681.vgtest			    \
+	circular_buffer.stderr.exp		    \
+	circular_buffer.vgtest			    \
+	custom_alloc.stderr.exp			    \
+	custom_alloc.vgtest			    \
+	fp_race.stderr.exp                          \
+	fp_race.vgtest                              \
+	fp_race2.stderr.exp                         \
+	fp_race2.vgtest                             \
+	hg01_all_ok.stderr.exp                      \
+	hg01_all_ok.vgtest                          \
+	hg02_deadlock.stderr.exp                    \
+	hg02_deadlock.vgtest                        \
+	hg03_inherit.stderr.exp                     \
+	hg03_inherit.vgtest                         \
+	hg04_race.stderr.exp                        \
+	hg04_race.vgtest                            \
+	hg05_race2.stderr.exp                       \
+	hg05_race2.stderr.exp-powerpc               \
+	hg05_race2.vgtest                           \
+	hg06_readshared.stderr.exp                  \
+	hg06_readshared.vgtest                      \
+	hold_lock_1.stderr.exp                      \
+	hold_lock_1.vgtest                          \
+	hold_lock_2.stderr.exp                      \
+	hold_lock_2.vgtest                          \
+	linuxthreads_det.stderr.exp                 \
+	linuxthreads_det.stderr.exp-linuxthreads    \
+	linuxthreads_det.stdout.exp                 \
+	linuxthreads_det.stdout.exp-linuxthreads    \
+	linuxthreads_det.vgtest                     \
+	matinv.stderr.exp                           \
+	matinv.stdout.exp                           \
+	matinv.vgtest                               \
+	memory_allocation.stderr.exp		    \
+	memory_allocation.vgtest		    \
+	monitor_example.stderr.exp		    \
+	monitor_example.vgtest			    \
+	new_delete.stderr.exp                       \
+	new_delete.vgtest                           \
+	omp_matinv.stderr.exp                       \
+	omp_matinv.stdout.exp                       \
+	omp_matinv.vgtest                           \
+	omp_matinv_racy.stderr.exp                  \
+	omp_matinv_racy.stdout.exp                  \
+	omp_matinv_racy.vgtest                      \
+	omp_prime_racy.stderr.exp                   \
+	omp_prime_racy.vgtest                       \
+	omp_printf.stderr.exp                       \
+	omp_printf.vgtest                           \
+	pth_barrier.stderr.exp                      \
+	pth_barrier.vgtest                          \
+	pth_barrier2.stderr.exp                     \
+	pth_barrier2.vgtest                         \
+	pth_barrier3.stderr.exp                     \
+	pth_barrier3.vgtest                         \
+	pth_barrier_race.stderr.exp                 \
+	pth_barrier_race.vgtest                     \
+	pth_barrier_reinit.stderr.exp               \
+	pth_barrier_reinit.vgtest                   \
+	pth_broadcast.stderr.exp                    \
+	pth_broadcast.vgtest                        \
+	pth_cancel_locked.stderr.exp		    \
+	pth_cancel_locked.stderr.exp-darwin	    \
+	pth_cancel_locked.vgtest		    \
+	pth_cleanup_handler.stderr.exp		    \
+	pth_cleanup_handler.vgtest		    \
+	pth_cond_race.stderr.exp                    \
+	pth_cond_race.vgtest                        \
+	pth_cond_race2.stderr.exp                   \
+	pth_cond_race2.vgtest                       \
+	pth_cond_race3.stderr.exp                   \
+	pth_cond_race3.vgtest                       \
+	pth_create_chain.stderr.exp                 \
+	pth_create_chain.vgtest                     \
+	pth_create_glibc_2_0.stderr.exp             \
+	pth_create_glibc_2_0.vgtest                 \
+	pth_detached.stderr.exp                     \
+	pth_detached.stdout.exp                     \
+	pth_detached.vgtest                         \
+	pth_detached2.stderr.exp                    \
+	pth_detached2.stdout.exp                    \
+	pth_detached2.vgtest                        \
+	pth_detached_sem.stderr.exp                 \
+	pth_detached_sem.stdout.exp                 \
+	pth_detached_sem.vgtest                     \
+	pth_inconsistent_cond_wait.stderr.exp1      \
+	pth_inconsistent_cond_wait.stderr.exp2      \
+	pth_inconsistent_cond_wait.vgtest           \
+	pth_mutex_reinit.stderr.exp		    \
+	pth_mutex_reinit.vgtest			    \
+	pth_once.stderr.exp			    \
+	pth_once.vgtest				    \
+	pth_process_shared_mutex.stderr.exp         \
+	pth_process_shared_mutex.vgtest             \
+	pth_spinlock.stderr.exp                     \
+	pth_spinlock.vgtest                         \
+	pth_uninitialized_cond.stderr.exp           \
+	pth_uninitialized_cond.vgtest               \
+	qt4_atomic.stderr.exp                       \
+	qt4_atomic.vgtest                           \
+	qt4_mutex.stderr.exp                        \
+	qt4_mutex.vgtest                            \
+	qt4_rwlock.stderr.exp                       \
+	qt4_rwlock.vgtest                           \
+	qt4_semaphore.stderr.exp                    \
+	qt4_semaphore.vgtest                        \
+	read_after_free.stderr.exp		    \
+	read_after_free.vgtest			    \
+	recursive_mutex.stderr.exp-linux            \
+	recursive_mutex.stderr.exp-darwin           \
+	recursive_mutex.vgtest                      \
+	rwlock_race.stderr.exp	                    \
+	rwlock_race.stderr.exp2	                    \
+	rwlock_race.vgtest                          \
+	rwlock_test.stderr.exp	                    \
+	rwlock_test.vgtest                          \
+	rwlock_type_checking.stderr.exp	            \
+	rwlock_type_checking.vgtest                 \
+	sem_as_mutex.stderr.exp                     \
+	sem_as_mutex.vgtest                         \
+	sem_as_mutex2.stderr.exp                    \
+	sem_as_mutex2.vgtest                        \
+	sem_as_mutex3.stderr.exp                    \
+	sem_as_mutex3.vgtest                        \
+	sem_open.stderr.exp                         \
+	sem_open.vgtest                             \
+	sem_open2.stderr.exp                        \
+	sem_open2.vgtest                            \
+	sem_open3.stderr.exp                        \
+	sem_open3.vgtest                            \
+	sem_open_traced.stderr.exp                  \
+	sem_open_traced.vgtest                      \
+	sigalrm.stderr.exp                          \
+	sigalrm.vgtest                              \
+	sigaltstack.stderr.exp                      \
+	sigaltstack.vgtest                          \
+	tc01_simple_race.stderr.exp                 \
+	tc01_simple_race.vgtest                     \
+	tc02_simple_tls.stderr.exp                  \
+	tc02_simple_tls.vgtest                      \
+	tc03_re_excl.stderr.exp                     \
+	tc03_re_excl.vgtest                         \
+	tc04_free_lock.stderr.exp                   \
+	tc04_free_lock.vgtest                       \
+	tc05_simple_race.stderr.exp                 \
+	tc05_simple_race.vgtest                     \
+	tc06_two_races.stderr.exp                   \
+	tc06_two_races.vgtest                       \
+	tc07_hbl1.stderr.exp                        \
+	tc07_hbl1.stdout.exp                        \
+	tc07_hbl1.vgtest                            \
+	tc08_hbl2.stderr.exp                        \
+	tc08_hbl2.stdout.exp                        \
+	tc08_hbl2.vgtest                            \
+	tc09_bad_unlock.stderr.exp                  \
+	tc09_bad_unlock.stderr.exp-glibc2.8         \
+	tc09_bad_unlock.vgtest                      \
+	tc10_rec_lock.stderr.exp                    \
+	tc10_rec_lock.vgtest                        \
+	tc11_XCHG.stderr.exp tc11_XCHG.stdout.exp   \
+	tc11_XCHG.vgtest                            \
+	tc12_rwl_trivial.stderr.exp                 \
+	tc12_rwl_trivial.vgtest                     \
+	tc13_laog1.stderr.exp                       \
+	tc13_laog1.vgtest                           \
+	tc15_laog_lockdel.stderr.exp                \
+	tc15_laog_lockdel.vgtest                    \
+	tc16_byterace.stderr.exp                    \
+	tc16_byterace.vgtest                        \
+	tc17_sembar.stderr.exp                      \
+	tc17_sembar.vgtest                          \
+	tc18_semabuse.stderr.exp                    \
+	tc18_semabuse.vgtest                        \
+	tc19_shadowmem.stderr.exp-32bit             \
+	tc19_shadowmem.stderr.exp-64bit             \
+	tc19_shadowmem.vgtest                       \
+	tc21_pthonce.stderr.exp                     \
+	tc21_pthonce.stdout.exp                     \
+	tc21_pthonce.vgtest                         \
+	tc22_exit_w_lock.stderr.exp-32bit	    \
+	tc22_exit_w_lock.stderr.exp-64bit           \
+	tc22_exit_w_lock.vgtest                     \
+	tc23_bogus_condwait.stderr.exp-linux-x86    \
+	tc23_bogus_condwait.stderr.exp-linux-ppc    \
+	tc23_bogus_condwait.stderr.exp-darwin       \
+	tc23_bogus_condwait.vgtest                  \
+	tc24_nonzero_sem.stderr.exp                 \
+	tc24_nonzero_sem.vgtest                     \
+	thread_name.stderr.exp			    \
+	thread_name.vgtest			    \
+	trylock.stderr.exp                          \
+	trylock.vgtest				    \
+	unit_bitmap.stderr.exp                      \
+	unit_bitmap.vgtest                          \
+	unit_vc.stderr.exp                          \
+	unit_vc.vgtest
+
+
+check_PROGRAMS =      \
+  annotate_hb_err     \
+  annotate_hb_race    \
+  annotate_ignore_rw  \
+  annotate_ignore_write \
+  annotate_publish_hg \
+  annotate_static     \
+  bug-235681          \
+  custom_alloc        \
+  fp_race             \
+  hold_lock           \
+  linuxthreads_det    \
+  memory_allocation   \
+  monitor_example     \
+  new_delete          \
+  pth_broadcast       \
+  pth_cancel_locked   \
+  pth_cleanup_handler \
+  pth_cond_race       \
+  pth_create_chain    \
+  pth_detached        \
+  pth_detached_sem    \
+  pth_inconsistent_cond_wait \
+  pth_mutex_reinit    \
+  pth_process_shared_mutex   \
+  pth_uninitialized_cond \
+  recursive_mutex     \
+  rwlock_race         \
+  rwlock_test         \
+  rwlock_type_checking \
+  sem_as_mutex        \
+  sem_open            \
+  sigalrm             \
+  thread_name         \
+  trylock             \
+  unit_bitmap         \
+  unit_vc
+
+if HAVE_BOOST_1_35
+check_PROGRAMS += boost_thread
+endif
+
+if HAVE_BUILTIN_ATOMIC
+check_PROGRAMS +=        \
+  annotate_barrier       \
+  annotate_rwlock        \
+  annotate_smart_pointer \
+  atomic_var             \
+  circular_buffer        \
+  read_after_free        \
+  tsan_unittest
+endif
+
+if HAVE_OPENMP
+check_PROGRAMS += omp_matinv omp_prime omp_printf
+endif
+
+if HAVE_PTHREAD_BARRIER
+check_PROGRAMS += matinv pth_barrier pth_barrier_race pth_barrier_reinit
+endif
+
+if HAVE_PTHREAD_CREATE_GLIBC_2_0
+check_PROGRAMS += pth_create_glibc_2_0
+endif
+
+if HAVE_PTHREAD_SPINLOCK
+check_PROGRAMS += pth_spinlock
+endif
+
+if HAVE_QTCORE
+check_PROGRAMS += qt4_mutex qt4_rwlock qt4_semaphore
+endif
+
+if HAVE_QTCORE_QATOMICINT
+check_PROGRAMS += qt4_atomic
+endif
+
+
+AM_CFLAGS   += $(AM_FLAG_M3264_PRI) @FLAG_W_EXTRA@ -Wno-inline -Wno-unused-parameter
+AM_CXXFLAGS += $(AM_FLAG_M3264_PRI) @FLAG_W_EXTRA@ -Wno-inline -Wno-unused-parameter
+
+LDADD = -lpthread
+
+
+monitor_example_SOURCES     = monitor_example.cpp
+new_delete_SOURCES          = new_delete.cpp
+
+pth_cleanup_handler_CFLAGS  = $(AM_CFLAGS) @FLAG_W_NO_EMPTY_BODY@
+
+tsan_unittest_SOURCES       = tsan_unittest.cpp
+tsan_unittest_CXXFLAGS      = $(AM_CXXFLAGS) \
+			-DTHREAD_WRAPPERS='"tsan_thread_wrappers_pthread.h"'
+
+unit_bitmap_CFLAGS          = $(AM_CFLAGS) -O2 \
+                              -DENABLE_DRD_CONSISTENCY_CHECKS \
+                              @FLAG_UNLIMITED_INLINE_UNIT_GROWTH@
+unit_bitmap_LDADD           = # nothing, i.e. not -lpthread
+
+unit_vc_CFLAGS              = $(AM_CFLAGS) -DENABLE_DRD_CONSISTENCY_CHECKS
+unit_vc_LDADD               = # nothing, i.e. not -lpthread
+
+if HAVE_BOOST_1_35
+boost_thread_SOURCES        = boost_thread.cpp
+boost_thread_CXXFLAGS       = $(AM_CXXFLAGS) $(BOOST_CFLAGS)
+boost_thread_LDADD          = $(BOOST_LIBS)
+endif
+
+if HAVE_BUILTIN_ATOMIC
+annotate_smart_pointer_SOURCES = annotate_smart_pointer.cpp
+endif
+
+annotate_static_SOURCES     = annotate_static.cpp
+
+if HAVE_OPENMP
+omp_matinv_CFLAGS           = $(AM_CFLAGS) -fopenmp
+omp_matinv_LDFLAGS          = -fopenmp
+omp_matinv_LDADD            = $(LDADD) -lm
+
+omp_prime_CFLAGS            = $(AM_CFLAGS) -fopenmp
+omp_prime_LDFLAGS           = -fopenmp
+omp_prime_LDADD             = $(LDADD) -lm
+
+omp_printf_CFLAGS           = $(AM_CFLAGS) -fopenmp
+omp_printf_LDFLAGS          = -fopenmp
+omp_printf_LDADD            = $(LDADD) -lm
+endif
+
+if HAVE_PTHREAD_BARRIER
+matinv_LDADD                = $(LDADD) -lm
+endif
+
+if HAVE_QTCORE
+qt4_mutex_SOURCES           = qt4_mutex.cpp
+qt4_mutex_CXXFLAGS          = $(AM_CXXFLAGS) $(QTCORE_CFLAGS)
+qt4_mutex_LDADD             = $(LDADD) $(QTCORE_LIBS)
+
+qt4_rwlock_SOURCES          = qt4_rwlock.cpp
+qt4_rwlock_CXXFLAGS         = $(AM_CXXFLAGS) $(QTCORE_CFLAGS)
+qt4_rwlock_LDADD            = $(LDADD) $(QTCORE_LIBS)
+
+qt4_semaphore_SOURCES       = qt4_semaphore.cpp
+qt4_semaphore_CXXFLAGS      = $(AM_CXXFLAGS) $(QTCORE_CFLAGS)
+qt4_semaphore_LDADD         = $(LDADD) $(QTCORE_LIBS)
+endif
+
+if HAVE_QTCORE_QATOMICINT
+qt4_atomic_SOURCES          = qt4_atomic.cpp
+qt4_atomic_CXXFLAGS         = $(AM_CXXFLAGS) $(QTCORE_CFLAGS)
+qt4_atomic_LDADD            = $(LDADD) $(QTCORE_LIBS)
+endif
diff --git a/drd/tests/Makefile.in b/drd/tests/Makefile.in
new file mode 100644
index 0000000..2a0d064
--- /dev/null
+++ b/drd/tests/Makefile.in
@@ -0,0 +1,1758 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# This file is used for tool tests, and also in perf/Makefile.am.
+
+# This file should be included (directly or indirectly) by every
+# Makefile.am that builds programs.  And also the top-level Makefile.am.
+
+#----------------------------------------------------------------------------
+# Global stuff
+#----------------------------------------------------------------------------
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+DIST_COMMON = $(dist_noinst_SCRIPTS) $(noinst_HEADERS) \
+	$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+	$(top_srcdir)/Makefile.all.am \
+	$(top_srcdir)/Makefile.tool-tests.am
+check_PROGRAMS = annotate_hb_err$(EXEEXT) annotate_hb_race$(EXEEXT) \
+	annotate_ignore_rw$(EXEEXT) annotate_ignore_write$(EXEEXT) \
+	annotate_publish_hg$(EXEEXT) annotate_static$(EXEEXT) \
+	bug-235681$(EXEEXT) custom_alloc$(EXEEXT) fp_race$(EXEEXT) \
+	hold_lock$(EXEEXT) linuxthreads_det$(EXEEXT) \
+	memory_allocation$(EXEEXT) monitor_example$(EXEEXT) \
+	new_delete$(EXEEXT) pth_broadcast$(EXEEXT) \
+	pth_cancel_locked$(EXEEXT) pth_cleanup_handler$(EXEEXT) \
+	pth_cond_race$(EXEEXT) pth_create_chain$(EXEEXT) \
+	pth_detached$(EXEEXT) pth_detached_sem$(EXEEXT) \
+	pth_inconsistent_cond_wait$(EXEEXT) pth_mutex_reinit$(EXEEXT) \
+	pth_process_shared_mutex$(EXEEXT) \
+	pth_uninitialized_cond$(EXEEXT) recursive_mutex$(EXEEXT) \
+	rwlock_race$(EXEEXT) rwlock_test$(EXEEXT) \
+	rwlock_type_checking$(EXEEXT) sem_as_mutex$(EXEEXT) \
+	sem_open$(EXEEXT) sigalrm$(EXEEXT) thread_name$(EXEEXT) \
+	trylock$(EXEEXT) unit_bitmap$(EXEEXT) unit_vc$(EXEEXT) \
+	$(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
+	$(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \
+	$(am__EXEEXT_7) $(am__EXEEXT_8)
+@HAVE_BOOST_1_35_TRUE@am__append_1 = boost_thread
+@HAVE_BUILTIN_ATOMIC_TRUE@am__append_2 = \
+@HAVE_BUILTIN_ATOMIC_TRUE@  annotate_barrier       \
+@HAVE_BUILTIN_ATOMIC_TRUE@  annotate_rwlock        \
+@HAVE_BUILTIN_ATOMIC_TRUE@  annotate_smart_pointer \
+@HAVE_BUILTIN_ATOMIC_TRUE@  atomic_var             \
+@HAVE_BUILTIN_ATOMIC_TRUE@  circular_buffer        \
+@HAVE_BUILTIN_ATOMIC_TRUE@  read_after_free        \
+@HAVE_BUILTIN_ATOMIC_TRUE@  tsan_unittest
+
+@HAVE_OPENMP_TRUE@am__append_3 = omp_matinv omp_prime omp_printf
+@HAVE_PTHREAD_BARRIER_TRUE@am__append_4 = matinv pth_barrier pth_barrier_race pth_barrier_reinit
+@HAVE_PTHREAD_CREATE_GLIBC_2_0_TRUE@am__append_5 = pth_create_glibc_2_0
+@HAVE_PTHREAD_SPINLOCK_TRUE@am__append_6 = pth_spinlock
+@HAVE_QTCORE_TRUE@am__append_7 = qt4_mutex qt4_rwlock qt4_semaphore
+@HAVE_QTCORE_QATOMICINT_TRUE@am__append_8 = qt4_atomic
+subdir = drd/tests
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+@HAVE_BOOST_1_35_TRUE@am__EXEEXT_1 = boost_thread$(EXEEXT)
+@HAVE_BUILTIN_ATOMIC_TRUE@am__EXEEXT_2 = annotate_barrier$(EXEEXT) \
+@HAVE_BUILTIN_ATOMIC_TRUE@	annotate_rwlock$(EXEEXT) \
+@HAVE_BUILTIN_ATOMIC_TRUE@	annotate_smart_pointer$(EXEEXT) \
+@HAVE_BUILTIN_ATOMIC_TRUE@	atomic_var$(EXEEXT) \
+@HAVE_BUILTIN_ATOMIC_TRUE@	circular_buffer$(EXEEXT) \
+@HAVE_BUILTIN_ATOMIC_TRUE@	read_after_free$(EXEEXT) \
+@HAVE_BUILTIN_ATOMIC_TRUE@	tsan_unittest$(EXEEXT)
+@HAVE_OPENMP_TRUE@am__EXEEXT_3 = omp_matinv$(EXEEXT) \
+@HAVE_OPENMP_TRUE@	omp_prime$(EXEEXT) omp_printf$(EXEEXT)
+@HAVE_PTHREAD_BARRIER_TRUE@am__EXEEXT_4 = matinv$(EXEEXT) \
+@HAVE_PTHREAD_BARRIER_TRUE@	pth_barrier$(EXEEXT) \
+@HAVE_PTHREAD_BARRIER_TRUE@	pth_barrier_race$(EXEEXT) \
+@HAVE_PTHREAD_BARRIER_TRUE@	pth_barrier_reinit$(EXEEXT)
+@HAVE_PTHREAD_CREATE_GLIBC_2_0_TRUE@am__EXEEXT_5 = pth_create_glibc_2_0$(EXEEXT)
+@HAVE_PTHREAD_SPINLOCK_TRUE@am__EXEEXT_6 = pth_spinlock$(EXEEXT)
+@HAVE_QTCORE_TRUE@am__EXEEXT_7 = qt4_mutex$(EXEEXT) \
+@HAVE_QTCORE_TRUE@	qt4_rwlock$(EXEEXT) qt4_semaphore$(EXEEXT)
+@HAVE_QTCORE_QATOMICINT_TRUE@am__EXEEXT_8 = qt4_atomic$(EXEEXT)
+annotate_barrier_SOURCES = annotate_barrier.c
+annotate_barrier_OBJECTS = annotate_barrier.$(OBJEXT)
+annotate_barrier_LDADD = $(LDADD)
+annotate_barrier_DEPENDENCIES =
+annotate_hb_err_SOURCES = annotate_hb_err.c
+annotate_hb_err_OBJECTS = annotate_hb_err.$(OBJEXT)
+annotate_hb_err_LDADD = $(LDADD)
+annotate_hb_err_DEPENDENCIES =
+annotate_hb_race_SOURCES = annotate_hb_race.c
+annotate_hb_race_OBJECTS = annotate_hb_race.$(OBJEXT)
+annotate_hb_race_LDADD = $(LDADD)
+annotate_hb_race_DEPENDENCIES =
+annotate_ignore_rw_SOURCES = annotate_ignore_rw.c
+annotate_ignore_rw_OBJECTS = annotate_ignore_rw.$(OBJEXT)
+annotate_ignore_rw_LDADD = $(LDADD)
+annotate_ignore_rw_DEPENDENCIES =
+annotate_ignore_write_SOURCES = annotate_ignore_write.c
+annotate_ignore_write_OBJECTS = annotate_ignore_write.$(OBJEXT)
+annotate_ignore_write_LDADD = $(LDADD)
+annotate_ignore_write_DEPENDENCIES =
+annotate_publish_hg_SOURCES = annotate_publish_hg.c
+annotate_publish_hg_OBJECTS = annotate_publish_hg.$(OBJEXT)
+annotate_publish_hg_LDADD = $(LDADD)
+annotate_publish_hg_DEPENDENCIES =
+annotate_rwlock_SOURCES = annotate_rwlock.c
+annotate_rwlock_OBJECTS = annotate_rwlock.$(OBJEXT)
+annotate_rwlock_LDADD = $(LDADD)
+annotate_rwlock_DEPENDENCIES =
+am__annotate_smart_pointer_SOURCES_DIST = annotate_smart_pointer.cpp
+@HAVE_BUILTIN_ATOMIC_TRUE@am_annotate_smart_pointer_OBJECTS =  \
+@HAVE_BUILTIN_ATOMIC_TRUE@	annotate_smart_pointer.$(OBJEXT)
+annotate_smart_pointer_OBJECTS = $(am_annotate_smart_pointer_OBJECTS)
+annotate_smart_pointer_LDADD = $(LDADD)
+annotate_smart_pointer_DEPENDENCIES =
+am_annotate_static_OBJECTS = annotate_static.$(OBJEXT)
+annotate_static_OBJECTS = $(am_annotate_static_OBJECTS)
+annotate_static_LDADD = $(LDADD)
+annotate_static_DEPENDENCIES =
+atomic_var_SOURCES = atomic_var.c
+atomic_var_OBJECTS = atomic_var.$(OBJEXT)
+atomic_var_LDADD = $(LDADD)
+atomic_var_DEPENDENCIES =
+am__boost_thread_SOURCES_DIST = boost_thread.cpp
+@HAVE_BOOST_1_35_TRUE@am_boost_thread_OBJECTS =  \
+@HAVE_BOOST_1_35_TRUE@	boost_thread-boost_thread.$(OBJEXT)
+boost_thread_OBJECTS = $(am_boost_thread_OBJECTS)
+am__DEPENDENCIES_1 =
+@HAVE_BOOST_1_35_TRUE@boost_thread_DEPENDENCIES =  \
+@HAVE_BOOST_1_35_TRUE@	$(am__DEPENDENCIES_1)
+boost_thread_LINK = $(CXXLD) $(boost_thread_CXXFLAGS) $(CXXFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+bug_235681_SOURCES = bug-235681.c
+bug_235681_OBJECTS = bug-235681.$(OBJEXT)
+bug_235681_LDADD = $(LDADD)
+bug_235681_DEPENDENCIES =
+circular_buffer_SOURCES = circular_buffer.c
+circular_buffer_OBJECTS = circular_buffer.$(OBJEXT)
+circular_buffer_LDADD = $(LDADD)
+circular_buffer_DEPENDENCIES =
+custom_alloc_SOURCES = custom_alloc.c
+custom_alloc_OBJECTS = custom_alloc.$(OBJEXT)
+custom_alloc_LDADD = $(LDADD)
+custom_alloc_DEPENDENCIES =
+fp_race_SOURCES = fp_race.c
+fp_race_OBJECTS = fp_race.$(OBJEXT)
+fp_race_LDADD = $(LDADD)
+fp_race_DEPENDENCIES =
+hold_lock_SOURCES = hold_lock.c
+hold_lock_OBJECTS = hold_lock.$(OBJEXT)
+hold_lock_LDADD = $(LDADD)
+hold_lock_DEPENDENCIES =
+linuxthreads_det_SOURCES = linuxthreads_det.c
+linuxthreads_det_OBJECTS = linuxthreads_det.$(OBJEXT)
+linuxthreads_det_LDADD = $(LDADD)
+linuxthreads_det_DEPENDENCIES =
+matinv_SOURCES = matinv.c
+matinv_OBJECTS = matinv.$(OBJEXT)
+@HAVE_PTHREAD_BARRIER_TRUE@matinv_DEPENDENCIES =  \
+@HAVE_PTHREAD_BARRIER_TRUE@	$(am__DEPENDENCIES_1)
+memory_allocation_SOURCES = memory_allocation.c
+memory_allocation_OBJECTS = memory_allocation.$(OBJEXT)
+memory_allocation_LDADD = $(LDADD)
+memory_allocation_DEPENDENCIES =
+am_monitor_example_OBJECTS = monitor_example.$(OBJEXT)
+monitor_example_OBJECTS = $(am_monitor_example_OBJECTS)
+monitor_example_LDADD = $(LDADD)
+monitor_example_DEPENDENCIES =
+am_new_delete_OBJECTS = new_delete.$(OBJEXT)
+new_delete_OBJECTS = $(am_new_delete_OBJECTS)
+new_delete_LDADD = $(LDADD)
+new_delete_DEPENDENCIES =
+omp_matinv_SOURCES = omp_matinv.c
+omp_matinv_OBJECTS = omp_matinv-omp_matinv.$(OBJEXT)
+@HAVE_OPENMP_TRUE@omp_matinv_DEPENDENCIES = $(am__DEPENDENCIES_1)
+omp_matinv_LINK = $(CCLD) $(omp_matinv_CFLAGS) $(CFLAGS) \
+	$(omp_matinv_LDFLAGS) $(LDFLAGS) -o $@
+omp_prime_SOURCES = omp_prime.c
+omp_prime_OBJECTS = omp_prime-omp_prime.$(OBJEXT)
+@HAVE_OPENMP_TRUE@omp_prime_DEPENDENCIES = $(am__DEPENDENCIES_1)
+omp_prime_LINK = $(CCLD) $(omp_prime_CFLAGS) $(CFLAGS) \
+	$(omp_prime_LDFLAGS) $(LDFLAGS) -o $@
+omp_printf_SOURCES = omp_printf.c
+omp_printf_OBJECTS = omp_printf-omp_printf.$(OBJEXT)
+@HAVE_OPENMP_TRUE@omp_printf_DEPENDENCIES = $(am__DEPENDENCIES_1)
+omp_printf_LINK = $(CCLD) $(omp_printf_CFLAGS) $(CFLAGS) \
+	$(omp_printf_LDFLAGS) $(LDFLAGS) -o $@
+pth_barrier_SOURCES = pth_barrier.c
+pth_barrier_OBJECTS = pth_barrier.$(OBJEXT)
+pth_barrier_LDADD = $(LDADD)
+pth_barrier_DEPENDENCIES =
+pth_barrier_race_SOURCES = pth_barrier_race.c
+pth_barrier_race_OBJECTS = pth_barrier_race.$(OBJEXT)
+pth_barrier_race_LDADD = $(LDADD)
+pth_barrier_race_DEPENDENCIES =
+pth_barrier_reinit_SOURCES = pth_barrier_reinit.c
+pth_barrier_reinit_OBJECTS = pth_barrier_reinit.$(OBJEXT)
+pth_barrier_reinit_LDADD = $(LDADD)
+pth_barrier_reinit_DEPENDENCIES =
+pth_broadcast_SOURCES = pth_broadcast.c
+pth_broadcast_OBJECTS = pth_broadcast.$(OBJEXT)
+pth_broadcast_LDADD = $(LDADD)
+pth_broadcast_DEPENDENCIES =
+pth_cancel_locked_SOURCES = pth_cancel_locked.c
+pth_cancel_locked_OBJECTS = pth_cancel_locked.$(OBJEXT)
+pth_cancel_locked_LDADD = $(LDADD)
+pth_cancel_locked_DEPENDENCIES =
+pth_cleanup_handler_SOURCES = pth_cleanup_handler.c
+pth_cleanup_handler_OBJECTS =  \
+	pth_cleanup_handler-pth_cleanup_handler.$(OBJEXT)
+pth_cleanup_handler_LDADD = $(LDADD)
+pth_cleanup_handler_DEPENDENCIES =
+pth_cleanup_handler_LINK = $(CCLD) $(pth_cleanup_handler_CFLAGS) \
+	$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+pth_cond_race_SOURCES = pth_cond_race.c
+pth_cond_race_OBJECTS = pth_cond_race.$(OBJEXT)
+pth_cond_race_LDADD = $(LDADD)
+pth_cond_race_DEPENDENCIES =
+pth_create_chain_SOURCES = pth_create_chain.c
+pth_create_chain_OBJECTS = pth_create_chain.$(OBJEXT)
+pth_create_chain_LDADD = $(LDADD)
+pth_create_chain_DEPENDENCIES =
+pth_create_glibc_2_0_SOURCES = pth_create_glibc_2_0.c
+pth_create_glibc_2_0_OBJECTS = pth_create_glibc_2_0.$(OBJEXT)
+pth_create_glibc_2_0_LDADD = $(LDADD)
+pth_create_glibc_2_0_DEPENDENCIES =
+pth_detached_SOURCES = pth_detached.c
+pth_detached_OBJECTS = pth_detached.$(OBJEXT)
+pth_detached_LDADD = $(LDADD)
+pth_detached_DEPENDENCIES =
+pth_detached_sem_SOURCES = pth_detached_sem.c
+pth_detached_sem_OBJECTS = pth_detached_sem.$(OBJEXT)
+pth_detached_sem_LDADD = $(LDADD)
+pth_detached_sem_DEPENDENCIES =
+pth_inconsistent_cond_wait_SOURCES = pth_inconsistent_cond_wait.c
+pth_inconsistent_cond_wait_OBJECTS =  \
+	pth_inconsistent_cond_wait.$(OBJEXT)
+pth_inconsistent_cond_wait_LDADD = $(LDADD)
+pth_inconsistent_cond_wait_DEPENDENCIES =
+pth_mutex_reinit_SOURCES = pth_mutex_reinit.c
+pth_mutex_reinit_OBJECTS = pth_mutex_reinit.$(OBJEXT)
+pth_mutex_reinit_LDADD = $(LDADD)
+pth_mutex_reinit_DEPENDENCIES =
+pth_process_shared_mutex_SOURCES = pth_process_shared_mutex.c
+pth_process_shared_mutex_OBJECTS = pth_process_shared_mutex.$(OBJEXT)
+pth_process_shared_mutex_LDADD = $(LDADD)
+pth_process_shared_mutex_DEPENDENCIES =
+pth_spinlock_SOURCES = pth_spinlock.c
+pth_spinlock_OBJECTS = pth_spinlock.$(OBJEXT)
+pth_spinlock_LDADD = $(LDADD)
+pth_spinlock_DEPENDENCIES =
+pth_uninitialized_cond_SOURCES = pth_uninitialized_cond.c
+pth_uninitialized_cond_OBJECTS = pth_uninitialized_cond.$(OBJEXT)
+pth_uninitialized_cond_LDADD = $(LDADD)
+pth_uninitialized_cond_DEPENDENCIES =
+am__qt4_atomic_SOURCES_DIST = qt4_atomic.cpp
+@HAVE_QTCORE_QATOMICINT_TRUE@am_qt4_atomic_OBJECTS =  \
+@HAVE_QTCORE_QATOMICINT_TRUE@	qt4_atomic-qt4_atomic.$(OBJEXT)
+qt4_atomic_OBJECTS = $(am_qt4_atomic_OBJECTS)
+@HAVE_QTCORE_QATOMICINT_TRUE@qt4_atomic_DEPENDENCIES =  \
+@HAVE_QTCORE_QATOMICINT_TRUE@	$(am__DEPENDENCIES_1) \
+@HAVE_QTCORE_QATOMICINT_TRUE@	$(am__DEPENDENCIES_1)
+qt4_atomic_LINK = $(CXXLD) $(qt4_atomic_CXXFLAGS) $(CXXFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+am__qt4_mutex_SOURCES_DIST = qt4_mutex.cpp
+@HAVE_QTCORE_TRUE@am_qt4_mutex_OBJECTS =  \
+@HAVE_QTCORE_TRUE@	qt4_mutex-qt4_mutex.$(OBJEXT)
+qt4_mutex_OBJECTS = $(am_qt4_mutex_OBJECTS)
+@HAVE_QTCORE_TRUE@qt4_mutex_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+@HAVE_QTCORE_TRUE@	$(am__DEPENDENCIES_1)
+qt4_mutex_LINK = $(CXXLD) $(qt4_mutex_CXXFLAGS) $(CXXFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+am__qt4_rwlock_SOURCES_DIST = qt4_rwlock.cpp
+@HAVE_QTCORE_TRUE@am_qt4_rwlock_OBJECTS =  \
+@HAVE_QTCORE_TRUE@	qt4_rwlock-qt4_rwlock.$(OBJEXT)
+qt4_rwlock_OBJECTS = $(am_qt4_rwlock_OBJECTS)
+@HAVE_QTCORE_TRUE@qt4_rwlock_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+@HAVE_QTCORE_TRUE@	$(am__DEPENDENCIES_1)
+qt4_rwlock_LINK = $(CXXLD) $(qt4_rwlock_CXXFLAGS) $(CXXFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+am__qt4_semaphore_SOURCES_DIST = qt4_semaphore.cpp
+@HAVE_QTCORE_TRUE@am_qt4_semaphore_OBJECTS =  \
+@HAVE_QTCORE_TRUE@	qt4_semaphore-qt4_semaphore.$(OBJEXT)
+qt4_semaphore_OBJECTS = $(am_qt4_semaphore_OBJECTS)
+@HAVE_QTCORE_TRUE@qt4_semaphore_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+@HAVE_QTCORE_TRUE@	$(am__DEPENDENCIES_1)
+qt4_semaphore_LINK = $(CXXLD) $(qt4_semaphore_CXXFLAGS) $(CXXFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+read_after_free_SOURCES = read_after_free.c
+read_after_free_OBJECTS = read_after_free.$(OBJEXT)
+read_after_free_LDADD = $(LDADD)
+read_after_free_DEPENDENCIES =
+recursive_mutex_SOURCES = recursive_mutex.c
+recursive_mutex_OBJECTS = recursive_mutex.$(OBJEXT)
+recursive_mutex_LDADD = $(LDADD)
+recursive_mutex_DEPENDENCIES =
+rwlock_race_SOURCES = rwlock_race.c
+rwlock_race_OBJECTS = rwlock_race.$(OBJEXT)
+rwlock_race_LDADD = $(LDADD)
+rwlock_race_DEPENDENCIES =
+rwlock_test_SOURCES = rwlock_test.c
+rwlock_test_OBJECTS = rwlock_test.$(OBJEXT)
+rwlock_test_LDADD = $(LDADD)
+rwlock_test_DEPENDENCIES =
+rwlock_type_checking_SOURCES = rwlock_type_checking.c
+rwlock_type_checking_OBJECTS = rwlock_type_checking.$(OBJEXT)
+rwlock_type_checking_LDADD = $(LDADD)
+rwlock_type_checking_DEPENDENCIES =
+sem_as_mutex_SOURCES = sem_as_mutex.c
+sem_as_mutex_OBJECTS = sem_as_mutex.$(OBJEXT)
+sem_as_mutex_LDADD = $(LDADD)
+sem_as_mutex_DEPENDENCIES =
+sem_open_SOURCES = sem_open.c
+sem_open_OBJECTS = sem_open.$(OBJEXT)
+sem_open_LDADD = $(LDADD)
+sem_open_DEPENDENCIES =
+sigalrm_SOURCES = sigalrm.c
+sigalrm_OBJECTS = sigalrm.$(OBJEXT)
+sigalrm_LDADD = $(LDADD)
+sigalrm_DEPENDENCIES =
+thread_name_SOURCES = thread_name.c
+thread_name_OBJECTS = thread_name.$(OBJEXT)
+thread_name_LDADD = $(LDADD)
+thread_name_DEPENDENCIES =
+trylock_SOURCES = trylock.c
+trylock_OBJECTS = trylock.$(OBJEXT)
+trylock_LDADD = $(LDADD)
+trylock_DEPENDENCIES =
+am_tsan_unittest_OBJECTS = tsan_unittest-tsan_unittest.$(OBJEXT)
+tsan_unittest_OBJECTS = $(am_tsan_unittest_OBJECTS)
+tsan_unittest_LDADD = $(LDADD)
+tsan_unittest_DEPENDENCIES =
+tsan_unittest_LINK = $(CXXLD) $(tsan_unittest_CXXFLAGS) $(CXXFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+unit_bitmap_SOURCES = unit_bitmap.c
+unit_bitmap_OBJECTS = unit_bitmap-unit_bitmap.$(OBJEXT)
+unit_bitmap_DEPENDENCIES =
+unit_bitmap_LINK = $(CCLD) $(unit_bitmap_CFLAGS) $(CFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+unit_vc_SOURCES = unit_vc.c
+unit_vc_OBJECTS = unit_vc-unit_vc.$(OBJEXT)
+unit_vc_DEPENDENCIES =
+unit_vc_LINK = $(CCLD) $(unit_vc_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+SCRIPTS = $(dist_noinst_SCRIPTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+	-o $@
+SOURCES = annotate_barrier.c annotate_hb_err.c annotate_hb_race.c \
+	annotate_ignore_rw.c annotate_ignore_write.c \
+	annotate_publish_hg.c annotate_rwlock.c \
+	$(annotate_smart_pointer_SOURCES) $(annotate_static_SOURCES) \
+	atomic_var.c $(boost_thread_SOURCES) bug-235681.c \
+	circular_buffer.c custom_alloc.c fp_race.c hold_lock.c \
+	linuxthreads_det.c matinv.c memory_allocation.c \
+	$(monitor_example_SOURCES) $(new_delete_SOURCES) omp_matinv.c \
+	omp_prime.c omp_printf.c pth_barrier.c pth_barrier_race.c \
+	pth_barrier_reinit.c pth_broadcast.c pth_cancel_locked.c \
+	pth_cleanup_handler.c pth_cond_race.c pth_create_chain.c \
+	pth_create_glibc_2_0.c pth_detached.c pth_detached_sem.c \
+	pth_inconsistent_cond_wait.c pth_mutex_reinit.c \
+	pth_process_shared_mutex.c pth_spinlock.c \
+	pth_uninitialized_cond.c $(qt4_atomic_SOURCES) \
+	$(qt4_mutex_SOURCES) $(qt4_rwlock_SOURCES) \
+	$(qt4_semaphore_SOURCES) read_after_free.c recursive_mutex.c \
+	rwlock_race.c rwlock_test.c rwlock_type_checking.c \
+	sem_as_mutex.c sem_open.c sigalrm.c thread_name.c trylock.c \
+	$(tsan_unittest_SOURCES) unit_bitmap.c unit_vc.c
+DIST_SOURCES = annotate_barrier.c annotate_hb_err.c annotate_hb_race.c \
+	annotate_ignore_rw.c annotate_ignore_write.c \
+	annotate_publish_hg.c annotate_rwlock.c \
+	$(am__annotate_smart_pointer_SOURCES_DIST) \
+	$(annotate_static_SOURCES) atomic_var.c \
+	$(am__boost_thread_SOURCES_DIST) bug-235681.c \
+	circular_buffer.c custom_alloc.c fp_race.c hold_lock.c \
+	linuxthreads_det.c matinv.c memory_allocation.c \
+	$(monitor_example_SOURCES) $(new_delete_SOURCES) omp_matinv.c \
+	omp_prime.c omp_printf.c pth_barrier.c pth_barrier_race.c \
+	pth_barrier_reinit.c pth_broadcast.c pth_cancel_locked.c \
+	pth_cleanup_handler.c pth_cond_race.c pth_create_chain.c \
+	pth_create_glibc_2_0.c pth_detached.c pth_detached_sem.c \
+	pth_inconsistent_cond_wait.c pth_mutex_reinit.c \
+	pth_process_shared_mutex.c pth_spinlock.c \
+	pth_uninitialized_cond.c $(am__qt4_atomic_SOURCES_DIST) \
+	$(am__qt4_mutex_SOURCES_DIST) $(am__qt4_rwlock_SOURCES_DIST) \
+	$(am__qt4_semaphore_SOURCES_DIST) read_after_free.c \
+	recursive_mutex.c rwlock_race.c rwlock_test.c \
+	rwlock_type_checking.c sem_as_mutex.c sem_open.c sigalrm.c \
+	thread_name.c trylock.c $(tsan_unittest_SOURCES) unit_bitmap.c \
+	unit_vc.c
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BOOST_CFLAGS = @BOOST_CFLAGS@
+BOOST_LIBS = @BOOST_LIBS@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_SUPP = @DEFAULT_SUPP@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DIFF = @DIFF@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FLAG_FNO_STACK_PROTECTOR = @FLAG_FNO_STACK_PROTECTOR@
+FLAG_M32 = @FLAG_M32@
+FLAG_M64 = @FLAG_M64@
+FLAG_MAIX32 = @FLAG_MAIX32@
+FLAG_MAIX64 = @FLAG_MAIX64@
+FLAG_MMMX = @FLAG_MMMX@
+FLAG_MSSE = @FLAG_MSSE@
+FLAG_NO_BUILD_ID = @FLAG_NO_BUILD_ID@
+FLAG_UNLIMITED_INLINE_UNIT_GROWTH = @FLAG_UNLIMITED_INLINE_UNIT_GROWTH@
+FLAG_W_EXTRA = @FLAG_W_EXTRA@
+FLAG_W_NO_EMPTY_BODY = @FLAG_W_NO_EMPTY_BODY@
+FLAG_W_NO_FORMAT_ZERO_LENGTH = @FLAG_W_NO_FORMAT_ZERO_LENGTH@
+FLAG_W_NO_UNINITIALIZED = @FLAG_W_NO_UNINITIALIZED@
+GDB = @GDB@
+GLIBC_VERSION = @GLIBC_VERSION@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MPI_CC = @MPI_CC@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PREFERRED_STACK_BOUNDARY = @PREFERRED_STACK_BOUNDARY@
+QTCORE_CFLAGS = @QTCORE_CFLAGS@
+QTCORE_LIBS = @QTCORE_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VALT_LOAD_ADDRESS_PRI = @VALT_LOAD_ADDRESS_PRI@
+VALT_LOAD_ADDRESS_SEC = @VALT_LOAD_ADDRESS_SEC@
+VERSION = @VERSION@
+VGCONF_ARCH_PRI = @VGCONF_ARCH_PRI@
+VGCONF_ARCH_SEC = @VGCONF_ARCH_SEC@
+VGCONF_OS = @VGCONF_OS@
+VGCONF_PLATFORM_PRI_CAPS = @VGCONF_PLATFORM_PRI_CAPS@
+VGCONF_PLATFORM_SEC_CAPS = @VGCONF_PLATFORM_SEC_CAPS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+inplacedir = $(top_builddir)/.in_place
+
+#----------------------------------------------------------------------------
+# Flags
+#----------------------------------------------------------------------------
+
+# Baseline flags for all compilations.  Aim here is to maximise
+# performance and get whatever useful warnings we can out of gcc.
+AM_CFLAGS_BASE = \
+	-O2 -g \
+	-Wall \
+	-Wmissing-prototypes \
+	-Wshadow \
+	-Wpointer-arith \
+	-Wstrict-prototypes \
+	-Wmissing-declarations \
+	@FLAG_W_NO_FORMAT_ZERO_LENGTH@ \
+	-fno-strict-aliasing
+
+@VGCONF_OS_IS_DARWIN_FALSE@AM_CFLAGS_PIC = -fpic -O -g -fno-omit-frame-pointer -fno-strict-aliasing
+
+# These flags are used for building the preload shared objects.
+# The aim is to give reasonable performance but also to have good
+# stack traces, since users often see stack traces extending 
+# into (and through) the preloads.
+@VGCONF_OS_IS_DARWIN_TRUE@AM_CFLAGS_PIC = -dynamic -O -g -fno-omit-frame-pointer -fno-strict-aliasing \
+@VGCONF_OS_IS_DARWIN_TRUE@		-mno-dynamic-no-pic -fpic -fPIC
+
+
+# Flags for specific targets.
+#
+# Nb: the AM_CPPFLAGS_* values are suitable for building tools and auxprogs.
+# For building the core, coregrind/Makefile.am files add some extra things.
+#
+# Also: in newer versions of automake (1.10 onwards?) asm files ending with
+# '.S' are considered "pre-processed" (as opposed to those ending in '.s')
+# and so the CPPFLAGS are passed to the assembler.  But this is not true for
+# older automakes (e.g. 1.8.5, 1.9.6), sigh.  So we include
+# AM_CPPFLAGS_<PLATFORM> in each AM_CCASFLAGS_<PLATFORM> variable.  This
+# means some of the flags are duplicated on systems with newer versions of
+# automake, but this does not really matter and seems hard to avoid.
+AM_CPPFLAGS_@VGCONF_PLATFORM_PRI_CAPS@ = \
+	-I$(top_srcdir) \
+	-I$(top_srcdir)/include \
+	-I$(top_srcdir)/VEX/pub \
+	-DVGA_@VGCONF_ARCH_PRI@=1 \
+	-DVGO_@VGCONF_OS@=1 \
+	-DVGP_@VGCONF_ARCH_PRI@_@VGCONF_OS@=1
+
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@AM_CPPFLAGS_@VGCONF_PLATFORM_SEC_CAPS@ = \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	-I$(top_srcdir) \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	-I$(top_srcdir)/include \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	-I$(top_srcdir)/VEX/pub \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	-DVGA_@VGCONF_ARCH_SEC@=1 \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	-DVGO_@VGCONF_OS@=1 \
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@	-DVGP_@VGCONF_ARCH_SEC@_@VGCONF_OS@=1
+
+AM_FLAG_M3264_X86_LINUX = @FLAG_M32@
+AM_CFLAGS_X86_LINUX = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY@ \
+			 	$(AM_CFLAGS_BASE)
+
+AM_CCASFLAGS_X86_LINUX = $(AM_CPPFLAGS_X86_LINUX) @FLAG_M32@ -g
+AM_FLAG_M3264_AMD64_LINUX = @FLAG_M64@
+AM_CFLAGS_AMD64_LINUX = @FLAG_M64@ -fomit-frame-pointer \
+				@PREFERRED_STACK_BOUNDARY@ $(AM_CFLAGS_BASE)
+
+AM_CCASFLAGS_AMD64_LINUX = $(AM_CPPFLAGS_AMD64_LINUX) @FLAG_M64@ -g
+AM_FLAG_M3264_PPC32_LINUX = @FLAG_M32@
+AM_CFLAGS_PPC32_LINUX = @FLAG_M32@ $(AM_CFLAGS_BASE)
+AM_CCASFLAGS_PPC32_LINUX = $(AM_CPPFLAGS_PPC32_LINUX) @FLAG_M32@ -g
+AM_FLAG_M3264_PPC64_LINUX = @FLAG_M64@
+AM_CFLAGS_PPC64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
+AM_CCASFLAGS_PPC64_LINUX = $(AM_CPPFLAGS_PPC64_LINUX) @FLAG_M64@ -g
+AM_FLAG_M3264_ARM_LINUX = @FLAG_M32@
+AM_CFLAGS_ARM_LINUX = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY@ \
+			 	$(AM_CFLAGS_BASE) -marm
+
+AM_CCASFLAGS_ARM_LINUX = $(AM_CPPFLAGS_ARM_LINUX) @FLAG_M32@ -marm -g
+AM_FLAG_M3264_PPC32_AIX5 = @FLAG_MAIX32@
+AM_CFLAGS_PPC32_AIX5 = @FLAG_MAIX32@ -mcpu=powerpc $(AM_CFLAGS_BASE)
+AM_CCASFLAGS_PPC32_AIX5 = $(AM_CPPFLAGS_PPC32_AIX5) \
+			    @FLAG_MAIX32@ -mcpu=powerpc -g
+
+AM_FLAG_M3264_PPC64_AIX5 = @FLAG_MAIX64@
+AM_CFLAGS_PPC64_AIX5 = @FLAG_MAIX64@ -mcpu=powerpc64 $(AM_CFLAGS_BASE)
+AM_CCASFLAGS_PPC64_AIX5 = $(AM_CPPFLAGS_PPC64_AIX5) \
+			    @FLAG_MAIX64@ -mcpu=powerpc64 -g
+
+AM_FLAG_M3264_X86_DARWIN = -arch i386
+AM_CFLAGS_X86_DARWIN = $(WERROR) -arch i386 $(AM_CFLAGS_BASE) \
+				-mmacosx-version-min=10.5 \
+				-fno-stack-protector -fno-pic -fno-PIC
+
+AM_CCASFLAGS_X86_DARWIN = $(AM_CPPFLAGS_X86_DARWIN) -arch i386 -g
+AM_FLAG_M3264_AMD64_DARWIN = -arch x86_64
+AM_CFLAGS_AMD64_DARWIN = $(WERROR) -arch x86_64 $(AM_CFLAGS_BASE) \
+			    -mmacosx-version-min=10.5 -fno-stack-protector
+
+AM_CCASFLAGS_AMD64_DARWIN = $(AM_CPPFLAGS_AMD64_DARWIN) -arch x86_64 -g
+
+# Flags for the primary target.  These must be used to build the
+# regtests and performance tests.  In fact, these must be used to
+# build anything which is built only once on a dual-arch build.
+#
+AM_FLAG_M3264_PRI = $(AM_FLAG_M3264_@VGCONF_PLATFORM_PRI_CAPS@)
+AM_CPPFLAGS_PRI = $(AM_CPPFLAGS_@VGCONF_PLATFORM_PRI_CAPS@)
+AM_CFLAGS_PRI = $(AM_CFLAGS_@VGCONF_PLATFORM_PRI_CAPS@)
+AM_CCASFLAGS_PRI = $(AM_CCASFLAGS_@VGCONF_PLATFORM_PRI_CAPS@)
+@VGCONF_HAVE_PLATFORM_SEC_FALSE@AM_FLAG_M3264_SEC = 
+@VGCONF_HAVE_PLATFORM_SEC_TRUE@AM_FLAG_M3264_SEC = $(AM_FLAG_M3264_@VGCONF_PLATFORM_SEC_CAPS@)
+
+# Baseline link flags for making vgpreload shared objects.
+#
+PRELOAD_LDFLAGS_COMMON_LINUX = -nodefaultlibs -shared -Wl,-z,interpose,-z,initfirst
+PRELOAD_LDFLAGS_COMMON_AIX5 = -nodefaultlibs -shared -Wl,-G -Wl,-bnogc
+PRELOAD_LDFLAGS_COMMON_DARWIN = -dynamic -dynamiclib -all_load
+PRELOAD_LDFLAGS_X86_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
+PRELOAD_LDFLAGS_AMD64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
+PRELOAD_LDFLAGS_PPC32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
+PRELOAD_LDFLAGS_PPC64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
+PRELOAD_LDFLAGS_ARM_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
+PRELOAD_LDFLAGS_PPC32_AIX5 = $(PRELOAD_LDFLAGS_COMMON_AIX5)  @FLAG_MAIX32@
+PRELOAD_LDFLAGS_PPC64_AIX5 = $(PRELOAD_LDFLAGS_COMMON_AIX5)  @FLAG_MAIX64@
+PRELOAD_LDFLAGS_X86_DARWIN = $(PRELOAD_LDFLAGS_COMMON_DARWIN) -arch i386
+PRELOAD_LDFLAGS_AMD64_DARWIN = $(PRELOAD_LDFLAGS_COMMON_DARWIN) -arch x86_64
+AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
+		-I$(top_srcdir)/coregrind -I$(top_builddir)/include \
+		-I$(top_srcdir)/VEX/pub \
+		-DVGA_$(VGCONF_ARCH_PRI)=1 \
+		-DVGO_$(VGCONF_OS)=1 \
+		-DVGP_$(VGCONF_ARCH_PRI)_$(VGCONF_OS)=1
+
+# Nb: Tools need to augment these flags with an arch-selection option, such
+# as $(AM_FLAG_M3264_PRI).
+AM_CFLAGS = -Winline -Wall -Wshadow -g $(AM_FLAG_M3264_PRI) \
+	@FLAG_W_EXTRA@ -Wno-inline -Wno-unused-parameter
+AM_CXXFLAGS = -Winline -Wall -Wshadow -g $(AM_FLAG_M3264_PRI) \
+	@FLAG_W_EXTRA@ -Wno-inline -Wno-unused-parameter
+# Include AM_CPPFLAGS in AM_CCASFLAGS to allow for older versions of
+# automake;  see comments in Makefile.all.am for more detail.
+AM_CCASFLAGS = $(AM_CPPFLAGS)
+@VGCONF_OS_IS_DARWIN_TRUE@noinst_DSYMS = $(check_PROGRAMS)
+dist_noinst_SCRIPTS = \
+	compare_error_count_with    \
+	filter_error_summary	    \
+	filter_stderr               \
+	filter_stderr_and_thread_no \
+	run_openmp_test             \
+	supported_libpthread	    \
+	supported_sem_init
+
+noinst_HEADERS = \
+	tsan_thread_wrappers_pthread.h		    \
+	unified_annotations.h
+
+EXTRA_DIST = \
+	annotate_barrier.stderr.exp		    \
+	annotate_barrier.vgtest			    \
+	annotate_hb_err.stderr.exp		    \
+	annotate_hb_err.vgtest			    \
+	annotate_hb_race.stderr.exp		    \
+	annotate_hb_race.vgtest			    \
+	annotate_hbefore.stderr.exp		    \
+	annotate_hbefore.vgtest			    \
+	annotate_order_1.stderr.exp		    \
+	annotate_order_1.vgtest			    \
+	annotate_order_2.stderr.exp		    \
+	annotate_order_2.vgtest			    \
+	annotate_order_3.stderr.exp		    \
+	annotate_order_3.vgtest			    \
+	annotate_publish_hg.stderr.exp		    \
+	annotate_publish_hg.vgtest		    \
+	annotate_smart_pointer.stderr.exp	    \
+	annotate_smart_pointer.vgtest		    \
+	annotate_spinlock.stderr.exp		    \
+	annotate_spinlock.vgtest		    \
+	annotate_rwlock.stderr.exp		    \
+	annotate_rwlock.vgtest			    \
+	annotate_rwlock_hg.stderr.exp		    \
+	annotate_rwlock_hg.vgtest		    \
+	annotate_ignore_read.stderr.exp		    \
+	annotate_ignore_read.vgtest		    \
+	annotate_ignore_rw.stderr.exp		    \
+	annotate_ignore_rw.vgtest		    \
+	annotate_ignore_rw2.stderr.exp		    \
+	annotate_ignore_rw2.vgtest		    \
+	annotate_ignore_write.stderr.exp	    \
+	annotate_ignore_write.vgtest		    \
+	annotate_ignore_write2.stderr.exp	    \
+	annotate_ignore_write2.vgtest		    \
+	annotate_trace_memory.stderr.exp	    \
+	annotate_trace_memory.vgtest		    \
+	annotate_static.stderr.exp	            \
+	annotate_static.vgtest		            \
+	atomic_var.stderr.exp			    \
+	atomic_var.vgtest			    \
+	bar_bad.stderr.exp			    \
+	bar_bad.vgtest				    \
+	bar_trivial.stderr.exp			    \
+	bar_trivial.stdout.exp			    \
+	bar_trivial.vgtest			    \
+	boost_thread.stderr.exp			    \
+	boost_thread.vgtest			    \
+	bug-235681.stderr.exp			    \
+	bug-235681.vgtest			    \
+	circular_buffer.stderr.exp		    \
+	circular_buffer.vgtest			    \
+	custom_alloc.stderr.exp			    \
+	custom_alloc.vgtest			    \
+	fp_race.stderr.exp                          \
+	fp_race.vgtest                              \
+	fp_race2.stderr.exp                         \
+	fp_race2.vgtest                             \
+	hg01_all_ok.stderr.exp                      \
+	hg01_all_ok.vgtest                          \
+	hg02_deadlock.stderr.exp                    \
+	hg02_deadlock.vgtest                        \
+	hg03_inherit.stderr.exp                     \
+	hg03_inherit.vgtest                         \
+	hg04_race.stderr.exp                        \
+	hg04_race.vgtest                            \
+	hg05_race2.stderr.exp                       \
+	hg05_race2.stderr.exp-powerpc               \
+	hg05_race2.vgtest                           \
+	hg06_readshared.stderr.exp                  \
+	hg06_readshared.vgtest                      \
+	hold_lock_1.stderr.exp                      \
+	hold_lock_1.vgtest                          \
+	hold_lock_2.stderr.exp                      \
+	hold_lock_2.vgtest                          \
+	linuxthreads_det.stderr.exp                 \
+	linuxthreads_det.stderr.exp-linuxthreads    \
+	linuxthreads_det.stdout.exp                 \
+	linuxthreads_det.stdout.exp-linuxthreads    \
+	linuxthreads_det.vgtest                     \
+	matinv.stderr.exp                           \
+	matinv.stdout.exp                           \
+	matinv.vgtest                               \
+	memory_allocation.stderr.exp		    \
+	memory_allocation.vgtest		    \
+	monitor_example.stderr.exp		    \
+	monitor_example.vgtest			    \
+	new_delete.stderr.exp                       \
+	new_delete.vgtest                           \
+	omp_matinv.stderr.exp                       \
+	omp_matinv.stdout.exp                       \
+	omp_matinv.vgtest                           \
+	omp_matinv_racy.stderr.exp                  \
+	omp_matinv_racy.stdout.exp                  \
+	omp_matinv_racy.vgtest                      \
+	omp_prime_racy.stderr.exp                   \
+	omp_prime_racy.vgtest                       \
+	omp_printf.stderr.exp                       \
+	omp_printf.vgtest                           \
+	pth_barrier.stderr.exp                      \
+	pth_barrier.vgtest                          \
+	pth_barrier2.stderr.exp                     \
+	pth_barrier2.vgtest                         \
+	pth_barrier3.stderr.exp                     \
+	pth_barrier3.vgtest                         \
+	pth_barrier_race.stderr.exp                 \
+	pth_barrier_race.vgtest                     \
+	pth_barrier_reinit.stderr.exp               \
+	pth_barrier_reinit.vgtest                   \
+	pth_broadcast.stderr.exp                    \
+	pth_broadcast.vgtest                        \
+	pth_cancel_locked.stderr.exp		    \
+	pth_cancel_locked.stderr.exp-darwin	    \
+	pth_cancel_locked.vgtest		    \
+	pth_cleanup_handler.stderr.exp		    \
+	pth_cleanup_handler.vgtest		    \
+	pth_cond_race.stderr.exp                    \
+	pth_cond_race.vgtest                        \
+	pth_cond_race2.stderr.exp                   \
+	pth_cond_race2.vgtest                       \
+	pth_cond_race3.stderr.exp                   \
+	pth_cond_race3.vgtest                       \
+	pth_create_chain.stderr.exp                 \
+	pth_create_chain.vgtest                     \
+	pth_create_glibc_2_0.stderr.exp             \
+	pth_create_glibc_2_0.vgtest                 \
+	pth_detached.stderr.exp                     \
+	pth_detached.stdout.exp                     \
+	pth_detached.vgtest                         \
+	pth_detached2.stderr.exp                    \
+	pth_detached2.stdout.exp                    \
+	pth_detached2.vgtest                        \
+	pth_detached_sem.stderr.exp                 \
+	pth_detached_sem.stdout.exp                 \
+	pth_detached_sem.vgtest                     \
+	pth_inconsistent_cond_wait.stderr.exp1      \
+	pth_inconsistent_cond_wait.stderr.exp2      \
+	pth_inconsistent_cond_wait.vgtest           \
+	pth_mutex_reinit.stderr.exp		    \
+	pth_mutex_reinit.vgtest			    \
+	pth_once.stderr.exp			    \
+	pth_once.vgtest				    \
+	pth_process_shared_mutex.stderr.exp         \
+	pth_process_shared_mutex.vgtest             \
+	pth_spinlock.stderr.exp                     \
+	pth_spinlock.vgtest                         \
+	pth_uninitialized_cond.stderr.exp           \
+	pth_uninitialized_cond.vgtest               \
+	qt4_atomic.stderr.exp                       \
+	qt4_atomic.vgtest                           \
+	qt4_mutex.stderr.exp                        \
+	qt4_mutex.vgtest                            \
+	qt4_rwlock.stderr.exp                       \
+	qt4_rwlock.vgtest                           \
+	qt4_semaphore.stderr.exp                    \
+	qt4_semaphore.vgtest                        \
+	read_after_free.stderr.exp		    \
+	read_after_free.vgtest			    \
+	recursive_mutex.stderr.exp-linux            \
+	recursive_mutex.stderr.exp-darwin           \
+	recursive_mutex.vgtest                      \
+	rwlock_race.stderr.exp	                    \
+	rwlock_race.stderr.exp2	                    \
+	rwlock_race.vgtest                          \
+	rwlock_test.stderr.exp	                    \
+	rwlock_test.vgtest                          \
+	rwlock_type_checking.stderr.exp	            \
+	rwlock_type_checking.vgtest                 \
+	sem_as_mutex.stderr.exp                     \
+	sem_as_mutex.vgtest                         \
+	sem_as_mutex2.stderr.exp                    \
+	sem_as_mutex2.vgtest                        \
+	sem_as_mutex3.stderr.exp                    \
+	sem_as_mutex3.vgtest                        \
+	sem_open.stderr.exp                         \
+	sem_open.vgtest                             \
+	sem_open2.stderr.exp                        \
+	sem_open2.vgtest                            \
+	sem_open3.stderr.exp                        \
+	sem_open3.vgtest                            \
+	sem_open_traced.stderr.exp                  \
+	sem_open_traced.vgtest                      \
+	sigalrm.stderr.exp                          \
+	sigalrm.vgtest                              \
+	sigaltstack.stderr.exp                      \
+	sigaltstack.vgtest                          \
+	tc01_simple_race.stderr.exp                 \
+	tc01_simple_race.vgtest                     \
+	tc02_simple_tls.stderr.exp                  \
+	tc02_simple_tls.vgtest                      \
+	tc03_re_excl.stderr.exp                     \
+	tc03_re_excl.vgtest                         \
+	tc04_free_lock.stderr.exp                   \
+	tc04_free_lock.vgtest                       \
+	tc05_simple_race.stderr.exp                 \
+	tc05_simple_race.vgtest                     \
+	tc06_two_races.stderr.exp                   \
+	tc06_two_races.vgtest                       \
+	tc07_hbl1.stderr.exp                        \
+	tc07_hbl1.stdout.exp                        \
+	tc07_hbl1.vgtest                            \
+	tc08_hbl2.stderr.exp                        \
+	tc08_hbl2.stdout.exp                        \
+	tc08_hbl2.vgtest                            \
+	tc09_bad_unlock.stderr.exp                  \
+	tc09_bad_unlock.stderr.exp-glibc2.8         \
+	tc09_bad_unlock.vgtest                      \
+	tc10_rec_lock.stderr.exp                    \
+	tc10_rec_lock.vgtest                        \
+	tc11_XCHG.stderr.exp tc11_XCHG.stdout.exp   \
+	tc11_XCHG.vgtest                            \
+	tc12_rwl_trivial.stderr.exp                 \
+	tc12_rwl_trivial.vgtest                     \
+	tc13_laog1.stderr.exp                       \
+	tc13_laog1.vgtest                           \
+	tc15_laog_lockdel.stderr.exp                \
+	tc15_laog_lockdel.vgtest                    \
+	tc16_byterace.stderr.exp                    \
+	tc16_byterace.vgtest                        \
+	tc17_sembar.stderr.exp                      \
+	tc17_sembar.vgtest                          \
+	tc18_semabuse.stderr.exp                    \
+	tc18_semabuse.vgtest                        \
+	tc19_shadowmem.stderr.exp-32bit             \
+	tc19_shadowmem.stderr.exp-64bit             \
+	tc19_shadowmem.vgtest                       \
+	tc21_pthonce.stderr.exp                     \
+	tc21_pthonce.stdout.exp                     \
+	tc21_pthonce.vgtest                         \
+	tc22_exit_w_lock.stderr.exp-32bit	    \
+	tc22_exit_w_lock.stderr.exp-64bit           \
+	tc22_exit_w_lock.vgtest                     \
+	tc23_bogus_condwait.stderr.exp-linux-x86    \
+	tc23_bogus_condwait.stderr.exp-linux-ppc    \
+	tc23_bogus_condwait.stderr.exp-darwin       \
+	tc23_bogus_condwait.vgtest                  \
+	tc24_nonzero_sem.stderr.exp                 \
+	tc24_nonzero_sem.vgtest                     \
+	thread_name.stderr.exp			    \
+	thread_name.vgtest			    \
+	trylock.stderr.exp                          \
+	trylock.vgtest				    \
+	unit_bitmap.stderr.exp                      \
+	unit_bitmap.vgtest                          \
+	unit_vc.stderr.exp                          \
+	unit_vc.vgtest
+
+LDADD = -lpthread
+monitor_example_SOURCES = monitor_example.cpp
+new_delete_SOURCES = new_delete.cpp
+pth_cleanup_handler_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_EMPTY_BODY@
+tsan_unittest_SOURCES = tsan_unittest.cpp
+tsan_unittest_CXXFLAGS = $(AM_CXXFLAGS) \
+			-DTHREAD_WRAPPERS='"tsan_thread_wrappers_pthread.h"'
+
+unit_bitmap_CFLAGS = $(AM_CFLAGS) -O2 \
+                              -DENABLE_DRD_CONSISTENCY_CHECKS \
+                              @FLAG_UNLIMITED_INLINE_UNIT_GROWTH@
+
+unit_bitmap_LDADD = # nothing, i.e. not -lpthread
+unit_vc_CFLAGS = $(AM_CFLAGS) -DENABLE_DRD_CONSISTENCY_CHECKS
+unit_vc_LDADD = # nothing, i.e. not -lpthread
+@HAVE_BOOST_1_35_TRUE@boost_thread_SOURCES = boost_thread.cpp
+@HAVE_BOOST_1_35_TRUE@boost_thread_CXXFLAGS = $(AM_CXXFLAGS) $(BOOST_CFLAGS)
+@HAVE_BOOST_1_35_TRUE@boost_thread_LDADD = $(BOOST_LIBS)
+@HAVE_BUILTIN_ATOMIC_TRUE@annotate_smart_pointer_SOURCES = annotate_smart_pointer.cpp
+annotate_static_SOURCES = annotate_static.cpp
+@HAVE_OPENMP_TRUE@omp_matinv_CFLAGS = $(AM_CFLAGS) -fopenmp
+@HAVE_OPENMP_TRUE@omp_matinv_LDFLAGS = -fopenmp
+@HAVE_OPENMP_TRUE@omp_matinv_LDADD = $(LDADD) -lm
+@HAVE_OPENMP_TRUE@omp_prime_CFLAGS = $(AM_CFLAGS) -fopenmp
+@HAVE_OPENMP_TRUE@omp_prime_LDFLAGS = -fopenmp
+@HAVE_OPENMP_TRUE@omp_prime_LDADD = $(LDADD) -lm
+@HAVE_OPENMP_TRUE@omp_printf_CFLAGS = $(AM_CFLAGS) -fopenmp
+@HAVE_OPENMP_TRUE@omp_printf_LDFLAGS = -fopenmp
+@HAVE_OPENMP_TRUE@omp_printf_LDADD = $(LDADD) -lm
+@HAVE_PTHREAD_BARRIER_TRUE@matinv_LDADD = $(LDADD) -lm
+@HAVE_QTCORE_TRUE@qt4_mutex_SOURCES = qt4_mutex.cpp
+@HAVE_QTCORE_TRUE@qt4_mutex_CXXFLAGS = $(AM_CXXFLAGS) $(QTCORE_CFLAGS)
+@HAVE_QTCORE_TRUE@qt4_mutex_LDADD = $(LDADD) $(QTCORE_LIBS)
+@HAVE_QTCORE_TRUE@qt4_rwlock_SOURCES = qt4_rwlock.cpp
+@HAVE_QTCORE_TRUE@qt4_rwlock_CXXFLAGS = $(AM_CXXFLAGS) $(QTCORE_CFLAGS)
+@HAVE_QTCORE_TRUE@qt4_rwlock_LDADD = $(LDADD) $(QTCORE_LIBS)
+@HAVE_QTCORE_TRUE@qt4_semaphore_SOURCES = qt4_semaphore.cpp
+@HAVE_QTCORE_TRUE@qt4_semaphore_CXXFLAGS = $(AM_CXXFLAGS) $(QTCORE_CFLAGS)
+@HAVE_QTCORE_TRUE@qt4_semaphore_LDADD = $(LDADD) $(QTCORE_LIBS)
+@HAVE_QTCORE_QATOMICINT_TRUE@qt4_atomic_SOURCES = qt4_atomic.cpp
+@HAVE_QTCORE_QATOMICINT_TRUE@qt4_atomic_CXXFLAGS = $(AM_CXXFLAGS) $(QTCORE_CFLAGS)
+@HAVE_QTCORE_QATOMICINT_TRUE@qt4_atomic_LDADD = $(LDADD) $(QTCORE_LIBS)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.tool-tests.am $(top_srcdir)/Makefile.all.am $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign drd/tests/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign drd/tests/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-checkPROGRAMS:
+	-test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS)
+annotate_barrier$(EXEEXT): $(annotate_barrier_OBJECTS) $(annotate_barrier_DEPENDENCIES) 
+	@rm -f annotate_barrier$(EXEEXT)
+	$(LINK) $(annotate_barrier_OBJECTS) $(annotate_barrier_LDADD) $(LIBS)
+annotate_hb_err$(EXEEXT): $(annotate_hb_err_OBJECTS) $(annotate_hb_err_DEPENDENCIES) 
+	@rm -f annotate_hb_err$(EXEEXT)
+	$(LINK) $(annotate_hb_err_OBJECTS) $(annotate_hb_err_LDADD) $(LIBS)
+annotate_hb_race$(EXEEXT): $(annotate_hb_race_OBJECTS) $(annotate_hb_race_DEPENDENCIES) 
+	@rm -f annotate_hb_race$(EXEEXT)
+	$(LINK) $(annotate_hb_race_OBJECTS) $(annotate_hb_race_LDADD) $(LIBS)
+annotate_ignore_rw$(EXEEXT): $(annotate_ignore_rw_OBJECTS) $(annotate_ignore_rw_DEPENDENCIES) 
+	@rm -f annotate_ignore_rw$(EXEEXT)
+	$(LINK) $(annotate_ignore_rw_OBJECTS) $(annotate_ignore_rw_LDADD) $(LIBS)
+annotate_ignore_write$(EXEEXT): $(annotate_ignore_write_OBJECTS) $(annotate_ignore_write_DEPENDENCIES) 
+	@rm -f annotate_ignore_write$(EXEEXT)
+	$(LINK) $(annotate_ignore_write_OBJECTS) $(annotate_ignore_write_LDADD) $(LIBS)
+annotate_publish_hg$(EXEEXT): $(annotate_publish_hg_OBJECTS) $(annotate_publish_hg_DEPENDENCIES) 
+	@rm -f annotate_publish_hg$(EXEEXT)
+	$(LINK) $(annotate_publish_hg_OBJECTS) $(annotate_publish_hg_LDADD) $(LIBS)
+annotate_rwlock$(EXEEXT): $(annotate_rwlock_OBJECTS) $(annotate_rwlock_DEPENDENCIES) 
+	@rm -f annotate_rwlock$(EXEEXT)
+	$(LINK) $(annotate_rwlock_OBJECTS) $(annotate_rwlock_LDADD) $(LIBS)
+annotate_smart_pointer$(EXEEXT): $(annotate_smart_pointer_OBJECTS) $(annotate_smart_pointer_DEPENDENCIES) 
+	@rm -f annotate_smart_pointer$(EXEEXT)
+	$(CXXLINK) $(annotate_smart_pointer_OBJECTS) $(annotate_smart_pointer_LDADD) $(LIBS)
+annotate_static$(EXEEXT): $(annotate_static_OBJECTS) $(annotate_static_DEPENDENCIES) 
+	@rm -f annotate_static$(EXEEXT)
+	$(CXXLINK) $(annotate_static_OBJECTS) $(annotate_static_LDADD) $(LIBS)
+atomic_var$(EXEEXT): $(atomic_var_OBJECTS) $(atomic_var_DEPENDENCIES) 
+	@rm -f atomic_var$(EXEEXT)
+	$(LINK) $(atomic_var_OBJECTS) $(atomic_var_LDADD) $(LIBS)
+boost_thread$(EXEEXT): $(boost_thread_OBJECTS) $(boost_thread_DEPENDENCIES) 
+	@rm -f boost_thread$(EXEEXT)
+	$(boost_thread_LINK) $(boost_thread_OBJECTS) $(boost_thread_LDADD) $(LIBS)
+bug-235681$(EXEEXT): $(bug_235681_OBJECTS) $(bug_235681_DEPENDENCIES) 
+	@rm -f bug-235681$(EXEEXT)
+	$(LINK) $(bug_235681_OBJECTS) $(bug_235681_LDADD) $(LIBS)
+circular_buffer$(EXEEXT): $(circular_buffer_OBJECTS) $(circular_buffer_DEPENDENCIES) 
+	@rm -f circular_buffer$(EXEEXT)
+	$(LINK) $(circular_buffer_OBJECTS) $(circular_buffer_LDADD) $(LIBS)
+custom_alloc$(EXEEXT): $(custom_alloc_OBJECTS) $(custom_alloc_DEPENDENCIES) 
+	@rm -f custom_alloc$(EXEEXT)
+	$(LINK) $(custom_alloc_OBJECTS) $(custom_alloc_LDADD) $(LIBS)
+fp_race$(EXEEXT): $(fp_race_OBJECTS) $(fp_race_DEPENDENCIES) 
+	@rm -f fp_race$(EXEEXT)
+	$(LINK) $(fp_race_OBJECTS) $(fp_race_LDADD) $(LIBS)
+hold_lock$(EXEEXT): $(hold_lock_OBJECTS) $(hold_lock_DEPENDENCIES) 
+	@rm -f hold_lock$(EXEEXT)
+	$(LINK) $(hold_lock_OBJECTS) $(hold_lock_LDADD) $(LIBS)
+linuxthreads_det$(EXEEXT): $(linuxthreads_det_OBJECTS) $(linuxthreads_det_DEPENDENCIES) 
+	@rm -f linuxthreads_det$(EXEEXT)
+	$(LINK) $(linuxthreads_det_OBJECTS) $(linuxthreads_det_LDADD) $(LIBS)
+matinv$(EXEEXT): $(matinv_OBJECTS) $(matinv_DEPENDENCIES) 
+	@rm -f matinv$(EXEEXT)
+	$(LINK) $(matinv_OBJECTS) $(matinv_LDADD) $(LIBS)
+memory_allocation$(EXEEXT): $(memory_allocation_OBJECTS) $(memory_allocation_DEPENDENCIES) 
+	@rm -f memory_allocation$(EXEEXT)
+	$(LINK) $(memory_allocation_OBJECTS) $(memory_allocation_LDADD) $(LIBS)
+monitor_example$(EXEEXT): $(monitor_example_OBJECTS) $(monitor_example_DEPENDENCIES) 
+	@rm -f monitor_example$(EXEEXT)
+	$(CXXLINK) $(monitor_example_OBJECTS) $(monitor_example_LDADD) $(LIBS)
+new_delete$(EXEEXT): $(new_delete_OBJECTS) $(new_delete_DEPENDENCIES) 
+	@rm -f new_delete$(EXEEXT)
+	$(CXXLINK) $(new_delete_OBJECTS) $(new_delete_LDADD) $(LIBS)
+omp_matinv$(EXEEXT): $(omp_matinv_OBJECTS) $(omp_matinv_DEPENDENCIES) 
+	@rm -f omp_matinv$(EXEEXT)
+	$(omp_matinv_LINK) $(omp_matinv_OBJECTS) $(omp_matinv_LDADD) $(LIBS)
+omp_prime$(EXEEXT): $(omp_prime_OBJECTS) $(omp_prime_DEPENDENCIES) 
+	@rm -f omp_prime$(EXEEXT)
+	$(omp_prime_LINK) $(omp_prime_OBJECTS) $(omp_prime_LDADD) $(LIBS)
+omp_printf$(EXEEXT): $(omp_printf_OBJECTS) $(omp_printf_DEPENDENCIES) 
+	@rm -f omp_printf$(EXEEXT)
+	$(omp_printf_LINK) $(omp_printf_OBJECTS) $(omp_printf_LDADD) $(LIBS)
+pth_barrier$(EXEEXT): $(pth_barrier_OBJECTS) $(pth_barrier_DEPENDENCIES) 
+	@rm -f pth_barrier$(EXEEXT)
+	$(LINK) $(pth_barrier_OBJECTS) $(pth_barrier_LDADD) $(LIBS)
+pth_barrier_race$(EXEEXT): $(pth_barrier_race_OBJECTS) $(pth_barrier_race_DEPENDENCIES) 
+	@rm -f pth_barrier_race$(EXEEXT)
+	$(LINK) $(pth_barrier_race_OBJECTS) $(pth_barrier_race_LDADD) $(LIBS)
+pth_barrier_reinit$(EXEEXT): $(pth_barrier_reinit_OBJECTS) $(pth_barrier_reinit_DEPENDENCIES) 
+	@rm -f pth_barrier_reinit$(EXEEXT)
+	$(LINK) $(pth_barrier_reinit_OBJECTS) $(pth_barrier_reinit_LDADD) $(LIBS)
+pth_broadcast$(EXEEXT): $(pth_broadcast_OBJECTS) $(pth_broadcast_DEPENDENCIES) 
+	@rm -f pth_broadcast$(EXEEXT)
+	$(LINK) $(pth_broadcast_OBJECTS) $(pth_broadcast_LDADD) $(LIBS)
+pth_cancel_locked$(EXEEXT): $(pth_cancel_locked_OBJECTS) $(pth_cancel_locked_DEPENDENCIES) 
+	@rm -f pth_cancel_locked$(EXEEXT)
+	$(LINK) $(pth_cancel_locked_OBJECTS) $(pth_cancel_locked_LDADD) $(LIBS)
+pth_cleanup_handler$(EXEEXT): $(pth_cleanup_handler_OBJECTS) $(pth_cleanup_handler_DEPENDENCIES) 
+	@rm -f pth_cleanup_handler$(EXEEXT)
+	$(pth_cleanup_handler_LINK) $(pth_cleanup_handler_OBJECTS) $(pth_cleanup_handler_LDADD) $(LIBS)
+pth_cond_race$(EXEEXT): $(pth_cond_race_OBJECTS) $(pth_cond_race_DEPENDENCIES) 
+	@rm -f pth_cond_race$(EXEEXT)
+	$(LINK) $(pth_cond_race_OBJECTS) $(pth_cond_race_LDADD) $(LIBS)
+pth_create_chain$(EXEEXT): $(pth_create_chain_OBJECTS) $(pth_create_chain_DEPENDENCIES) 
+	@rm -f pth_create_chain$(EXEEXT)
+	$(LINK) $(pth_create_chain_OBJECTS) $(pth_create_chain_LDADD) $(LIBS)
+pth_create_glibc_2_0$(EXEEXT): $(pth_create_glibc_2_0_OBJECTS) $(pth_create_glibc_2_0_DEPENDENCIES) 
+	@rm -f pth_create_glibc_2_0$(EXEEXT)
+	$(LINK) $(pth_create_glibc_2_0_OBJECTS) $(pth_create_glibc_2_0_LDADD) $(LIBS)
+pth_detached$(EXEEXT): $(pth_detached_OBJECTS) $(pth_detached_DEPENDENCIES) 
+	@rm -f pth_detached$(EXEEXT)
+	$(LINK) $(pth_detached_OBJECTS) $(pth_detached_LDADD) $(LIBS)
+pth_detached_sem$(EXEEXT): $(pth_detached_sem_OBJECTS) $(pth_detached_sem_DEPENDENCIES) 
+	@rm -f pth_detached_sem$(EXEEXT)
+	$(LINK) $(pth_detached_sem_OBJECTS) $(pth_detached_sem_LDADD) $(LIBS)
+pth_inconsistent_cond_wait$(EXEEXT): $(pth_inconsistent_cond_wait_OBJECTS) $(pth_inconsistent_cond_wait_DEPENDENCIES) 
+	@rm -f pth_inconsistent_cond_wait$(EXEEXT)
+	$(LINK) $(pth_inconsistent_cond_wait_OBJECTS) $(pth_inconsistent_cond_wait_LDADD) $(LIBS)
+pth_mutex_reinit$(EXEEXT): $(pth_mutex_reinit_OBJECTS) $(pth_mutex_reinit_DEPENDENCIES) 
+	@rm -f pth_mutex_reinit$(EXEEXT)
+	$(LINK) $(pth_mutex_reinit_OBJECTS) $(pth_mutex_reinit_LDADD) $(LIBS)
+pth_process_shared_mutex$(EXEEXT): $(pth_process_shared_mutex_OBJECTS) $(pth_process_shared_mutex_DEPENDENCIES) 
+	@rm -f pth_process_shared_mutex$(EXEEXT)
+	$(LINK) $(pth_process_shared_mutex_OBJECTS) $(pth_process_shared_mutex_LDADD) $(LIBS)
+pth_spinlock$(EXEEXT): $(pth_spinlock_OBJECTS) $(pth_spinlock_DEPENDENCIES) 
+	@rm -f pth_spinlock$(EXEEXT)
+	$(LINK) $(pth_spinlock_OBJECTS) $(pth_spinlock_LDADD) $(LIBS)
+pth_uninitialized_cond$(EXEEXT): $(pth_uninitialized_cond_OBJECTS) $(pth_uninitialized_cond_DEPENDENCIES) 
+	@rm -f pth_uninitialized_cond$(EXEEXT)
+	$(LINK) $(pth_uninitialized_cond_OBJECTS) $(pth_uninitialized_cond_LDADD) $(LIBS)
+qt4_atomic$(EXEEXT): $(qt4_atomic_OBJECTS) $(qt4_atomic_DEPENDENCIES) 
+	@rm -f qt4_atomic$(EXEEXT)
+	$(qt4_atomic_LINK) $(qt4_atomic_OBJECTS) $(qt4_atomic_LDADD) $(LIBS)
+qt4_mutex$(EXEEXT): $(qt4_mutex_OBJECTS) $(qt4_mutex_DEPENDENCIES) 
+	@rm -f qt4_mutex$(EXEEXT)
+	$(qt4_mutex_LINK) $(qt4_mutex_OBJECTS) $(qt4_mutex_LDADD) $(LIBS)
+qt4_rwlock$(EXEEXT): $(qt4_rwlock_OBJECTS) $(qt4_rwlock_DEPENDENCIES) 
+	@rm -f qt4_rwlock$(EXEEXT)
+	$(qt4_rwlock_LINK) $(qt4_rwlock_OBJECTS) $(qt4_rwlock_LDADD) $(LIBS)
+qt4_semaphore$(EXEEXT): $(qt4_semaphore_OBJECTS) $(qt4_semaphore_DEPENDENCIES) 
+	@rm -f qt4_semaphore$(EXEEXT)
+	$(qt4_semaphore_LINK) $(qt4_semaphore_OBJECTS) $(qt4_semaphore_LDADD) $(LIBS)
+read_after_free$(EXEEXT): $(read_after_free_OBJECTS) $(read_after_free_DEPENDENCIES) 
+	@rm -f read_after_free$(EXEEXT)
+	$(LINK) $(read_after_free_OBJECTS) $(read_after_free_LDADD) $(LIBS)
+recursive_mutex$(EXEEXT): $(recursive_mutex_OBJECTS) $(recursive_mutex_DEPENDENCIES) 
+	@rm -f recursive_mutex$(EXEEXT)
+	$(LINK) $(recursive_mutex_OBJECTS) $(recursive_mutex_LDADD) $(LIBS)
+rwlock_race$(EXEEXT): $(rwlock_race_OBJECTS) $(rwlock_race_DEPENDENCIES) 
+	@rm -f rwlock_race$(EXEEXT)
+	$(LINK) $(rwlock_race_OBJECTS) $(rwlock_race_LDADD) $(LIBS)
+rwlock_test$(EXEEXT): $(rwlock_test_OBJECTS) $(rwlock_test_DEPENDENCIES) 
+	@rm -f rwlock_test$(EXEEXT)
+	$(LINK) $(rwlock_test_OBJECTS) $(rwlock_test_LDADD) $(LIBS)
+rwlock_type_checking$(EXEEXT): $(rwlock_type_checking_OBJECTS) $(rwlock_type_checking_DEPENDENCIES) 
+	@rm -f rwlock_type_checking$(EXEEXT)
+	$(LINK) $(rwlock_type_checking_OBJECTS) $(rwlock_type_checking_LDADD) $(LIBS)
+sem_as_mutex$(EXEEXT): $(sem_as_mutex_OBJECTS) $(sem_as_mutex_DEPENDENCIES) 
+	@rm -f sem_as_mutex$(EXEEXT)
+	$(LINK) $(sem_as_mutex_OBJECTS) $(sem_as_mutex_LDADD) $(LIBS)
+sem_open$(EXEEXT): $(sem_open_OBJECTS) $(sem_open_DEPENDENCIES) 
+	@rm -f sem_open$(EXEEXT)
+	$(LINK) $(sem_open_OBJECTS) $(sem_open_LDADD) $(LIBS)
+sigalrm$(EXEEXT): $(sigalrm_OBJECTS) $(sigalrm_DEPENDENCIES) 
+	@rm -f sigalrm$(EXEEXT)
+	$(LINK) $(sigalrm_OBJECTS) $(sigalrm_LDADD) $(LIBS)
+thread_name$(EXEEXT): $(thread_name_OBJECTS) $(thread_name_DEPENDENCIES) 
+	@rm -f thread_name$(EXEEXT)
+	$(LINK) $(thread_name_OBJECTS) $(thread_name_LDADD) $(LIBS)
+trylock$(EXEEXT): $(trylock_OBJECTS) $(trylock_DEPENDENCIES) 
+	@rm -f trylock$(EXEEXT)
+	$(LINK) $(trylock_OBJECTS) $(trylock_LDADD) $(LIBS)
+tsan_unittest$(EXEEXT): $(tsan_unittest_OBJECTS) $(tsan_unittest_DEPENDENCIES) 
+	@rm -f tsan_unittest$(EXEEXT)
+	$(tsan_unittest_LINK) $(tsan_unittest_OBJECTS) $(tsan_unittest_LDADD) $(LIBS)
+unit_bitmap$(EXEEXT): $(unit_bitmap_OBJECTS) $(unit_bitmap_DEPENDENCIES) 
+	@rm -f unit_bitmap$(EXEEXT)
+	$(unit_bitmap_LINK) $(unit_bitmap_OBJECTS) $(unit_bitmap_LDADD) $(LIBS)
+unit_vc$(EXEEXT): $(unit_vc_OBJECTS) $(unit_vc_DEPENDENCIES) 
+	@rm -f unit_vc$(EXEEXT)
+	$(unit_vc_LINK) $(unit_vc_OBJECTS) $(unit_vc_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/annotate_barrier.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/annotate_hb_err.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/annotate_hb_race.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/annotate_ignore_rw.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/annotate_ignore_write.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/annotate_publish_hg.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/annotate_rwlock.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/annotate_smart_pointer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/annotate_static.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atomic_var.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/boost_thread-boost_thread.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug-235681.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/circular_buffer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/custom_alloc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fp_race.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hold_lock.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/linuxthreads_det.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/matinv.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memory_allocation.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/monitor_example.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/new_delete.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omp_matinv-omp_matinv.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omp_prime-omp_prime.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omp_printf-omp_printf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pth_barrier.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pth_barrier_race.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pth_barrier_reinit.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pth_broadcast.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pth_cancel_locked.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pth_cleanup_handler-pth_cleanup_handler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pth_cond_race.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pth_create_chain.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pth_create_glibc_2_0.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pth_detached.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pth_detached_sem.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pth_inconsistent_cond_wait.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pth_mutex_reinit.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pth_process_shared_mutex.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pth_spinlock.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pth_uninitialized_cond.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qt4_atomic-qt4_atomic.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qt4_mutex-qt4_mutex.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qt4_rwlock-qt4_rwlock.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qt4_semaphore-qt4_semaphore.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/read_after_free.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/recursive_mutex.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rwlock_race.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rwlock_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rwlock_type_checking.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sem_as_mutex.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sem_open.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sigalrm.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread_name.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trylock.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_unittest-tsan_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unit_bitmap-unit_bitmap.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unit_vc-unit_vc.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+omp_matinv-omp_matinv.o: omp_matinv.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omp_matinv_CFLAGS) $(CFLAGS) -MT omp_matinv-omp_matinv.o -MD -MP -MF $(DEPDIR)/omp_matinv-omp_matinv.Tpo -c -o omp_matinv-omp_matinv.o `test -f 'omp_matinv.c' || echo '$(srcdir)/'`omp_matinv.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/omp_matinv-omp_matinv.Tpo $(DEPDIR)/omp_matinv-omp_matinv.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='omp_matinv.c' object='omp_matinv-omp_matinv.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omp_matinv_CFLAGS) $(CFLAGS) -c -o omp_matinv-omp_matinv.o `test -f 'omp_matinv.c' || echo '$(srcdir)/'`omp_matinv.c
+
+omp_matinv-omp_matinv.obj: omp_matinv.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omp_matinv_CFLAGS) $(CFLAGS) -MT omp_matinv-omp_matinv.obj -MD -MP -MF $(DEPDIR)/omp_matinv-omp_matinv.Tpo -c -o omp_matinv-omp_matinv.obj `if test -f 'omp_matinv.c'; then $(CYGPATH_W) 'omp_matinv.c'; else $(CYGPATH_W) '$(srcdir)/omp_matinv.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/omp_matinv-omp_matinv.Tpo $(DEPDIR)/omp_matinv-omp_matinv.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='omp_matinv.c' object='omp_matinv-omp_matinv.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omp_matinv_CFLAGS) $(CFLAGS) -c -o omp_matinv-omp_matinv.obj `if test -f 'omp_matinv.c'; then $(CYGPATH_W) 'omp_matinv.c'; else $(CYGPATH_W) '$(srcdir)/omp_matinv.c'; fi`
+
+omp_prime-omp_prime.o: omp_prime.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omp_prime_CFLAGS) $(CFLAGS) -MT omp_prime-omp_prime.o -MD -MP -MF $(DEPDIR)/omp_prime-omp_prime.Tpo -c -o omp_prime-omp_prime.o `test -f 'omp_prime.c' || echo '$(srcdir)/'`omp_prime.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/omp_prime-omp_prime.Tpo $(DEPDIR)/omp_prime-omp_prime.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='omp_prime.c' object='omp_prime-omp_prime.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omp_prime_CFLAGS) $(CFLAGS) -c -o omp_prime-omp_prime.o `test -f 'omp_prime.c' || echo '$(srcdir)/'`omp_prime.c
+
+omp_prime-omp_prime.obj: omp_prime.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omp_prime_CFLAGS) $(CFLAGS) -MT omp_prime-omp_prime.obj -MD -MP -MF $(DEPDIR)/omp_prime-omp_prime.Tpo -c -o omp_prime-omp_prime.obj `if test -f 'omp_prime.c'; then $(CYGPATH_W) 'omp_prime.c'; else $(CYGPATH_W) '$(srcdir)/omp_prime.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/omp_prime-omp_prime.Tpo $(DEPDIR)/omp_prime-omp_prime.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='omp_prime.c' object='omp_prime-omp_prime.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omp_prime_CFLAGS) $(CFLAGS) -c -o omp_prime-omp_prime.obj `if test -f 'omp_prime.c'; then $(CYGPATH_W) 'omp_prime.c'; else $(CYGPATH_W) '$(srcdir)/omp_prime.c'; fi`
+
+omp_printf-omp_printf.o: omp_printf.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omp_printf_CFLAGS) $(CFLAGS) -MT omp_printf-omp_printf.o -MD -MP -MF $(DEPDIR)/omp_printf-omp_printf.Tpo -c -o omp_printf-omp_printf.o `test -f 'omp_printf.c' || echo '$(srcdir)/'`omp_printf.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/omp_printf-omp_printf.Tpo $(DEPDIR)/omp_printf-omp_printf.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='omp_printf.c' object='omp_printf-omp_printf.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omp_printf_CFLAGS) $(CFLAGS) -c -o omp_printf-omp_printf.o `test -f 'omp_printf.c' || echo '$(srcdir)/'`omp_printf.c
+
+omp_printf-omp_printf.obj: omp_printf.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omp_printf_CFLAGS) $(CFLAGS) -MT omp_printf-omp_printf.obj -MD -MP -MF $(DEPDIR)/omp_printf-omp_printf.Tpo -c -o omp_printf-omp_printf.obj `if test -f 'omp_printf.c'; then $(CYGPATH_W) 'omp_printf.c'; else $(CYGPATH_W) '$(srcdir)/omp_printf.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/omp_printf-omp_printf.Tpo $(DEPDIR)/omp_printf-omp_printf.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='omp_printf.c' object='omp_printf-omp_printf.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(omp_printf_CFLAGS) $(CFLAGS) -c -o omp_printf-omp_printf.obj `if test -f 'omp_printf.c'; then $(CYGPATH_W) 'omp_printf.c'; else $(CYGPATH_W) '$(srcdir)/omp_printf.c'; fi`
+
+pth_cleanup_handler-pth_cleanup_handler.o: pth_cleanup_handler.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pth_cleanup_handler_CFLAGS) $(CFLAGS) -MT pth_cleanup_handler-pth_cleanup_handler.o -MD -MP -MF $(DEPDIR)/pth_cleanup_handler-pth_cleanup_handler.Tpo -c -o pth_cleanup_handler-pth_cleanup_handler.o `test -f 'pth_cleanup_handler.c' || echo '$(srcdir)/'`pth_cleanup_handler.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/pth_cleanup_handler-pth_cleanup_handler.Tpo $(DEPDIR)/pth_cleanup_handler-pth_cleanup_handler.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='pth_cleanup_handler.c' object='pth_cleanup_handler-pth_cleanup_handler.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pth_cleanup_handler_CFLAGS) $(CFLAGS) -c -o pth_cleanup_handler-pth_cleanup_handler.o `test -f 'pth_cleanup_handler.c' || echo '$(srcdir)/'`pth_cleanup_handler.c
+
+pth_cleanup_handler-pth_cleanup_handler.obj: pth_cleanup_handler.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pth_cleanup_handler_CFLAGS) $(CFLAGS) -MT pth_cleanup_handler-pth_cleanup_handler.obj -MD -MP -MF $(DEPDIR)/pth_cleanup_handler-pth_cleanup_handler.Tpo -c -o pth_cleanup_handler-pth_cleanup_handler.obj `if test -f 'pth_cleanup_handler.c'; then $(CYGPATH_W) 'pth_cleanup_handler.c'; else $(CYGPATH_W) '$(srcdir)/pth_cleanup_handler.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/pth_cleanup_handler-pth_cleanup_handler.Tpo $(DEPDIR)/pth_cleanup_handler-pth_cleanup_handler.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='pth_cleanup_handler.c' object='pth_cleanup_handler-pth_cleanup_handler.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pth_cleanup_handler_CFLAGS) $(CFLAGS) -c -o pth_cleanup_handler-pth_cleanup_handler.obj `if test -f 'pth_cleanup_handler.c'; then $(CYGPATH_W) 'pth_cleanup_handler.c'; else $(CYGPATH_W) '$(srcdir)/pth_cleanup_handler.c'; fi`
+
+unit_bitmap-unit_bitmap.o: unit_bitmap.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unit_bitmap_CFLAGS) $(CFLAGS) -MT unit_bitmap-unit_bitmap.o -MD -MP -MF $(DEPDIR)/unit_bitmap-unit_bitmap.Tpo -c -o unit_bitmap-unit_bitmap.o `test -f 'unit_bitmap.c' || echo '$(srcdir)/'`unit_bitmap.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/unit_bitmap-unit_bitmap.Tpo $(DEPDIR)/unit_bitmap-unit_bitmap.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='unit_bitmap.c' object='unit_bitmap-unit_bitmap.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unit_bitmap_CFLAGS) $(CFLAGS) -c -o unit_bitmap-unit_bitmap.o `test -f 'unit_bitmap.c' || echo '$(srcdir)/'`unit_bitmap.c
+
+unit_bitmap-unit_bitmap.obj: unit_bitmap.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unit_bitmap_CFLAGS) $(CFLAGS) -MT unit_bitmap-unit_bitmap.obj -MD -MP -MF $(DEPDIR)/unit_bitmap-unit_bitmap.Tpo -c -o unit_bitmap-unit_bitmap.obj `if test -f 'unit_bitmap.c'; then $(CYGPATH_W) 'unit_bitmap.c'; else $(CYGPATH_W) '$(srcdir)/unit_bitmap.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/unit_bitmap-unit_bitmap.Tpo $(DEPDIR)/unit_bitmap-unit_bitmap.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='unit_bitmap.c' object='unit_bitmap-unit_bitmap.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unit_bitmap_CFLAGS) $(CFLAGS) -c -o unit_bitmap-unit_bitmap.obj `if test -f 'unit_bitmap.c'; then $(CYGPATH_W) 'unit_bitmap.c'; else $(CYGPATH_W) '$(srcdir)/unit_bitmap.c'; fi`
+
+unit_vc-unit_vc.o: unit_vc.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unit_vc_CFLAGS) $(CFLAGS) -MT unit_vc-unit_vc.o -MD -MP -MF $(DEPDIR)/unit_vc-unit_vc.Tpo -c -o unit_vc-unit_vc.o `test -f 'unit_vc.c' || echo '$(srcdir)/'`unit_vc.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/unit_vc-unit_vc.Tpo $(DEPDIR)/unit_vc-unit_vc.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='unit_vc.c' object='unit_vc-unit_vc.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unit_vc_CFLAGS) $(CFLAGS) -c -o unit_vc-unit_vc.o `test -f 'unit_vc.c' || echo '$(srcdir)/'`unit_vc.c
+
+unit_vc-unit_vc.obj: unit_vc.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unit_vc_CFLAGS) $(CFLAGS) -MT unit_vc-unit_vc.obj -MD -MP -MF $(DEPDIR)/unit_vc-unit_vc.Tpo -c -o unit_vc-unit_vc.obj `if test -f 'unit_vc.c'; then $(CYGPATH_W) 'unit_vc.c'; else $(CYGPATH_W) '$(srcdir)/unit_vc.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/unit_vc-unit_vc.Tpo $(DEPDIR)/unit_vc-unit_vc.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='unit_vc.c' object='unit_vc-unit_vc.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unit_vc_CFLAGS) $(CFLAGS) -c -o unit_vc-unit_vc.obj `if test -f 'unit_vc.c'; then $(CYGPATH_W) 'unit_vc.c'; else $(CYGPATH_W) '$(srcdir)/unit_vc.c'; fi`
+
+.cpp.o:
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+boost_thread-boost_thread.o: boost_thread.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(boost_thread_CXXFLAGS) $(CXXFLAGS) -MT boost_thread-boost_thread.o -MD -MP -MF $(DEPDIR)/boost_thread-boost_thread.Tpo -c -o boost_thread-boost_thread.o `test -f 'boost_thread.cpp' || echo '$(srcdir)/'`boost_thread.cpp
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/boost_thread-boost_thread.Tpo $(DEPDIR)/boost_thread-boost_thread.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='boost_thread.cpp' object='boost_thread-boost_thread.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(boost_thread_CXXFLAGS) $(CXXFLAGS) -c -o boost_thread-boost_thread.o `test -f 'boost_thread.cpp' || echo '$(srcdir)/'`boost_thread.cpp
+
+boost_thread-boost_thread.obj: boost_thread.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(boost_thread_CXXFLAGS) $(CXXFLAGS) -MT boost_thread-boost_thread.obj -MD -MP -MF $(DEPDIR)/boost_thread-boost_thread.Tpo -c -o boost_thread-boost_thread.obj `if test -f 'boost_thread.cpp'; then $(CYGPATH_W) 'boost_thread.cpp'; else $(CYGPATH_W) '$(srcdir)/boost_thread.cpp'; fi`
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/boost_thread-boost_thread.Tpo $(DEPDIR)/boost_thread-boost_thread.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='boost_thread.cpp' object='boost_thread-boost_thread.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(boost_thread_CXXFLAGS) $(CXXFLAGS) -c -o boost_thread-boost_thread.obj `if test -f 'boost_thread.cpp'; then $(CYGPATH_W) 'boost_thread.cpp'; else $(CYGPATH_W) '$(srcdir)/boost_thread.cpp'; fi`
+
+qt4_atomic-qt4_atomic.o: qt4_atomic.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(qt4_atomic_CXXFLAGS) $(CXXFLAGS) -MT qt4_atomic-qt4_atomic.o -MD -MP -MF $(DEPDIR)/qt4_atomic-qt4_atomic.Tpo -c -o qt4_atomic-qt4_atomic.o `test -f 'qt4_atomic.cpp' || echo '$(srcdir)/'`qt4_atomic.cpp
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/qt4_atomic-qt4_atomic.Tpo $(DEPDIR)/qt4_atomic-qt4_atomic.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='qt4_atomic.cpp' object='qt4_atomic-qt4_atomic.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(qt4_atomic_CXXFLAGS) $(CXXFLAGS) -c -o qt4_atomic-qt4_atomic.o `test -f 'qt4_atomic.cpp' || echo '$(srcdir)/'`qt4_atomic.cpp
+
+qt4_atomic-qt4_atomic.obj: qt4_atomic.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(qt4_atomic_CXXFLAGS) $(CXXFLAGS) -MT qt4_atomic-qt4_atomic.obj -MD -MP -MF $(DEPDIR)/qt4_atomic-qt4_atomic.Tpo -c -o qt4_atomic-qt4_atomic.obj `if test -f 'qt4_atomic.cpp'; then $(CYGPATH_W) 'qt4_atomic.cpp'; else $(CYGPATH_W) '$(srcdir)/qt4_atomic.cpp'; fi`
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/qt4_atomic-qt4_atomic.Tpo $(DEPDIR)/qt4_atomic-qt4_atomic.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='qt4_atomic.cpp' object='qt4_atomic-qt4_atomic.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(qt4_atomic_CXXFLAGS) $(CXXFLAGS) -c -o qt4_atomic-qt4_atomic.obj `if test -f 'qt4_atomic.cpp'; then $(CYGPATH_W) 'qt4_atomic.cpp'; else $(CYGPATH_W) '$(srcdir)/qt4_atomic.cpp'; fi`
+
+qt4_mutex-qt4_mutex.o: qt4_mutex.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(qt4_mutex_CXXFLAGS) $(CXXFLAGS) -MT qt4_mutex-qt4_mutex.o -MD -MP -MF $(DEPDIR)/qt4_mutex-qt4_mutex.Tpo -c -o qt4_mutex-qt4_mutex.o `test -f 'qt4_mutex.cpp' || echo '$(srcdir)/'`qt4_mutex.cpp
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/qt4_mutex-qt4_mutex.Tpo $(DEPDIR)/qt4_mutex-qt4_mutex.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='qt4_mutex.cpp' object='qt4_mutex-qt4_mutex.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(qt4_mutex_CXXFLAGS) $(CXXFLAGS) -c -o qt4_mutex-qt4_mutex.o `test -f 'qt4_mutex.cpp' || echo '$(srcdir)/'`qt4_mutex.cpp
+
+qt4_mutex-qt4_mutex.obj: qt4_mutex.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(qt4_mutex_CXXFLAGS) $(CXXFLAGS) -MT qt4_mutex-qt4_mutex.obj -MD -MP -MF $(DEPDIR)/qt4_mutex-qt4_mutex.Tpo -c -o qt4_mutex-qt4_mutex.obj `if test -f 'qt4_mutex.cpp'; then $(CYGPATH_W) 'qt4_mutex.cpp'; else $(CYGPATH_W) '$(srcdir)/qt4_mutex.cpp'; fi`
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/qt4_mutex-qt4_mutex.Tpo $(DEPDIR)/qt4_mutex-qt4_mutex.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='qt4_mutex.cpp' object='qt4_mutex-qt4_mutex.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(qt4_mutex_CXXFLAGS) $(CXXFLAGS) -c -o qt4_mutex-qt4_mutex.obj `if test -f 'qt4_mutex.cpp'; then $(CYGPATH_W) 'qt4_mutex.cpp'; else $(CYGPATH_W) '$(srcdir)/qt4_mutex.cpp'; fi`
+
+qt4_rwlock-qt4_rwlock.o: qt4_rwlock.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(qt4_rwlock_CXXFLAGS) $(CXXFLAGS) -MT qt4_rwlock-qt4_rwlock.o -MD -MP -MF $(DEPDIR)/qt4_rwlock-qt4_rwlock.Tpo -c -o qt4_rwlock-qt4_rwlock.o `test -f 'qt4_rwlock.cpp' || echo '$(srcdir)/'`qt4_rwlock.cpp
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/qt4_rwlock-qt4_rwlock.Tpo $(DEPDIR)/qt4_rwlock-qt4_rwlock.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='qt4_rwlock.cpp' object='qt4_rwlock-qt4_rwlock.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(qt4_rwlock_CXXFLAGS) $(CXXFLAGS) -c -o qt4_rwlock-qt4_rwlock.o `test -f 'qt4_rwlock.cpp' || echo '$(srcdir)/'`qt4_rwlock.cpp
+
+qt4_rwlock-qt4_rwlock.obj: qt4_rwlock.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(qt4_rwlock_CXXFLAGS) $(CXXFLAGS) -MT qt4_rwlock-qt4_rwlock.obj -MD -MP -MF $(DEPDIR)/qt4_rwlock-qt4_rwlock.Tpo -c -o qt4_rwlock-qt4_rwlock.obj `if test -f 'qt4_rwlock.cpp'; then $(CYGPATH_W) 'qt4_rwlock.cpp'; else $(CYGPATH_W) '$(srcdir)/qt4_rwlock.cpp'; fi`
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/qt4_rwlock-qt4_rwlock.Tpo $(DEPDIR)/qt4_rwlock-qt4_rwlock.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='qt4_rwlock.cpp' object='qt4_rwlock-qt4_rwlock.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(qt4_rwlock_CXXFLAGS) $(CXXFLAGS) -c -o qt4_rwlock-qt4_rwlock.obj `if test -f 'qt4_rwlock.cpp'; then $(CYGPATH_W) 'qt4_rwlock.cpp'; else $(CYGPATH_W) '$(srcdir)/qt4_rwlock.cpp'; fi`
+
+qt4_semaphore-qt4_semaphore.o: qt4_semaphore.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(qt4_semaphore_CXXFLAGS) $(CXXFLAGS) -MT qt4_semaphore-qt4_semaphore.o -MD -MP -MF $(DEPDIR)/qt4_semaphore-qt4_semaphore.Tpo -c -o qt4_semaphore-qt4_semaphore.o `test -f 'qt4_semaphore.cpp' || echo '$(srcdir)/'`qt4_semaphore.cpp
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/qt4_semaphore-qt4_semaphore.Tpo $(DEPDIR)/qt4_semaphore-qt4_semaphore.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='qt4_semaphore.cpp' object='qt4_semaphore-qt4_semaphore.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(qt4_semaphore_CXXFLAGS) $(CXXFLAGS) -c -o qt4_semaphore-qt4_semaphore.o `test -f 'qt4_semaphore.cpp' || echo '$(srcdir)/'`qt4_semaphore.cpp
+
+qt4_semaphore-qt4_semaphore.obj: qt4_semaphore.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(qt4_semaphore_CXXFLAGS) $(CXXFLAGS) -MT qt4_semaphore-qt4_semaphore.obj -MD -MP -MF $(DEPDIR)/qt4_semaphore-qt4_semaphore.Tpo -c -o qt4_semaphore-qt4_semaphore.obj `if test -f 'qt4_semaphore.cpp'; then $(CYGPATH_W) 'qt4_semaphore.cpp'; else $(CYGPATH_W) '$(srcdir)/qt4_semaphore.cpp'; fi`
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/qt4_semaphore-qt4_semaphore.Tpo $(DEPDIR)/qt4_semaphore-qt4_semaphore.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='qt4_semaphore.cpp' object='qt4_semaphore-qt4_semaphore.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(qt4_semaphore_CXXFLAGS) $(CXXFLAGS) -c -o qt4_semaphore-qt4_semaphore.obj `if test -f 'qt4_semaphore.cpp'; then $(CYGPATH_W) 'qt4_semaphore.cpp'; else $(CYGPATH_W) '$(srcdir)/qt4_semaphore.cpp'; fi`
+
+tsan_unittest-tsan_unittest.o: tsan_unittest.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tsan_unittest_CXXFLAGS) $(CXXFLAGS) -MT tsan_unittest-tsan_unittest.o -MD -MP -MF $(DEPDIR)/tsan_unittest-tsan_unittest.Tpo -c -o tsan_unittest-tsan_unittest.o `test -f 'tsan_unittest.cpp' || echo '$(srcdir)/'`tsan_unittest.cpp
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/tsan_unittest-tsan_unittest.Tpo $(DEPDIR)/tsan_unittest-tsan_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='tsan_unittest.cpp' object='tsan_unittest-tsan_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tsan_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tsan_unittest-tsan_unittest.o `test -f 'tsan_unittest.cpp' || echo '$(srcdir)/'`tsan_unittest.cpp
+
+tsan_unittest-tsan_unittest.obj: tsan_unittest.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tsan_unittest_CXXFLAGS) $(CXXFLAGS) -MT tsan_unittest-tsan_unittest.obj -MD -MP -MF $(DEPDIR)/tsan_unittest-tsan_unittest.Tpo -c -o tsan_unittest-tsan_unittest.obj `if test -f 'tsan_unittest.cpp'; then $(CYGPATH_W) 'tsan_unittest.cpp'; else $(CYGPATH_W) '$(srcdir)/tsan_unittest.cpp'; fi`
+@am__fastdepCXX_TRUE@	$(am__mv) $(DEPDIR)/tsan_unittest-tsan_unittest.Tpo $(DEPDIR)/tsan_unittest-tsan_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='tsan_unittest.cpp' object='tsan_unittest-tsan_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tsan_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tsan_unittest-tsan_unittest.obj `if test -f 'tsan_unittest.cpp'; then $(CYGPATH_W) 'tsan_unittest.cpp'; else $(CYGPATH_W) '$(srcdir)/tsan_unittest.cpp'; fi`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	set x; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+	$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+	$(MAKE) $(AM_MAKEFLAGS) check-local
+check: check-am
+all-am: Makefile $(SCRIPTS) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-checkPROGRAMS clean-generic clean-local mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am check-local clean \
+	clean-checkPROGRAMS clean-generic clean-local ctags distclean \
+	distclean-compile distclean-generic distclean-tags distdir dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-dvi install-dvi-am \
+	install-exec install-exec-am install-html install-html-am \
+	install-info install-info-am install-man install-pdf \
+	install-pdf-am install-ps install-ps-am install-strip \
+	installcheck installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+	uninstall-am
+
+
+# This used to be required when Vex had a handwritten Makefile.  It
+# shouldn't be needed any more, though.
+
+#----------------------------------------------------------------------------
+# noinst_PROGRAMS and noinst_DSYMS targets
+#----------------------------------------------------------------------------
+
+# On Darwin, for a program 'p', the DWARF debug info is stored in the
+# directory 'p.dSYM'.  This must be generated after the executable is
+# created, with 'dsymutil p'.  We could redefine LINK with a script that
+# executes 'dsymutil' after linking, but that's a pain.  Instead we use this
+# hook so that every time "make check" is run, we subsequently invoke
+# 'dsymutil' on all the executables that lack a .dSYM directory, or that are
+# newer than their corresponding .dSYM directory.
+build-noinst_DSYMS: $(noinst_DSYMS)
+	for f in $(noinst_DSYMS); do \
+	  if [ ! -e $$f.dSYM  -o  $$f -nt $$f.dSYM ] ; then \
+	      echo "dsymutil $$f"; \
+	      dsymutil $$f; \
+	  fi; \
+	done
+
+# This is used by coregrind/Makefile.am and Makefile.tool.am for doing
+# "in-place" installs.  It copies $(noinst_PROGRAMS) into $inplacedir.
+# It needs to be depended on by an 'all-local' rule.
+inplace-noinst_PROGRAMS: $(noinst_PROGRAMS)
+	mkdir -p $(inplacedir); \
+	for f in $(noinst_PROGRAMS) ; do \
+	  rm -f $(inplacedir)/$$f; \
+	  ln -f -s ../$(subdir)/$$f $(inplacedir); \
+	done
+
+# Similar to inplace-noinst_PROGRAMS
+inplace-noinst_DSYMS: build-noinst_DSYMS
+	mkdir -p $(inplacedir); \
+	for f in $(noinst_DSYMS); do \
+	  rm -f $(inplacedir)/$$f.dSYM; \
+	  ln -f -s ../$(subdir)/$$f.dSYM $(inplacedir); \
+	done
+
+# This is used by coregrind/Makefile.am and by <tool>/Makefile.am for doing
+# "make install".  It copies $(noinst_PROGRAMS) into $prefix/lib/valgrind/.
+# It needs to be depended on by an 'install-exec-local' rule.
+install-noinst_PROGRAMS: $(noinst_PROGRAMS)
+	$(mkinstalldirs) $(DESTDIR)$(pkglibdir); \
+	for f in $(noinst_PROGRAMS); do \
+	  $(INSTALL_PROGRAM) $$f $(DESTDIR)$(pkglibdir); \
+	done
+
+# Similar to install-noinst_PROGRAMS.
+# Nb: we don't use $(INSTALL_PROGRAM) here because it doesn't work with
+# directories.  XXX: not sure whether the resulting permissions will be
+# correct when using 'cp -R'...
+install-noinst_DSYMS: build-noinst_DSYMS
+	$(mkinstalldirs) $(DESTDIR)$(pkglibdir); \
+	for f in $(noinst_DSYMS); do \
+	  cp -R $$f.dSYM $(DESTDIR)$(pkglibdir); \
+	done
+
+# This needs to be depended on by a 'clean-local' rule.
+clean-noinst_DSYMS:
+	for f in $(noinst_DSYMS); do \
+	  rm -rf $$f.dSYM; \
+	done
+
+check-local: build-noinst_DSYMS
+
+clean-local: clean-noinst_DSYMS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/drd/tests/annotate_barrier.c b/drd/tests/annotate_barrier.c
new file mode 100644
index 0000000..5db1763
--- /dev/null
+++ b/drd/tests/annotate_barrier.c
@@ -0,0 +1,172 @@
+/*
+ * Test whether all data races are detected in a multithreaded program with
+ * user-annotated barriers. See also pth_barrier.c.
+ */
+
+
+#define _GNU_SOURCE
+
+
+#include <pthread.h> /* pthread_create() */
+#include <stdio.h>   /* fprintf() */
+#include <stdlib.h>  /* atoi() */
+#include <string.h>  /* memset() */
+#include <unistd.h>  /* usleep() */
+#include "../../drd/drd.h"
+#include "../../config.h"
+
+
+#define BARRIER_SERIAL_THREAD -1
+
+
+/* Local datatypes. */
+
+typedef struct
+{
+  /*
+   * number of threads that must call barrier_wait() before any of them
+   * successfully return from the call.
+   */
+  unsigned thread_count;
+  /* number of barrier_wait() calls since last barrier. */
+  volatile unsigned wait_count;
+  /*
+   * barrier count. Only the least significant bit matters -- a single bit
+   * counter would be sufficient.
+   */
+  volatile unsigned barrier_count;
+} barrier_t;
+
+struct threadinfo
+{
+  int        thread_num;
+  barrier_t* b;
+  pthread_t  tid;
+  int*       array;
+  int        iterations;
+};
+
+
+/* Local variables. */
+
+static int s_silent;
+
+
+/* Local functions. */
+
+static void barrier_init(barrier_t* b, unsigned count)
+{
+  b->thread_count = count;
+  b->wait_count = 0;
+  b->barrier_count = 0;
+  ANNOTATE_BARRIER_INIT(b, count, 0);
+}
+
+static void barrier_destroy(barrier_t* b)
+{
+  ANNOTATE_BARRIER_DESTROY(b);
+  memset(b, 0, sizeof(*b));
+}
+
+static int barrier_wait(barrier_t* b)
+{
+  int res;
+  unsigned barrier_count;
+
+  res = 0;
+  ANNOTATE_BARRIER_WAIT_BEFORE(b);
+  barrier_count = b->barrier_count;
+  if (__sync_add_and_fetch(&b->wait_count, 1) == b->thread_count)
+  {
+    __sync_sub_and_fetch(&b->wait_count, b->thread_count);
+    __sync_add_and_fetch(&b->barrier_count, 1);
+    res = BARRIER_SERIAL_THREAD;
+  }
+  else
+  {
+    while (b->barrier_count == barrier_count)
+    {
+#ifndef HAVE_PTHREAD_YIELD
+      /* Darwin doesn't have an implementation of pthread_yield(). */
+      usleep(100 * 1000);
+#else
+      pthread_yield();
+#endif
+    }
+  }
+  ANNOTATE_BARRIER_WAIT_AFTER(b);
+  return res;
+}
+
+/*
+ * Single thread, which touches p->iterations elements of array p->array.
+ * Each modification of an element of p->array is a data race.
+ */
+static void* threadfunc(struct threadinfo* p)
+{
+  int i;
+  int* const array = p->array;
+  barrier_t* const b = p->b;
+  if (! s_silent)
+    printf("thread %d iteration 0\n", p->thread_num);
+  barrier_wait(b);
+  for (i = 0; i < p->iterations; i++)
+  {
+    if (! s_silent)
+      printf("thread %d iteration %d; writing to %p\n",
+             p->thread_num, i + 1, &array[i]);
+    array[i] = i;
+    barrier_wait(b);
+  }
+  return 0;
+}
+
+/* Actual test, consisting of nthread threads. */
+static void barriers_and_races(const int nthread, const int iterations)
+{
+  int i;
+  struct threadinfo* t;
+  barrier_t b;
+  int* array;
+
+  t = malloc(nthread * sizeof(struct threadinfo));
+  array = malloc(iterations * sizeof(array[0]));
+
+  if (! s_silent)
+    printf("&array[0] = %p\n", array);
+
+  barrier_init(&b, nthread);
+
+  for (i = 0; i < nthread; i++)
+  {
+    t[i].thread_num = i + 1;
+    t[i].b = &b;
+    t[i].array = array;
+    t[i].iterations = iterations;
+    pthread_create(&t[i].tid, 0, (void*(*)(void*))threadfunc, &t[i]);
+  }
+
+  for (i = 0; i < nthread; i++)
+    pthread_join(t[i].tid, 0);
+
+  barrier_destroy(&b);
+
+  free(array);
+  free(t);
+}
+
+int main(int argc, char** argv)
+{
+  int nthread;
+  int iterations;
+
+  nthread    = (argc > 1) ? atoi(argv[1]) : 2;
+  iterations = (argc > 2) ? atoi(argv[2]) : 3;
+  s_silent   = (argc > 3) ? atoi(argv[3]) : 0;
+
+  barriers_and_races(nthread, iterations);
+
+  fprintf(stderr, "Done.\n");
+
+  return 0;
+}
diff --git a/drd/tests/annotate_barrier.stderr.exp b/drd/tests/annotate_barrier.stderr.exp
new file mode 100644
index 0000000..1ae8934
--- /dev/null
+++ b/drd/tests/annotate_barrier.stderr.exp
@@ -0,0 +1,47 @@
+
+The annotation macro ANNOTATE_BARRIER_INIT has not yet been implemented in <valgrind/drd.h>
+   at 0x........: barrier_init (annotate_barrier.c:?)
+   by 0x........: barriers_and_races (annotate_barrier.c:?)
+   by 0x........: main (annotate_barrier.c:?)
+
+Thread 2:
+The annotation macro ANNOTATE_BARRIER_WAIT_BEFORE has not yet been implemented in <valgrind/drd.h>
+   at 0x........: barrier_wait (annotate_barrier.c:?)
+   by 0x........: threadfunc (annotate_barrier.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+
+Thread 3:
+The annotation macro ANNOTATE_BARRIER_WAIT_AFTER has not yet been implemented in <valgrind/drd.h>
+   at 0x........: barrier_wait (annotate_barrier.c:?)
+   by 0x........: threadfunc (annotate_barrier.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+
+The annotation macro ANNOTATE_BARRIER_WAIT_BEFORE has not yet been implemented in <valgrind/drd.h>
+   at 0x........: barrier_wait (annotate_barrier.c:?)
+   by 0x........: threadfunc (annotate_barrier.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+
+Thread 2:
+Conflicting store by thread 2 at 0x........ size 4
+   at 0x........: threadfunc (annotate_barrier.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+   by 0x........: (within libpthread-?.?.so)
+Address 0x........ is at offset 0 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: barriers_and_races (annotate_barrier.c:?)
+   by 0x........: main (annotate_barrier.c:?)
+
+The annotation macro ANNOTATE_BARRIER_WAIT_AFTER has not yet been implemented in <valgrind/drd.h>
+   at 0x........: barrier_wait (annotate_barrier.c:?)
+   by 0x........: threadfunc (annotate_barrier.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+
+Thread 1:
+The annotation macro ANNOTATE_BARRIER_DESTROY has not yet been implemented in <valgrind/drd.h>
+   at 0x........: barrier_destroy (annotate_barrier.c:?)
+   by 0x........: barriers_and_races (annotate_barrier.c:?)
+   by 0x........: main (annotate_barrier.c:?)
+
+Done.
+
+ERROR SUMMARY: 11 errors from 7 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/annotate_barrier.vgtest b/drd/tests/annotate_barrier.vgtest
new file mode 100644
index 0000000..c3491e5
--- /dev/null
+++ b/drd/tests/annotate_barrier.vgtest
@@ -0,0 +1,4 @@
+prereq: test -e annotate_barrier && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no --num-callers=3
+prog: annotate_barrier 2 1 1
+stderr_filter: filter_stderr
diff --git a/drd/tests/annotate_hb_err.c b/drd/tests/annotate_hb_err.c
new file mode 100644
index 0000000..3ed15b9
--- /dev/null
+++ b/drd/tests/annotate_hb_err.c
@@ -0,0 +1,53 @@
+/* Test program that triggers several happens-before usage errors. */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <pthread.h>
+#include "unified_annotations.h"
+
+
+int main(int argc, char** argv)
+{
+  pthread_mutex_t m;
+  pthread_cond_t  cv;
+  int i[64];
+
+  pthread_mutex_init(&m, NULL);
+  pthread_cond_init(&cv, NULL);
+
+  /* happens-after without preceding happens-before. */
+  U_ANNOTATE_HAPPENS_AFTER(&i);
+
+  /* happens-after on a mutex. */
+  U_ANNOTATE_HAPPENS_BEFORE(&m);
+
+  /* happens-after on a condition variable. */
+  U_ANNOTATE_HAPPENS_BEFORE(&cv);
+
+  /* condition variable operation on a h.b. annotated object. */
+  U_ANNOTATE_HAPPENS_BEFORE(&i);
+  pthread_cond_init((pthread_cond_t*)&i, NULL);
+
+  /* The sequence below is fine. */
+  U_ANNOTATE_NEW_MEMORY(&i, sizeof(i));
+  U_ANNOTATE_HAPPENS_BEFORE(&i);
+  U_ANNOTATE_HAPPENS_AFTER(&i);
+  U_ANNOTATE_NEW_MEMORY(&i, sizeof(i));
+  U_ANNOTATE_HAPPENS_BEFORE(&i);
+  U_ANNOTATE_NEW_MEMORY(&i, sizeof(i));
+
+  /* happens-before after happens-after. */
+  U_ANNOTATE_HAPPENS_BEFORE(&i);
+  U_ANNOTATE_HAPPENS_AFTER(&i);
+  U_ANNOTATE_HAPPENS_BEFORE(&i);
+
+  fprintf(stderr, "Done.\n");
+  return 0;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff --git a/drd/tests/annotate_hb_err.stderr.exp b/drd/tests/annotate_hb_err.stderr.exp
new file mode 100644
index 0000000..b52069b
--- /dev/null
+++ b/drd/tests/annotate_hb_err.stderr.exp
@@ -0,0 +1,25 @@
+
+wrong type of synchronization object
+   at 0x........: U_AnnotateHappensBefore (unified_annotations.h:?)
+   by 0x........: main (annotate_hb_err.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (annotate_hb_err.c:?)
+
+wrong type of synchronization object
+   at 0x........: U_AnnotateHappensBefore (unified_annotations.h:?)
+   by 0x........: main (annotate_hb_err.c:?)
+cond 0x........ was first observed at:
+   at 0x........: pthread_cond_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (annotate_hb_err.c:?)
+
+wrong type of synchronization object
+   at 0x........: pthread_cond_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (annotate_hb_err.c:?)
+order annotation 0x........ was first observed at:
+   at 0x........: U_AnnotateHappensAfter (unified_annotations.h:?)
+   by 0x........: main (annotate_hb_err.c:?)
+
+Done.
+
+ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/annotate_hb_err.vgtest b/drd/tests/annotate_hb_err.vgtest
new file mode 100644
index 0000000..eab9704
--- /dev/null
+++ b/drd/tests/annotate_hb_err.vgtest
@@ -0,0 +1,4 @@
+prereq: test -e annotate_hb_err && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no
+prog: annotate_hb_err
+stderr_filter: filter_stderr_and_thread_no
diff --git a/drd/tests/annotate_hb_race.c b/drd/tests/annotate_hb_race.c
new file mode 100644
index 0000000..0c2b450
--- /dev/null
+++ b/drd/tests/annotate_hb_race.c
@@ -0,0 +1,50 @@
+/*
+ * Test program with happens-before / happens-after annotations that triggers
+ * a data race. The data race will only be reported if happens-after
+ * annotations that occur in different threads are not totally ordered. Or:
+ * this is a test for the implementation of ordering annotations.
+ */
+
+
+#include <stdio.h>
+#include <pthread.h>
+#include "unified_annotations.h"
+
+
+static int s_i;
+
+
+static void* thread_func(void* arg)
+{
+  int i;
+
+  U_ANNOTATE_HAPPENS_AFTER(&s_i);
+  i = s_i;
+  U_ANNOTATE_HAPPENS_AFTER(&s_i);
+  *(int*)arg = i;
+  return NULL;
+}
+
+int main(int argc, char** argv)
+{
+  pthread_t tid[2];
+  int result[2];
+
+  U_ANNOTATE_HAPPENS_BEFORE(&s_i);
+  pthread_create(&tid[0], 0, thread_func, &result[0]);
+  pthread_create(&tid[1], 0, thread_func, &result[1]);
+  s_i = 1;
+
+  pthread_join(tid[0], NULL);
+  pthread_join(tid[1], NULL);
+
+  fprintf(stderr, "Done.\n");
+
+  return 0;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff --git a/drd/tests/annotate_hb_race.stderr.exp b/drd/tests/annotate_hb_race.stderr.exp
new file mode 100644
index 0000000..bcb275b
--- /dev/null
+++ b/drd/tests/annotate_hb_race.stderr.exp
@@ -0,0 +1,8 @@
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: main (annotate_hb_race.c:?)
+Allocation context: BSS section of annotate_hb_race
+
+Done.
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/annotate_hb_race.vgtest b/drd/tests/annotate_hb_race.vgtest
new file mode 100644
index 0000000..38f75e9
--- /dev/null
+++ b/drd/tests/annotate_hb_race.vgtest
@@ -0,0 +1,4 @@
+prereq: test -e annotate_hb_race && ./supported_libpthread
+vgopts: --check-stack-var=yes --show-confl-seg=no
+prog: annotate_hb_race
+stderr_filter: filter_stderr_and_thread_no
diff --git a/drd/tests/annotate_hbefore.stderr.exp b/drd/tests/annotate_hbefore.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/annotate_hbefore.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/annotate_hbefore.vgtest b/drd/tests/annotate_hbefore.vgtest
new file mode 100644
index 0000000..d898915
--- /dev/null
+++ b/drd/tests/annotate_hbefore.vgtest
@@ -0,0 +1,4 @@
+prereq: test -e ../../helgrind/tests/annotate_hbefore && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no
+prog: ../../helgrind/tests/annotate_hbefore
+stderr_filter: filter_stderr
diff --git a/drd/tests/annotate_ignore_read.stderr.exp b/drd/tests/annotate_ignore_read.stderr.exp
new file mode 100644
index 0000000..8e6c6a8
--- /dev/null
+++ b/drd/tests/annotate_ignore_read.stderr.exp
@@ -0,0 +1,6 @@
+
+FLAGS [phb=1, fm=0]
+test69: negative
+	GLOB=30
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/annotate_ignore_read.vgtest b/drd/tests/annotate_ignore_read.vgtest
new file mode 100644
index 0000000..6488232
--- /dev/null
+++ b/drd/tests/annotate_ignore_read.vgtest
@@ -0,0 +1,5 @@
+prereq: test -e tsan_unittest && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no
+prog: tsan_unittest
+args: 69
+stderr_filter: filter_stderr_and_thread_no
diff --git a/drd/tests/annotate_ignore_rw.c b/drd/tests/annotate_ignore_rw.c
new file mode 100644
index 0000000..f6a63b6
--- /dev/null
+++ b/drd/tests/annotate_ignore_rw.c
@@ -0,0 +1,64 @@
+/* Test program for the annotations that suppress both reads and writes. */
+
+#include <assert.h>  /* assert() */
+#include <pthread.h>
+#include <stdio.h>   /* EOF */
+#include <unistd.h>  /* getopt() */
+#include "../../drd/drd.h"
+
+static int s_a;
+static int s_b;
+static int s_c;
+
+static void* thread_func(void* arg)
+{
+  /* Read s_a and modify s_b. */
+  s_b = s_a;
+  /* Modify s_c. */
+  s_c = 1;
+
+  return NULL;
+}
+
+int main(int argc, char** argv)
+{
+  int optchar;
+  int ign_rw = 1;
+  int tmp;
+  pthread_t tid;
+
+  while ((optchar = getopt(argc, argv, "r")) != EOF)
+  {
+    switch (optchar)
+    {
+    case 'r':
+      ign_rw = 0;
+      break;
+    default:
+      assert(0);
+    }
+  }
+
+  pthread_create(&tid, 0, thread_func, 0);
+  if (ign_rw)
+    ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
+  /* Read s_b and modify s_a. */
+  s_a = s_b;
+  if (ign_rw)
+    ANNOTATE_IGNORE_READS_AND_WRITES_END();
+
+  /*
+   * Insert a delay here in order to make sure the load of s_c happens
+   * after s_c has been modified.
+   */
+  sleep(1);
+
+  /* Read s_c. */
+  tmp = s_c;
+
+  pthread_join(tid, 0);
+
+  fprintf(stderr, "Finished.\n");
+
+  return 0;
+}
diff --git a/drd/tests/annotate_ignore_rw.stderr.exp b/drd/tests/annotate_ignore_rw.stderr.exp
new file mode 100644
index 0000000..384490a
--- /dev/null
+++ b/drd/tests/annotate_ignore_rw.stderr.exp
@@ -0,0 +1,9 @@
+
+Conflicting load by thread 1 at 0x........ size 4
+   at 0x........: main (annotate_ignore_rw.c:?)
+Location 0x........ is 0 bytes inside local var "s_c"
+declared at annotate_ignore_rw.c:11, in frame #? of thread 1
+
+Finished.
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/annotate_ignore_rw.vgtest b/drd/tests/annotate_ignore_rw.vgtest
new file mode 100644
index 0000000..cee4289
--- /dev/null
+++ b/drd/tests/annotate_ignore_rw.vgtest
@@ -0,0 +1,4 @@
+prereq: ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no
+prog: annotate_ignore_rw
+stderr_filter: filter_stderr
diff --git a/drd/tests/annotate_ignore_rw2.stderr.exp b/drd/tests/annotate_ignore_rw2.stderr.exp
new file mode 100644
index 0000000..617dd2d
--- /dev/null
+++ b/drd/tests/annotate_ignore_rw2.stderr.exp
@@ -0,0 +1,19 @@
+
+Conflicting load by thread 1 at 0x........ size 4
+   at 0x........: main (annotate_ignore_rw.c:?)
+Location 0x........ is 0 bytes inside local var "s_b"
+declared at annotate_ignore_rw.c:10, in frame #? of thread 1
+
+Conflicting store by thread 1 at 0x........ size 4
+   at 0x........: main (annotate_ignore_rw.c:?)
+Location 0x........ is 0 bytes inside local var "s_a"
+declared at annotate_ignore_rw.c:9, in frame #? of thread 1
+
+Conflicting load by thread 1 at 0x........ size 4
+   at 0x........: main (annotate_ignore_rw.c:?)
+Location 0x........ is 0 bytes inside local var "s_c"
+declared at annotate_ignore_rw.c:11, in frame #? of thread 1
+
+Finished.
+
+ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/annotate_ignore_rw2.vgtest b/drd/tests/annotate_ignore_rw2.vgtest
new file mode 100644
index 0000000..dec0575
--- /dev/null
+++ b/drd/tests/annotate_ignore_rw2.vgtest
@@ -0,0 +1,5 @@
+prereq: ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no
+prog: annotate_ignore_rw
+args: -r
+stderr_filter: filter_stderr
diff --git a/drd/tests/annotate_ignore_write.c b/drd/tests/annotate_ignore_write.c
new file mode 100644
index 0000000..2b71eb2
--- /dev/null
+++ b/drd/tests/annotate_ignore_write.c
@@ -0,0 +1,63 @@
+/* Test program for the annotations that suppress write operations. */
+
+#include <assert.h>  /* assert() */
+#include <pthread.h>
+#include <stdio.h>   /* EOF */
+#include <unistd.h>  /* getopt() */
+#include "../../drd/drd.h"
+
+static int s_a;
+static int s_b;
+static int s_c;
+
+static void* thread_func(void* arg)
+{
+  /* Read s_a and modify s_b. */
+  s_b = s_a;
+  /* Modify s_c. */
+  s_c = 1;
+
+  return NULL;
+}
+
+int main(int argc, char** argv)
+{
+  int optchar;
+  int ign_rw = 1;
+  pthread_t tid;
+
+  while ((optchar = getopt(argc, argv, "r")) != EOF)
+  {
+    switch (optchar)
+    {
+    case 'r':
+      ign_rw = 0;
+      break;
+    default:
+      assert(0);
+    }
+  }
+
+  pthread_create(&tid, 0, thread_func, 0);
+  if (ign_rw)
+    ANNOTATE_IGNORE_WRITES_BEGIN();
+  /* Read s_b and modify s_a. */
+  s_a = s_b;
+  if (ign_rw)
+    ANNOTATE_IGNORE_WRITES_END();
+
+  /*
+   * Insert a delay here in order to make sure the load of s_c happens
+   * after s_c has been modified.
+   */
+  sleep(1);
+
+  /* Read s_c and modify s_a. */
+  s_a = s_c;
+
+  pthread_join(tid, 0);
+
+  fprintf(stderr, "Finished.\n");
+
+  return 0;
+}
diff --git a/drd/tests/annotate_ignore_write.stderr.exp b/drd/tests/annotate_ignore_write.stderr.exp
new file mode 100644
index 0000000..63ade6c
--- /dev/null
+++ b/drd/tests/annotate_ignore_write.stderr.exp
@@ -0,0 +1,19 @@
+
+Conflicting load by thread 1 at 0x........ size 4
+   at 0x........: main (annotate_ignore_write.c:?)
+Location 0x........ is 0 bytes inside local var "s_b"
+declared at annotate_ignore_write.c:10, in frame #? of thread 1
+
+Conflicting load by thread 1 at 0x........ size 4
+   at 0x........: main (annotate_ignore_write.c:?)
+Location 0x........ is 0 bytes inside local var "s_c"
+declared at annotate_ignore_write.c:11, in frame #? of thread 1
+
+Conflicting store by thread 1 at 0x........ size 4
+   at 0x........: main (annotate_ignore_write.c:?)
+Location 0x........ is 0 bytes inside local var "s_a"
+declared at annotate_ignore_write.c:9, in frame #? of thread 1
+
+Finished.
+
+ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/annotate_ignore_write.vgtest b/drd/tests/annotate_ignore_write.vgtest
new file mode 100644
index 0000000..1cc3ef0
--- /dev/null
+++ b/drd/tests/annotate_ignore_write.vgtest
@@ -0,0 +1,4 @@
+prereq: ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no
+prog: annotate_ignore_write
+stderr_filter: filter_stderr
diff --git a/drd/tests/annotate_ignore_write2.stderr.exp b/drd/tests/annotate_ignore_write2.stderr.exp
new file mode 100644
index 0000000..e0eef71
--- /dev/null
+++ b/drd/tests/annotate_ignore_write2.stderr.exp
@@ -0,0 +1,24 @@
+
+Conflicting load by thread 1 at 0x........ size 4
+   at 0x........: main (annotate_ignore_write.c:?)
+Location 0x........ is 0 bytes inside local var "s_b"
+declared at annotate_ignore_write.c:10, in frame #? of thread 1
+
+Conflicting store by thread 1 at 0x........ size 4
+   at 0x........: main (annotate_ignore_write.c:?)
+Location 0x........ is 0 bytes inside local var "s_a"
+declared at annotate_ignore_write.c:9, in frame #? of thread 1
+
+Conflicting load by thread 1 at 0x........ size 4
+   at 0x........: main (annotate_ignore_write.c:?)
+Location 0x........ is 0 bytes inside local var "s_c"
+declared at annotate_ignore_write.c:11, in frame #? of thread 1
+
+Conflicting store by thread 1 at 0x........ size 4
+   at 0x........: main (annotate_ignore_write.c:?)
+Location 0x........ is 0 bytes inside local var "s_a"
+declared at annotate_ignore_write.c:9, in frame #? of thread 1
+
+Finished.
+
+ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/annotate_ignore_write2.vgtest b/drd/tests/annotate_ignore_write2.vgtest
new file mode 100644
index 0000000..b16ced7
--- /dev/null
+++ b/drd/tests/annotate_ignore_write2.vgtest
@@ -0,0 +1,5 @@
+prereq: ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no
+prog: annotate_ignore_write
+args: -r
+stderr_filter: filter_stderr
diff --git a/drd/tests/annotate_order_1.stderr.exp b/drd/tests/annotate_order_1.stderr.exp
new file mode 100644
index 0000000..0192a29
--- /dev/null
+++ b/drd/tests/annotate_order_1.stderr.exp
@@ -0,0 +1,6 @@
+
+FLAGS [phb=1, fm=0]
+test03: negative
+	GLOB=2
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/annotate_order_1.vgtest b/drd/tests/annotate_order_1.vgtest
new file mode 100644
index 0000000..f261092
--- /dev/null
+++ b/drd/tests/annotate_order_1.vgtest
@@ -0,0 +1,5 @@
+prereq: test -e tsan_unittest && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no
+prog: tsan_unittest
+args: 3
+stderr_filter: filter_stderr_and_thread_no
diff --git a/drd/tests/annotate_order_2.stderr.exp b/drd/tests/annotate_order_2.stderr.exp
new file mode 100644
index 0000000..731cd66
--- /dev/null
+++ b/drd/tests/annotate_order_2.stderr.exp
@@ -0,0 +1,6 @@
+
+FLAGS [phb=1, fm=0]
+test30: negative
+	GLOB=47
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/annotate_order_2.vgtest b/drd/tests/annotate_order_2.vgtest
new file mode 100644
index 0000000..8b22fbb
--- /dev/null
+++ b/drd/tests/annotate_order_2.vgtest
@@ -0,0 +1,5 @@
+prereq: test -e tsan_unittest && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no
+prog: tsan_unittest
+args: 30
+stderr_filter: filter_stderr_and_thread_no
diff --git a/drd/tests/annotate_order_3.stderr.exp b/drd/tests/annotate_order_3.stderr.exp
new file mode 100644
index 0000000..a5a9f85
--- /dev/null
+++ b/drd/tests/annotate_order_3.stderr.exp
@@ -0,0 +1,6 @@
+
+FLAGS [phb=1, fm=0]
+test31: negative
+	GLOB=48
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/annotate_order_3.vgtest b/drd/tests/annotate_order_3.vgtest
new file mode 100644
index 0000000..76b4595
--- /dev/null
+++ b/drd/tests/annotate_order_3.vgtest
@@ -0,0 +1,5 @@
+prereq: test -e tsan_unittest && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no
+prog: tsan_unittest
+args: 31
+stderr_filter: filter_stderr_and_thread_no
diff --git a/drd/tests/annotate_publish_hg.c b/drd/tests/annotate_publish_hg.c
new file mode 100644
index 0000000..12c5e44
--- /dev/null
+++ b/drd/tests/annotate_publish_hg.c
@@ -0,0 +1,11 @@
+/* Test for verifying that unsupported annotations are reported properly. */
+
+#include <stdio.h>
+#include "../../helgrind/helgrind.h"
+
+int main(int argc, char** argv)
+{
+  ANNOTATE_PUBLISH_MEMORY_RANGE(argv[0], sizeof(argv[0]));
+  fprintf(stderr, "Done.\n");
+  return 0;
+}
diff --git a/drd/tests/annotate_publish_hg.stderr.exp b/drd/tests/annotate_publish_hg.stderr.exp
new file mode 100644
index 0000000..b46c0ed
--- /dev/null
+++ b/drd/tests/annotate_publish_hg.stderr.exp
@@ -0,0 +1,7 @@
+
+The annotation macro ANNOTATE_PUBLISH_MEMORY_RANGE has not yet been implemented in <valgrind/helgrind.h>
+   at 0x........: main (annotate_publish_hg.c:?)
+
+Done.
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/annotate_publish_hg.vgtest b/drd/tests/annotate_publish_hg.vgtest
new file mode 100644
index 0000000..3c75d3f
--- /dev/null
+++ b/drd/tests/annotate_publish_hg.vgtest
@@ -0,0 +1,4 @@
+prereq: test -e annotate_publish_hg && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no
+prog: annotate_publish_hg
+stderr_filter: filter_stderr
diff --git a/drd/tests/annotate_rwlock.c b/drd/tests/annotate_rwlock.c
new file mode 100644
index 0000000..5ebb5fd
--- /dev/null
+++ b/drd/tests/annotate_rwlock.c
@@ -0,0 +1,162 @@
+/**
+ * @file  annotate_rwlock.c
+ *
+ * @brief Multithreaded test program that triggers various access patterns
+ *        without triggering any race conditions using a reader-writer lock
+ *        implemented via busy-waiting. Annotations are used to tell DRD
+ *        which higher-level rwlock operations are being performed.
+ */
+
+
+#define _GNU_SOURCE 1
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>        /* usleep() */
+#include "../../config.h"
+#include "../../drd/drd.h"
+
+
+#ifndef HAVE_BUILTIN_ATOMIC
+#error Sorry, but this test program can only be compiled by a compiler that\
+has built-in functions for atomic memory access.
+#endif
+
+
+typedef struct {
+  volatile int locked;
+  int          writer_count;
+  int          reader_count;
+} rwlock_t;
+
+
+static rwlock_t s_rwlock;
+static int s_counter;
+
+
+static void rwlock_init(rwlock_t* p)
+{
+  DRD_IGNORE_VAR(*p);
+  p->locked       = 0;
+  p->writer_count = 0;
+  p->reader_count = 0;
+  ANNOTATE_RWLOCK_CREATE(p);
+}
+
+static void rwlock_destroy(rwlock_t* p)
+{
+  ANNOTATE_RWLOCK_DESTROY(p);
+  assert(p->locked       == 0);
+  assert(p->writer_count == 0);
+  assert(p->reader_count == 0);
+}
+
+static void rwlock_rdlock(rwlock_t* p)
+{
+  while (1)
+  {
+    while (__sync_val_compare_and_swap(&p->locked, 0, 1) == 1)
+      ;
+    if (p->writer_count == 0)
+      break;
+#ifndef HAVE_PTHREAD_YIELD
+    /* Darwin doesn't have an implementation of pthread_yield(). */
+    usleep(100 * 1000);
+#else
+    pthread_yield();
+#endif
+    (void) __sync_fetch_and_sub(&p->locked, 1);
+  }
+  p->reader_count++;
+  assert(p->reader_count >= 0);
+  assert(p->writer_count >= 0);
+  assert(p->reader_count == 0 || p->writer_count == 0);
+  (void) __sync_fetch_and_sub(&p->locked, 1);
+  ANNOTATE_READERLOCK_ACQUIRED(p);
+}
+
+static void rwlock_wrlock(rwlock_t* p)
+{
+  while (1)
+  {
+    while (__sync_val_compare_and_swap(&p->locked, 0, 1) == 1)
+      ;
+    if (p->reader_count == 0)
+      break;
+#ifndef HAVE_PTHREAD_YIELD
+    /* Darwin doesn't have an implementation of pthread_yield(). */
+    usleep(100 * 1000);
+#else
+    pthread_yield();
+#endif
+    (void) __sync_fetch_and_sub(&p->locked, 1);
+  }
+  p->writer_count++;
+  assert(p->reader_count >= 0);
+  assert(p->writer_count >= 0);
+  assert(p->reader_count == 0 || p->writer_count == 0);
+  (void) __sync_fetch_and_sub(&p->locked, 1);
+  ANNOTATE_WRITERLOCK_ACQUIRED(p);
+}
+
+static void rwlock_unlock(rwlock_t* p)
+{
+  while (__sync_val_compare_and_swap(&p->locked, 0, 1) == 1)
+    ;
+  if (p->reader_count > 0)
+  {
+    p->reader_count--;
+    ANNOTATE_READERLOCK_RELEASED(p);
+  }
+  else
+  {
+    p->writer_count--;
+    ANNOTATE_WRITERLOCK_RELEASED(p);
+  }
+  assert(p->reader_count >= 0);
+  assert(p->writer_count >= 0);
+  assert(p->reader_count == 0 || p->writer_count == 0);
+  (void) __sync_fetch_and_sub(&p->locked, 1);
+}
+
+static void* thread_func(void* arg)
+{
+  int i;
+  int sum = 0;
+
+  for (i = 0; i < 1000; i++)
+  {
+    rwlock_rdlock(&s_rwlock);
+    sum += s_counter;
+    rwlock_unlock(&s_rwlock);
+    rwlock_wrlock(&s_rwlock);
+    s_counter++;
+    rwlock_unlock(&s_rwlock);
+  }
+
+  return 0;
+}
+
+int main(int argc, char** argv)
+{
+  const int thread_count = 10;
+  pthread_t tid[thread_count];
+  int i;
+
+  rwlock_init(&s_rwlock);
+  for (i = 0; i < thread_count; i++)
+  {
+    pthread_create(&tid[i], 0, thread_func, 0);
+  }
+
+  for (i = 0; i < thread_count; i++)
+  {
+    pthread_join(tid[i], 0);
+  }
+  rwlock_destroy(&s_rwlock);
+
+  fprintf(stderr, "Finished.\n");
+
+  return 0;
+}
diff --git a/drd/tests/annotate_rwlock.stderr.exp b/drd/tests/annotate_rwlock.stderr.exp
new file mode 100644
index 0000000..a7089bb
--- /dev/null
+++ b/drd/tests/annotate_rwlock.stderr.exp
@@ -0,0 +1,4 @@
+
+Finished.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/annotate_rwlock.vgtest b/drd/tests/annotate_rwlock.vgtest
new file mode 100644
index 0000000..f0f81d7
--- /dev/null
+++ b/drd/tests/annotate_rwlock.vgtest
@@ -0,0 +1,4 @@
+prereq: test -e annotate_rwlock && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no
+prog: annotate_rwlock
+stderr_filter: filter_stderr_and_thread_no
diff --git a/drd/tests/annotate_rwlock_hg.stderr.exp b/drd/tests/annotate_rwlock_hg.stderr.exp
new file mode 100644
index 0000000..12a0d6d
--- /dev/null
+++ b/drd/tests/annotate_rwlock_hg.stderr.exp
@@ -0,0 +1 @@
+Total error count is below threshold.
diff --git a/drd/tests/annotate_rwlock_hg.vgtest b/drd/tests/annotate_rwlock_hg.vgtest
new file mode 100644
index 0000000..fd25624
--- /dev/null
+++ b/drd/tests/annotate_rwlock_hg.vgtest
@@ -0,0 +1,4 @@
+prereq: test -e ../../helgrind/tests/annotate_rwlock && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no
+prog: ../../helgrind/tests/annotate_rwlock
+stderr_filter: compare_error_count_with
diff --git a/drd/tests/annotate_smart_pointer.cpp b/drd/tests/annotate_smart_pointer.cpp
new file mode 100755
index 0000000..7ef5e7c
--- /dev/null
+++ b/drd/tests/annotate_smart_pointer.cpp
@@ -0,0 +1,330 @@
+/*
+ * Test program that illustrates how to annotate a smart pointer
+ * implementation.  In a multithreaded program the following is relevant when
+ * working with smart pointers:
+ * - whether or not the objects pointed at are shared over threads.
+ * - whether or not the methods of the objects pointed at are thread-safe.
+ * - whether or not the smart pointer objects are shared over threads.
+ * - whether or not the smart pointer object itself is thread-safe.
+ *
+ * Most smart pointer implemenations are not thread-safe
+ * (e.g. boost::shared_ptr<>, tr1::shared_ptr<> and the smart_ptr<>
+ * implementation below). This means that it is not safe to modify a shared
+ * pointer object that is shared over threads without proper synchronization.
+ *
+ * Even for non-thread-safe smart pointers it is possible to have different
+ * threads access the same object via smart pointers without triggering data
+ * races on the smart pointer objects.
+ *
+ * A smart pointer implementation guarantees that the destructor of the object
+ * pointed at is invoked after the last smart pointer that points to that
+ * object has been destroyed or reset. Data race detection tools cannot detect
+ * this ordering without explicit annotation for smart pointers that track
+ * references without invoking synchronization operations recognized by data
+ * race detection tools.
+ */
+
+
+#include <cassert>     // assert()
+#include <climits>     // PTHREAD_STACK_MIN
+#include <iostream>    // std::cerr
+#include <stdlib.h>    // atoi()
+#ifdef _WIN32
+#include <process.h>   // _beginthreadex()
+#include <windows.h>   // CRITICAL_SECTION
+#else
+#include <pthread.h>   // pthread_mutex_t
+#endif
+#include "unified_annotations.h"
+
+
+static bool s_enable_annotations = true;
+
+
+#ifdef _WIN32
+
+class AtomicInt32
+{
+public:
+  AtomicInt32(const int value = 0) : m_value(value) { }
+  ~AtomicInt32() { }
+  LONG operator++() { return InterlockedIncrement(&m_value); }
+  LONG operator--() { return InterlockedDecrement(&m_value); }
+
+private:
+  volatile LONG m_value;
+};
+
+class Mutex
+{
+public:
+  Mutex() : m_mutex()
+  { InitializeCriticalSection(&m_mutex); }
+  ~Mutex()
+  { DeleteCriticalSection(&m_mutex); }
+  void Lock()
+  { EnterCriticalSection(&m_mutex); }
+  void Unlock()
+  { LeaveCriticalSection(&m_mutex); }
+
+private:
+  CRITICAL_SECTION m_mutex;
+};
+
+class Thread
+{
+public:
+  Thread() : m_thread(INVALID_HANDLE_VALUE) { }
+  ~Thread() { }
+  void Create(void* (*pf)(void*), void* arg)
+  {
+    WrapperArgs* wrapper_arg_p = new WrapperArgs(pf, arg);
+    m_thread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, wrapper,
+						       wrapper_arg_p, 0, NULL));
+  }
+  void Join()
+  { WaitForSingleObject(m_thread, INFINITE); }
+
+private:
+  struct WrapperArgs
+  {
+    WrapperArgs(void* (*pf)(void*), void* arg) : m_pf(pf), m_arg(arg) { }
+
+    void* (*m_pf)(void*);
+    void* m_arg;
+  };
+  static unsigned int __stdcall wrapper(void* arg)
+  {
+    WrapperArgs* wrapper_arg_p = reinterpret_cast<WrapperArgs*>(arg);
+    WrapperArgs wa = *wrapper_arg_p;
+    delete wrapper_arg_p;
+    return reinterpret_cast<unsigned>((wa.m_pf)(wa.m_arg));
+  }
+  HANDLE m_thread;
+};
+
+#else // _WIN32
+
+class AtomicInt32
+{
+public:
+  AtomicInt32(const int value = 0) : m_value(value) { }
+  ~AtomicInt32() { }
+  int operator++() { return __sync_add_and_fetch(&m_value, 1); }
+  int operator--() { return __sync_sub_and_fetch(&m_value, 1); }
+private:
+  volatile int m_value;
+};
+
+class Mutex
+{
+public:
+  Mutex() : m_mutex()
+  { pthread_mutex_init(&m_mutex, NULL); }
+  ~Mutex()
+  { pthread_mutex_destroy(&m_mutex); }
+  void Lock()
+  { pthread_mutex_lock(&m_mutex); }
+  void Unlock()
+  { pthread_mutex_unlock(&m_mutex); }
+
+private:
+  pthread_mutex_t m_mutex;
+};
+
+class Thread
+{
+public:
+  Thread() : m_tid() { }
+  ~Thread() { }
+  void Create(void* (*pf)(void*), void* arg)
+  {
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + 4096);
+    pthread_create(&m_tid, &attr, pf, arg);
+    pthread_attr_destroy(&attr);
+  }
+  void Join()
+  { pthread_join(m_tid, NULL); }
+private:
+  pthread_t m_tid;
+};
+
+#endif // !defined(_WIN32)
+
+
+template<class T>
+class smart_ptr
+{
+public:
+  typedef AtomicInt32 counter_t;
+
+  template <typename Q> friend class smart_ptr;
+
+  explicit smart_ptr()
+    : m_ptr(NULL), m_count_ptr(NULL)
+  { }
+
+  explicit smart_ptr(T* const pT)
+    : m_ptr(NULL), m_count_ptr(NULL)
+  {
+    set(pT, pT ? new counter_t(0) : NULL);
+  }
+
+  template <typename Q>
+  explicit smart_ptr(Q* const q)
+    : m_ptr(NULL), m_count_ptr(NULL)
+  {
+    set(q, q ? new counter_t(0) : NULL);
+  }
+
+  ~smart_ptr()
+  {
+    set(NULL, NULL);
+  }
+
+  smart_ptr(const smart_ptr<T>& sp)
+    : m_ptr(NULL), m_count_ptr(NULL)
+  {
+    set(sp.m_ptr, sp.m_count_ptr);
+  }
+
+  template <typename Q>
+  smart_ptr(const smart_ptr<Q>& sp)
+    : m_ptr(NULL), m_count_ptr(NULL)
+  {
+    set(sp.m_ptr, sp.m_count_ptr);
+  }
+
+  smart_ptr& operator=(const smart_ptr<T>& sp)
+  {
+    set(sp.m_ptr, sp.m_count_ptr);
+    return *this;
+  }
+
+  smart_ptr& operator=(T* const p)
+  {
+    set(p, p ? new counter_t(0) : NULL);
+    return *this;
+  }
+
+  template <typename Q>
+  smart_ptr& operator=(Q* const q)
+  {
+    set(q, q ? new counter_t(0) : NULL);
+    return *this;
+  }
+
+  T* operator->() const
+  {
+    assert(m_ptr);
+    return m_ptr;
+  }
+
+  T& operator*() const
+  {
+    assert(m_ptr);
+    return *m_ptr;
+  }
+
+private:
+  void set(T* const pT, counter_t* const count_ptr)
+  {
+    if (m_ptr != pT)
+    {
+      if (m_count_ptr)
+      {
+	if (s_enable_annotations)
+	  U_ANNOTATE_HAPPENS_BEFORE(m_count_ptr);
+	if (--(*m_count_ptr) == 0)
+	{
+	  if (s_enable_annotations)
+	    U_ANNOTATE_HAPPENS_AFTER(m_count_ptr);
+	  delete m_ptr;
+	  m_ptr = NULL;
+	  delete m_count_ptr;
+	  m_count_ptr = NULL;
+	}
+      }
+      m_ptr = pT;
+      m_count_ptr = count_ptr;
+      if (count_ptr)
+	++(*m_count_ptr);
+    }
+  }
+
+  T*         m_ptr;
+  counter_t* m_count_ptr;
+};
+
+class counter
+{
+public:
+  counter()
+    : m_mutex(), m_count()
+  { }
+  ~counter()
+  {
+    // Data race detection tools that do not recognize the
+    // ANNOTATE_HAPPENS_BEFORE() / ANNOTATE_HAPPENS_AFTER() annotations in the
+    // smart_ptr<> implementation will report that the assignment below
+    // triggers a data race.
+    m_count = -1;
+  }
+  int get() const
+  {
+    int result;
+    m_mutex.Lock();
+    result = m_count;
+    m_mutex.Unlock();
+    return result;
+  }
+  int post_increment()
+  {
+    int result;
+    m_mutex.Lock();
+    result = m_count++;
+    m_mutex.Unlock();
+    return result;
+  }
+
+private:
+  mutable Mutex m_mutex;
+  int           m_count;
+};
+
+static void* thread_func(void* arg)
+{
+  smart_ptr<counter>* pp = reinterpret_cast<smart_ptr<counter>*>(arg);
+  (*pp)->post_increment();
+  *pp = NULL;
+  delete pp;
+  return NULL;
+}
+
+int main(int argc, char** argv)
+{
+  const int nthreads = std::max(argc > 1 ? atoi(argv[1]) : 1, 1);
+  const int iterations = std::max(argc > 2 ? atoi(argv[2]) : 1, 1);
+  s_enable_annotations = argc > 3 ? !!atoi(argv[3]) : true;
+
+  for (int j = 0; j < iterations; ++j)
+  {
+    Thread T[nthreads];
+
+    smart_ptr<counter> p(new counter);
+    p->post_increment();
+    for (int i = 0; i < nthreads; ++i)
+      T[i].Create(thread_func, new smart_ptr<counter>(p));
+    p = NULL;
+    for (int i = 0; i < nthreads; ++i)
+      T[i].Join();
+  }
+  std::cerr << "Done.\n";
+  return 0;
+}
+
+// Local variables:
+// c-basic-offset: 2
+// End:
diff --git a/drd/tests/annotate_smart_pointer.stderr.exp b/drd/tests/annotate_smart_pointer.stderr.exp
new file mode 100644
index 0000000..d16127f
--- /dev/null
+++ b/drd/tests/annotate_smart_pointer.stderr.exp
@@ -0,0 +1,4 @@
+
+Done.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/annotate_smart_pointer.vgtest b/drd/tests/annotate_smart_pointer.vgtest
new file mode 100644
index 0000000..a103ef5
--- /dev/null
+++ b/drd/tests/annotate_smart_pointer.vgtest
@@ -0,0 +1,5 @@
+prereq: test -e annotate_smart_pointer && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no
+prog: annotate_smart_pointer
+args: 50 5
+stderr_filter: filter_stderr_and_thread_no
diff --git a/drd/tests/annotate_spinlock.stderr.exp b/drd/tests/annotate_spinlock.stderr.exp
new file mode 100644
index 0000000..dd42df3
--- /dev/null
+++ b/drd/tests/annotate_spinlock.stderr.exp
@@ -0,0 +1,6 @@
+
+FLAGS [phb=1, fm=0]
+test27: negative
+	GLOB=4
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/annotate_spinlock.vgtest b/drd/tests/annotate_spinlock.vgtest
new file mode 100644
index 0000000..5731798
--- /dev/null
+++ b/drd/tests/annotate_spinlock.vgtest
@@ -0,0 +1,5 @@
+prereq: test -e tsan_unittest && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no
+prog: tsan_unittest
+args: 27
+stderr_filter: filter_stderr_and_thread_no
diff --git a/drd/tests/annotate_static.cpp b/drd/tests/annotate_static.cpp
new file mode 100644
index 0000000..25ffd47
--- /dev/null
+++ b/drd/tests/annotate_static.cpp
@@ -0,0 +1,48 @@
+// Test for ANNOTATE_BENIGN_RACE_STATIC() and ANNOTATE_UNPROTECTED_READ().
+
+
+#include <pthread.h> /* pthread_create() */
+#include <stdio.h>   /* fprintf() */
+#include "../../drd/drd.h"
+
+
+/* Local variables. */
+
+static int s_i;
+static volatile int s_j;
+
+ANNOTATE_BENIGN_RACE_STATIC(s_i, "Benign because duplicate assignment.");
+
+
+/* Local functions. */
+
+static inline void AnnotateIgnoreReadsBegin() { ANNOTATE_IGNORE_READS_BEGIN(); }
+static inline void AnnotateIgnoreReadsEnd() { ANNOTATE_IGNORE_READS_END(); }
+
+static void* thread_func(void*)
+{
+#if defined(__powerpc__) && __GNUC__ -0 == 4 && __GNUC_MINOR__ -0 == 3 \
+    && __GNUC_PATCHLEVEL__ -0 == 0
+  AnnotateIgnoreReadsBegin();
+  int i = s_j;
+  AnnotateIgnoreReadsEnd();
+  s_i = i;
+#else
+  s_i = ANNOTATE_UNPROTECTED_READ(s_j);
+#endif
+  return 0;
+}
+
+int main(int argc, char** argv)
+{
+  pthread_t tid;
+
+  pthread_create(&tid, 0, thread_func, NULL);
+  s_j++;
+  s_i = s_j;
+  pthread_join(tid, NULL);
+
+  fprintf(stderr, "Done.\n");
+
+  return 0;
+}
diff --git a/drd/tests/annotate_static.stderr.exp b/drd/tests/annotate_static.stderr.exp
new file mode 100644
index 0000000..d16127f
--- /dev/null
+++ b/drd/tests/annotate_static.stderr.exp
@@ -0,0 +1,4 @@
+
+Done.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/annotate_static.vgtest b/drd/tests/annotate_static.vgtest
new file mode 100644
index 0000000..32ec4cc
--- /dev/null
+++ b/drd/tests/annotate_static.vgtest
@@ -0,0 +1,4 @@
+prereq: test -e annotate_static && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no
+prog: annotate_static
+stderr_filter: filter_stderr
diff --git a/drd/tests/annotate_trace_memory.stderr.exp b/drd/tests/annotate_trace_memory.stderr.exp
new file mode 100644
index 0000000..9c48a6e
--- /dev/null
+++ b/drd/tests/annotate_trace_memory.stderr.exp
@@ -0,0 +1,20 @@
+
+FLAGS [phb=1, fm=0]
+test01: positive
+store 0x........ size 4 (thread x / vc ...)
+   at 0x........: test01::Worker() (tsan_unittest.cpp:?)
+   by 0x........: MyThread::ThreadBody(MyThread*) (tsan_thread_wrappers_pthread.h:?)
+store 0x........ size 4 (thread x / vc ...)
+   at 0x........: test01::Parent() (tsan_unittest.cpp:?)
+   by 0x........: test01::Run() (tsan_unittest.cpp:?)
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: test01::Parent() (tsan_unittest.cpp:?)
+   by 0x........: test01::Run() (tsan_unittest.cpp:?)
+Allocation context: BSS section of tsan_unittest
+
+load  0x........ size 4 (thread x / vc ...)
+   at 0x........: test01::Run() (tsan_unittest.cpp:?)
+   by 0x........: main (tsan_unittest.cpp:?)
+	GLOB=2
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/annotate_trace_memory.vgtest b/drd/tests/annotate_trace_memory.vgtest
new file mode 100644
index 0000000..e7d23e2
--- /dev/null
+++ b/drd/tests/annotate_trace_memory.vgtest
@@ -0,0 +1,5 @@
+prereq: test -e tsan_unittest && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no --num-callers=2
+prog: tsan_unittest
+args: 1
+stderr_filter: filter_stderr_and_thread_no
diff --git a/drd/tests/atomic_var.c b/drd/tests/atomic_var.c
new file mode 100644
index 0000000..40f1566
--- /dev/null
+++ b/drd/tests/atomic_var.c
@@ -0,0 +1,66 @@
+/**
+ * This test program triggers a single race condition on variable s_y.
+ * Although another variable (s_x) is also modified by both threads, no race
+ * condition must be reported on this variable since it is only accessed via
+ * atomic instructions.
+ *
+ * Note: for the i386 and x86_64 memory models, thread 2 must print y = 1.
+ * On PPC however, both y = 0 and y = 1 are legal results. This is because
+ * the PPC memory model allows different CPU's to observe stores to variables
+ * in different cache lines in a different order.
+ */
+
+#define _GNU_SOURCE
+
+#include <pthread.h>
+#include <stdio.h>   /* fprintf() */
+#include <stdlib.h>  /* atoi() */
+#include "../../config.h"
+
+/* Atomic builtins are only supported by gcc 4.1.0 and later. */
+#ifndef HAVE_BUILTIN_ATOMIC
+#error Sorry, but this test program can only be compiled by a compiler that\
+has built-in functions for atomic memory access.
+#endif
+
+static __inline__
+int sync_add_and_fetch(int* p, int i)
+{
+  return __sync_add_and_fetch(p, i);
+}
+
+static int s_x = 0;
+/* g_dummy[] ensures that s_x and s_y are not in the same cache line. */
+char g_dummy[512];
+static int s_y = 0;
+
+static void* thread_func_1(void* arg)
+{
+  s_y = 1;
+  (void) sync_add_and_fetch(&s_x, 1);
+  return 0;
+}
+
+static void* thread_func_2(void* arg)
+{
+  while (sync_add_and_fetch(&s_x, 0) == 0)
+    ;
+  fprintf(stderr, "y = %d\n", s_y);
+  return 0;
+}
+
+int main(int argc, char** argv)
+{
+  int i;
+  const int n_threads = 2;
+  pthread_t tid[n_threads];
+
+  fprintf(stderr, "Start of test.\n");
+  pthread_create(&tid[0], 0, thread_func_1, 0);
+  pthread_create(&tid[1], 0, thread_func_2, 0);
+  for (i = 0; i < n_threads; i++)
+    pthread_join(tid[i], 0);
+  fprintf(stderr, "Test finished.\n");
+
+  return 0;
+}
diff --git a/drd/tests/atomic_var.stderr.exp b/drd/tests/atomic_var.stderr.exp
new file mode 100644
index 0000000..7fa1e0e
--- /dev/null
+++ b/drd/tests/atomic_var.stderr.exp
@@ -0,0 +1,12 @@
+
+Start of test.
+Conflicting load by thread x at 0x........ size 4
+   at 0x........: thread_func_2 (atomic_var.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Location 0x........ is 0 bytes inside local var "s_y"
+declared at atomic_var.c:35, in frame #? of thread x
+
+y = 1
+Test finished.
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/atomic_var.vgtest b/drd/tests/atomic_var.vgtest
new file mode 100644
index 0000000..e764355
--- /dev/null
+++ b/drd/tests/atomic_var.vgtest
@@ -0,0 +1,4 @@
+prereq: test -e atomic_var && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no --num-callers=2
+prog: atomic_var
+stderr_filter: filter_stderr_and_thread_no
diff --git a/drd/tests/bar_bad.stderr.exp b/drd/tests/bar_bad.stderr.exp
new file mode 100644
index 0000000..75f121f
--- /dev/null
+++ b/drd/tests/bar_bad.stderr.exp
@@ -0,0 +1,49 @@
+
+
+initialise a barrier with zero count
+pthread_barrier_init: 'count' argument is zero: barrier 0x........
+   at 0x........: pthread_barrier_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (bar_bad.c:?)
+
+
+initialise a barrier twice
+Barrier reinitialization: barrier 0x........
+   at 0x........: pthread_barrier_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (bar_bad.c:?)
+barrier 0x........ was first observed at:
+   at 0x........: pthread_barrier_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (bar_bad.c:?)
+
+
+initialise a barrier which has threads waiting on it
+Barrier reinitialization: barrier 0x........
+   at 0x........: pthread_barrier_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (bar_bad.c:?)
+barrier 0x........ was first observed at:
+   at 0x........: pthread_barrier_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (bar_bad.c:?)
+
+
+destroy a barrier that has waiting threads
+Destruction of a barrier with active waiters: barrier 0x........
+   at 0x........: pthread_barrier_destroy (drd_pthread_intercepts.c:?)
+   by 0x........: main (bar_bad.c:?)
+barrier 0x........ was first observed at:
+   at 0x........: pthread_barrier_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (bar_bad.c:?)
+
+
+destroy a barrier that was never initialised
+Not a barrier
+   at 0x........: pthread_barrier_destroy (drd_pthread_intercepts.c:?)
+   by 0x........: main (bar_bad.c:?)
+
+Destruction of barrier that is being waited upon: barrier 0x........
+   at 0x........: free (vg_replace_malloc.c:...)
+   by 0x........: main (bar_bad.c:?)
+barrier 0x........ was first observed at:
+   at 0x........: pthread_barrier_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (bar_bad.c:?)
+
+
+ERROR SUMMARY: 7 errors from 6 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/bar_bad.vgtest b/drd/tests/bar_bad.vgtest
new file mode 100644
index 0000000..14cdf19
--- /dev/null
+++ b/drd/tests/bar_bad.vgtest
@@ -0,0 +1,2 @@
+prereq: test -e ../../helgrind/tests/bar_bad && ./supported_libpthread
+prog: ../../helgrind/tests/bar_bad
diff --git a/drd/tests/bar_trivial.stderr.exp b/drd/tests/bar_trivial.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/bar_trivial.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/bar_trivial.stdout.exp b/drd/tests/bar_trivial.stdout.exp
new file mode 100644
index 0000000..407de30
--- /dev/null
+++ b/drd/tests/bar_trivial.stdout.exp
@@ -0,0 +1 @@
+x = 2
diff --git a/drd/tests/bar_trivial.vgtest b/drd/tests/bar_trivial.vgtest
new file mode 100644
index 0000000..3a11835
--- /dev/null
+++ b/drd/tests/bar_trivial.vgtest
@@ -0,0 +1,2 @@
+prereq: test -e ../../helgrind/tests/bar_trivial && ./supported_libpthread
+prog: ../../helgrind/tests/bar_trivial
diff --git a/drd/tests/boost_thread.cpp b/drd/tests/boost_thread.cpp
new file mode 100644
index 0000000..fbf9dbd
--- /dev/null
+++ b/drd/tests/boost_thread.cpp
@@ -0,0 +1,34 @@
+// Test program that allows to verify whether Drd works fine for programs that
+// use the boost::thread, boost::mutex and boost::condition classes.
+
+
+#include <boost/thread/condition.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/thread.hpp>
+#include <iostream>
+
+
+static boost::condition s_cva;
+static boost::mutex s_m;
+
+
+static void thread_func(void)
+{
+  std::cerr << "Thread 2.\n";
+  boost::mutex::scoped_lock sl(s_m);
+  s_cva.notify_all();
+  s_cva.wait(sl);
+}
+
+int main(int argc, char** argv)
+{
+  std::cerr << "Thread 1.\n";
+  boost::mutex::scoped_lock sl(s_m);
+  boost::thread t(thread_func);
+  s_cva.wait(sl);
+  s_cva.notify_all();
+  sl.unlock();
+  t.join();
+  std::cerr << "Finished.\n";
+  return 0;
+}
diff --git a/drd/tests/boost_thread.stderr.exp b/drd/tests/boost_thread.stderr.exp
new file mode 100644
index 0000000..78d8647
--- /dev/null
+++ b/drd/tests/boost_thread.stderr.exp
@@ -0,0 +1,6 @@
+
+Thread 1.
+Thread 2.
+Finished.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/boost_thread.vgtest b/drd/tests/boost_thread.vgtest
new file mode 100644
index 0000000..5351f93
--- /dev/null
+++ b/drd/tests/boost_thread.vgtest
@@ -0,0 +1,3 @@
+prereq: test -e boost_thread
+vgopts: --read-var-info=yes
+prog: boost_thread
diff --git a/drd/tests/bug-235681.c b/drd/tests/bug-235681.c
new file mode 100644
index 0000000..99114eb
--- /dev/null
+++ b/drd/tests/bug-235681.c
@@ -0,0 +1,94 @@
+/*
+ * pthread_cond_wait() test program.
+ * See also https://bugs.kde.org/show_bug.cgi?id=235681.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <pthread.h>
+#include <errno.h>
+#include <unistd.h>
+
+pthread_mutex_t mutex;
+pthread_cond_t cond_var;
+int status;
+int silent;
+
+static void *run_fn(void *v)
+{
+    int rc;
+
+    if (!silent)
+        fprintf(stderr, "run_fn starting\n");
+
+    rc = pthread_mutex_lock(&mutex);
+    assert(!rc);
+
+    while (!status) {
+        if (!silent)
+            fprintf(stderr, "run_fn(): status==0\n");
+        rc = pthread_cond_wait(&cond_var, &mutex);
+        assert(!rc);
+        if (!silent)
+            fprintf(stderr, "run_fn(): woke up\n");
+    }
+    if (!silent)
+        fprintf(stderr, "run_fn(): status==1\n");
+
+    rc = pthread_mutex_unlock(&mutex);
+    assert(!rc);
+
+    if (!silent)
+        fprintf(stderr, "run_fn done\n");
+
+    return NULL;
+}
+
+int main(int argc, char **argv)
+{
+    int rc;
+    pthread_t other_thread;
+
+    if (argc > 1)
+        silent = 1;
+
+    rc = pthread_mutex_init(&mutex, NULL);
+    assert(!rc);
+    rc = pthread_cond_init(&cond_var, NULL);
+    assert(!rc);
+
+    status = 0;
+
+    rc = pthread_create(&other_thread, NULL, run_fn, NULL);
+    assert(!rc);
+
+    /* yield the processor, and give the other thread a chance to get into the while loop */
+    if (!silent)
+        fprintf(stderr, "main(): sleeping...\n");
+    sleep(1);
+
+    rc = pthread_mutex_lock(&mutex);
+    assert(!rc);
+    /**** BEGIN CS *****/
+
+    if (!silent)
+        fprintf(stderr, "main(): status=1\n");
+    status = 1;
+    rc = pthread_cond_broadcast(&cond_var);
+    assert(!rc);
+
+    /**** END CS *****/
+    rc = pthread_mutex_unlock(&mutex);
+    assert(!rc);
+
+    if (!silent)
+        fprintf(stderr, "joining...\n");
+
+    rc = pthread_join(other_thread, NULL);
+    assert(!rc);
+
+    fprintf(stderr, "Done.\n");
+
+    return 0;
+}
diff --git a/drd/tests/bug-235681.stderr.exp b/drd/tests/bug-235681.stderr.exp
new file mode 100644
index 0000000..d16127f
--- /dev/null
+++ b/drd/tests/bug-235681.stderr.exp
@@ -0,0 +1,4 @@
+
+Done.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/bug-235681.vgtest b/drd/tests/bug-235681.vgtest
new file mode 100644
index 0000000..f6051b7
--- /dev/null
+++ b/drd/tests/bug-235681.vgtest
@@ -0,0 +1,5 @@
+prereq: test -e bug-235681 && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no --num-callers=3
+prog: bug-235681
+args: -q
+stderr_filter: filter_stderr
diff --git a/drd/tests/circular_buffer.c b/drd/tests/circular_buffer.c
new file mode 100644
index 0000000..6803521
--- /dev/null
+++ b/drd/tests/circular_buffer.c
@@ -0,0 +1,221 @@
+/* Test program that performs producer-consumer style communication through
+ * a circular buffer. This test program is a slightly modified version of the
+ * test program made available by Miguel Ojeda
+ * -- see also http://article.gmane.org/gmane.comp.debugging.valgrind/8782.
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <fcntl.h>
+#include "../../config.h"
+
+
+/** gcc versions 4.1.0 and later have support for atomic builtins. */
+
+#ifndef HAVE_BUILTIN_ATOMIC
+#error Sorry, but this test program can only be compiled by a compiler that\
+has built-in functions for atomic memory access.
+#endif
+
+
+#define BUFFER_MAX (2)
+#define DATA_SEMAPHORE_NAME "cb-data-semaphore"
+#define FREE_SEMAPHORE_NAME "cb-free-semaphore"
+
+
+typedef int data_t;
+
+typedef struct {
+  /* Counting semaphore representing the number of data items in the buffer. */
+  sem_t* data;
+  /* Counting semaphore representing the number of free elements. */
+  sem_t* free;
+  /* Position where a new elements should be written. */
+  int in;
+  /* Position from where an element can be removed. */
+  int out;
+  /* Mutex that protects 'in'. */
+  pthread_mutex_t mutex_in;
+  /* Mutex that protects 'out'. */
+  pthread_mutex_t mutex_out;
+  /* Data buffer. */
+  data_t buffer[BUFFER_MAX];
+} buffer_t;
+
+static int quiet = 0;
+static int use_locking = 1;
+
+static __inline__
+int fetch_and_add(int* p, int i)
+{
+  return __sync_fetch_and_add(p, i);
+}
+
+static sem_t* create_semaphore(const char* const name, const int value)
+{
+#ifdef __APPLE__
+  sem_t* p = sem_open(name, O_CREAT, 0600, value);
+  return p;
+#else
+  sem_t* p = malloc(sizeof(*p));
+  if (p)
+    sem_init(p, 0, value);
+  return p;
+#endif
+}
+
+static void destroy_semaphore(const char* const name, sem_t* p)
+{
+#ifdef __APPLE__
+  sem_close(p);
+  sem_unlink(name);
+#else
+  sem_destroy(p);
+  free(p);
+#endif
+}
+
+static void buffer_init(buffer_t * b)
+{
+  b->data = create_semaphore(DATA_SEMAPHORE_NAME, 0);
+  b->free = create_semaphore(FREE_SEMAPHORE_NAME, BUFFER_MAX);
+
+  pthread_mutex_init(&b->mutex_in, NULL);
+  pthread_mutex_init(&b->mutex_out, NULL);
+
+  b->in = 0;
+  b->out = 0;
+}
+
+static void buffer_recv(buffer_t* b, data_t* d)
+{
+  int out;
+  sem_wait(b->data);
+  if (use_locking)
+    pthread_mutex_lock(&b->mutex_out);
+  out = fetch_and_add(&b->out, 1);
+  if (out >= BUFFER_MAX)
+  {
+    fetch_and_add(&b->out, -BUFFER_MAX);
+    out -= BUFFER_MAX;
+  }
+  *d = b->buffer[out];
+  if (use_locking)
+    pthread_mutex_unlock(&b->mutex_out);
+  if (! quiet)
+  {
+    printf("received %d from buffer[%d]\n", *d, out);
+    fflush(stdout);
+  }
+  sem_post(b->free);
+}
+
+static void buffer_send(buffer_t* b, data_t* d)
+{
+  int in;
+  sem_wait(b->free);
+  if (use_locking)
+    pthread_mutex_lock(&b->mutex_in);
+  in = fetch_and_add(&b->in, 1);
+  if (in >= BUFFER_MAX)
+  {
+    fetch_and_add(&b->in, -BUFFER_MAX);
+    in -= BUFFER_MAX;
+  }
+  b->buffer[in] = *d;
+  if (use_locking)
+    pthread_mutex_unlock(&b->mutex_in);
+  if (! quiet)
+  {
+    printf("sent %d to buffer[%d]\n", *d, in);
+    fflush(stdout);
+  }
+  sem_post(b->data);
+}
+
+static void buffer_destroy(buffer_t* b)
+{
+  destroy_semaphore(DATA_SEMAPHORE_NAME, b->data);
+  destroy_semaphore(FREE_SEMAPHORE_NAME, b->free);
+
+  pthread_mutex_destroy(&b->mutex_in);
+  pthread_mutex_destroy(&b->mutex_out);
+}
+
+static buffer_t b;
+
+static void producer(int* id)
+{
+  buffer_send(&b, id);
+  pthread_exit(NULL);
+}
+
+#define MAXSLEEP (100 * 1000)
+
+static void consumer(int* id)
+{
+  int d;
+  usleep(rand() % MAXSLEEP);
+  buffer_recv(&b, &d);
+  if (! quiet)
+  {
+    printf("%i: %i\n", *id, d);
+    fflush(stdout);
+  }
+  pthread_exit(NULL);
+}
+
+#define THREADS (10)
+
+int main(int argc, char** argv)
+{
+  pthread_t producers[THREADS];
+  pthread_t consumers[THREADS];
+  int thread_arg[THREADS];
+  int i;
+  int optchar;
+
+  while ((optchar = getopt(argc, argv, "nq")) != EOF)
+  {
+    switch (optchar)
+    {
+    case 'n':
+      use_locking = 0;
+      break;
+    case 'q':
+      quiet = 1;
+      break;
+    }
+  }
+
+  srand(time(NULL));
+
+  buffer_init(&b);
+
+  for (i = 0; i < THREADS; ++i)
+  {
+    thread_arg[i] = i;
+    pthread_create(producers + i, NULL,
+                   (void * (*)(void *)) producer, &thread_arg[i]);
+  }
+
+  for (i = 0; i < THREADS; ++i)
+    pthread_create(consumers + i, NULL,
+                   (void * (*)(void *)) consumer, &thread_arg[i]);
+
+  for (i = 0; i < THREADS; ++i)
+  {
+    pthread_join(producers[i], NULL);
+    pthread_join(consumers[i], NULL);
+  }
+
+  buffer_destroy(&b);
+
+  return 0;
+}
diff --git a/drd/tests/circular_buffer.stderr.exp b/drd/tests/circular_buffer.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/circular_buffer.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/circular_buffer.vgtest b/drd/tests/circular_buffer.vgtest
new file mode 100644
index 0000000..faa70fc
--- /dev/null
+++ b/drd/tests/circular_buffer.vgtest
@@ -0,0 +1,3 @@
+prereq: test -e circular_buffer && ./supported_libpthread
+prog: circular_buffer
+args: -q
diff --git a/drd/tests/compare_error_count_with b/drd/tests/compare_error_count_with
new file mode 100755
index 0000000..48abf3e
--- /dev/null
+++ b/drd/tests/compare_error_count_with
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+awk -v count=50000 '/ERROR SUMMARY/{if ($4 <= count) print "Total error count is below threshold."; else print "Total error count is above threshold" }'
diff --git a/drd/tests/custom_alloc.c b/drd/tests/custom_alloc.c
new file mode 100644
index 0000000..9faead5
--- /dev/null
+++ b/drd/tests/custom_alloc.c
@@ -0,0 +1,90 @@
+#include <unistd.h>
+#include "tests/sys_mman.h"
+#include <assert.h>
+#include <stdlib.h>
+
+#include "../drd.h"
+
+#define SUPERBLOCK_SIZE    100000
+
+//-------------------------------------------------------------------------
+// Allocator
+//-------------------------------------------------------------------------
+
+void* get_superblock(void)
+{
+   void* p = mmap( 0, SUPERBLOCK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC,
+                   MAP_PRIVATE|MAP_ANONYMOUS, -1, 0 );
+
+   assert(p != ((void*)(-1)));
+
+   return p;
+}
+
+// has a redzone
+static void* custom_alloc(int size)
+{
+#define RZ  8
+   static void* hp     = 0;    // current heap pointer
+   static void* hp_lim = 0;    // maximum usable byte in current block
+   int          size2  = size + RZ*2;
+   void*        p;
+
+   if (hp + size2 > hp_lim) {
+      hp = get_superblock();
+      hp_lim = hp + SUPERBLOCK_SIZE - 1;
+   }
+
+   p = hp + RZ;
+   hp += size2;
+
+   VALGRIND_MALLOCLIKE_BLOCK( p, size, RZ, /*is_zeroed*/1 );
+   return (void*)p;
+}
+
+static void custom_free(void* p)
+{
+   // don't actually free any memory... but mark it as freed
+   VALGRIND_FREELIKE_BLOCK( p, RZ );
+}
+#undef RZ
+
+
+
+//-------------------------------------------------------------------------
+// Rest
+//-------------------------------------------------------------------------
+
+void make_leak(void)
+{
+   int* array2 = custom_alloc(sizeof(int) * 10);
+   array2 = 0;          // leak
+   return;
+}
+
+int main(void)
+{
+   int* array;
+   int* array3;
+
+   array = custom_alloc(sizeof(int) * 10);
+   array[8]  = 8;
+   array[9]  = 8;
+   array[10] = 10;      // invalid write (ok w/o MALLOCLIKE -- in superblock)
+
+   custom_free(array);  // ok
+
+   custom_free(NULL);   // invalid free (ok without MALLOCLIKE)
+
+   array3 = malloc(sizeof(int) * 10);
+   custom_free(array3); // mismatched free (ok without MALLOCLIKE)
+
+   make_leak();
+   return array[0];     // use after free (ok without MALLOCLIKE)
+                        // (nb: initialised because is_zeroed==1 above)
+                        // unfortunately not identified as being in a free'd
+                        // block because the freeing of the block and shadow
+                        // chunk isn't postponed.
+
+   // leak from make_leak()
+}
diff --git a/drd/tests/custom_alloc.stderr.exp b/drd/tests/custom_alloc.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/custom_alloc.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/custom_alloc.vgtest b/drd/tests/custom_alloc.vgtest
new file mode 100644
index 0000000..2b8a141
--- /dev/null
+++ b/drd/tests/custom_alloc.vgtest
@@ -0,0 +1 @@
+prog: custom_alloc
diff --git a/drd/tests/filter_error_summary b/drd/tests/filter_error_summary
new file mode 100755
index 0000000..cdf703f
--- /dev/null
+++ b/drd/tests/filter_error_summary
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# Filter the error output of Valgrind such that only the line with the error
+# summary is kept. Bart Van Assche, February 26, 2008.
+
+sed -n -e 's/^.*\(ERROR SUMMARY.*\) ([^()]*)$/\1/' -e '/ERROR SUMMARY/p'
diff --git a/drd/tests/filter_stderr b/drd/tests/filter_stderr
new file mode 100755
index 0000000..05f54d0
--- /dev/null
+++ b/drd/tests/filter_stderr
@@ -0,0 +1,45 @@
+#! /bin/sh
+
+dir=`dirname $0`
+
+sed -e "s:_pthread_start (in /usr/lib/libSystem.B.dylib):(within libpthread-?.?.so):" |
+
+$dir/../../tests/filter_stderr_basic |
+
+# Remove "drd, ..." line and the following copyright line.
+# Remove line numbers referring to drd's source code.
+# Remove libpthread's version number.
+# Remove line numbers from stack traces.
+sed \
+-e "/^drd, a thread error detector$/d" \
+-e "s/^Allocation context: stack of thread \([0-9]*\), offset -[0-9]*$/Allocation context: stack of thread \1, offset .../" \
+-e "/^warning: evaluate_Dwarf3_Expr: unhandled DW_OP_.*/d" \
+-e '/^warning: addVar:.*/d' \
+-e 's/^Allocation context: Data section of .\//Allocation context: BSS section of /' \
+-e '/^run: \/usr\/bin\/dsymutil.*/d' \
+-e "s/, in frame #[0-9]* of thread /, in frame #? of thread /" \
+-e "s/(tc20_verifywrap.c:261)/(tc20_verifywrap.c:262)/" \
+-e "/^Copyright (C) 2006-201., and GNU GPL'd, by Bart Van Assche.$/d" \
+-e "s/\([A-Za-z_]*\) (clone.S:[0-9]*)/\1 (in \/...libc...)/" \
+-e "s/[A-Za-z_]* (pthread_create.c:[0-9]*)/(within libpthread-?.?.so)/" \
+-e "s/[A-Za-z_]* (in [^ ]*libpthread-[0-9.]*\.so)/(within libpthread-?.?.so)/" \
+-e "s:(within /lib[0-9]*/ld-[0-9.]*\.so):(within ld-?.?.so):" \
+-e "s/was held during [0-9][0-9]*/was held during .../" \
+-e "s: BSS section of .*/: BSS section of :g" \
+-e "s: vc \[[ ,:0-9]*\]: vc ...:g" \
+-e "s/[@\$*]* (drd_pthread_intercepts.c:/ (drd_pthread_intercepts.c:/" \
+-e "s/ (\([a-zA-Z_]*\.c\):[0-9]*)/ (\1:?)/" \
+-e "s/ (\([a-zA-Z_]*\.h\):[0-9]*)/ (\1:?)/" \
+-e "s/ (\([a-zA-Z_]*\.cpp\):[0-9]*)/ (\1:?)/" \
+-e "/^For counts of detected and suppressed errors, rerun with: -v$/d" |
+
+# Remove the message that more than hundred errors have been detected
+# (consists of two lines) and also the empty line above it.
+awk 'BEGIN{begin=1} {if ($0 == "More than 100 errors detected.  Subsequent errors") { getline; getline; } else { if (begin) begin = 0; else print last_line; }; last_line = $0; } END { if (! begin) print last_line; }' |
+
+# Remove the message about experimental support for Darwin.
+awk 'BEGIN{begin=1} { if ($0 == "WARNING: DRD support for Darwin is still considered as experimental.") { getline; getline; } else { if (begin) begin = 0; else print last_line; }; last_line = $0; } END { if (! begin) print last_line; }' |
+
+# Anonymise addresses
+$dir/../../tests/filter_addresses
+
diff --git a/drd/tests/filter_stderr_and_thread_no b/drd/tests/filter_stderr_and_thread_no
new file mode 100755
index 0000000..3993f6f
--- /dev/null
+++ b/drd/tests/filter_stderr_and_thread_no
@@ -0,0 +1,9 @@
+#! /bin/sh
+
+./filter_stderr |
+
+# Get rid of the numbers as these make some tests more scheduling sensitive
+# -- those where there are multiple threads which play interchangeable roles.
+grep -v "^Thread [0-9][0-9]*:$" |
+sed -e "s:hread [0-9][0-9]*:hread x:g" \
+    -e "s:of thread [0-9][0-9]*$:of thread x:g"
diff --git a/drd/tests/fp_race.c b/drd/tests/fp_race.c
new file mode 100644
index 0000000..65d13a3
--- /dev/null
+++ b/drd/tests/fp_race.c
@@ -0,0 +1,104 @@
+/* Test data race detection between floating point variables. */
+
+
+#include <assert.h>
+#include <stdio.h>     /* printf() */
+#include <pthread.h>
+#include <unistd.h>    /* sleep() */
+
+
+/* Local functions declarations. */
+
+static void* thread_func(void*);
+
+
+/* Local variables. */
+
+/* s_mutex protects s_d3. */
+static pthread_mutex_t s_mutex;
+
+static double s_d1; /* accessed before thread creation and in the created */
+                    /* thread (not a race). */
+static double s_d2; /* accessed in the created thread and after the join */
+                    /* (not a race). */
+static double s_d3; /* accessed simultaneously from both threads (race). */
+static int    s_debug     = 0;
+static int    s_do_printf = 0;
+static int    s_use_mutex = 0;
+
+
+/* Function definitions. */
+
+int main(int argc, char** argv)
+{
+  int optchar;
+  pthread_t threadid;
+
+  while ((optchar = getopt(argc, argv, "dmp")) != EOF)
+  {
+    switch (optchar)
+    {
+    case 'd':
+      s_debug = 1;
+      break;
+    case 'm':
+      s_use_mutex = 1;
+      break;
+    case 'p':
+      s_do_printf = 1;
+      break;
+    default:
+      assert(0);
+    }
+  }
+
+  pthread_mutex_init(&s_mutex, 0);
+
+  /*
+   * Switch to line-buffered mode, such that timing information can be
+   * obtained for each printf() call with strace.
+   */
+  setlinebuf(stdout);
+
+  if (s_debug)
+  {
+    printf("&s_d1 = %p; &s_d2 = %p; &s_d3 = %p\n", &s_d1, &s_d2, &s_d3);
+  }
+
+  s_d1 = 1;
+  s_d3 = 3;
+
+  pthread_create(&threadid, 0, thread_func, 0);
+
+  sleep(1); /* Wait until thread_func() finished. */
+
+  {
+    if (s_use_mutex) pthread_mutex_lock(&s_mutex);
+    s_d3++;
+    if (s_use_mutex) pthread_mutex_unlock(&s_mutex);
+  }
+
+  /* Wait until the thread finished. */
+  pthread_join(threadid, 0);
+  if (s_do_printf) printf("s_d2 = %g (should be 2)\n", s_d2);
+  if (s_do_printf) printf("s_d3 = %g (should be 5)\n", s_d3);
+
+  pthread_mutex_destroy(&s_mutex);
+
+  return 0;
+}
+
+static void* thread_func(void* thread_arg)
+{
+  if (s_do_printf)
+  {
+    printf("s_d1 = %g (should be 1)\n", s_d1);
+  }
+  s_d2 = 2;
+  {
+    if (s_use_mutex) pthread_mutex_lock(&s_mutex);
+    s_d3++;
+    if (s_use_mutex) pthread_mutex_unlock(&s_mutex);
+  }
+  return 0;
+}
diff --git a/drd/tests/fp_race.stderr.exp b/drd/tests/fp_race.stderr.exp
new file mode 100644
index 0000000..23873d2
--- /dev/null
+++ b/drd/tests/fp_race.stderr.exp
@@ -0,0 +1,21 @@
+
+Conflicting load by thread 1 at 0x........ size 8
+   at 0x........: main (fp_race.c:?)
+Location 0x........ is 0 bytes inside local var "s_d3"
+declared at fp_race.c:24, in frame #? of thread 1
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+Conflicting store by thread 1 at 0x........ size 8
+   at 0x........: main (fp_race.c:?)
+Location 0x........ is 0 bytes inside local var "s_d3"
+declared at fp_race.c:24, in frame #? of thread 1
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+
+ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/fp_race.vgtest b/drd/tests/fp_race.vgtest
new file mode 100644
index 0000000..b658b7c
--- /dev/null
+++ b/drd/tests/fp_race.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread
+vgopts: --read-var-info=yes
+prog: fp_race
diff --git a/drd/tests/fp_race2.stderr.exp b/drd/tests/fp_race2.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/fp_race2.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/fp_race2.vgtest b/drd/tests/fp_race2.vgtest
new file mode 100644
index 0000000..dcbad0f
--- /dev/null
+++ b/drd/tests/fp_race2.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread
+prog: fp_race
+args: -m
diff --git a/drd/tests/hg01_all_ok.stderr.exp b/drd/tests/hg01_all_ok.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/hg01_all_ok.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/hg01_all_ok.vgtest b/drd/tests/hg01_all_ok.vgtest
new file mode 100644
index 0000000..f3409b6
--- /dev/null
+++ b/drd/tests/hg01_all_ok.vgtest
@@ -0,0 +1,2 @@
+prereq: ./supported_libpthread
+prog: ../../helgrind/tests/hg01_all_ok
diff --git a/drd/tests/hg02_deadlock.stderr.exp b/drd/tests/hg02_deadlock.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/hg02_deadlock.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/hg02_deadlock.vgtest b/drd/tests/hg02_deadlock.vgtest
new file mode 100644
index 0000000..8ee583c
--- /dev/null
+++ b/drd/tests/hg02_deadlock.vgtest
@@ -0,0 +1,2 @@
+prereq: ./supported_libpthread
+prog: ../../helgrind/tests/hg02_deadlock
diff --git a/drd/tests/hg03_inherit.stderr.exp b/drd/tests/hg03_inherit.stderr.exp
new file mode 100644
index 0000000..62a8d5d
--- /dev/null
+++ b/drd/tests/hg03_inherit.stderr.exp
@@ -0,0 +1,16 @@
+
+Thread 3:
+Conflicting store by thread 3 at 0x........ size 4
+   at 0x........: t2 (hg03_inherit.c:28)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Location 0x........ is 0 bytes inside shared[1],
+declared at hg03_inherit.c:11, in frame #? of thread 3
+
+Conflicting store by thread 3 at 0x........ size 4
+   at 0x........: t2 (hg03_inherit.c:29)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Location 0x........ is 0 bytes inside shared[1],
+declared at hg03_inherit.c:11, in frame #? of thread 3
+
+
+ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/hg03_inherit.vgtest b/drd/tests/hg03_inherit.vgtest
new file mode 100644
index 0000000..7b7481e
--- /dev/null
+++ b/drd/tests/hg03_inherit.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread
+vgopts: --show-confl-seg=no --read-var-info=yes --num-callers=2
+prog: ../../helgrind/tests/hg03_inherit
diff --git a/drd/tests/hg04_race.stderr.exp b/drd/tests/hg04_race.stderr.exp
new file mode 100644
index 0000000..9ea3ccd
--- /dev/null
+++ b/drd/tests/hg04_race.stderr.exp
@@ -0,0 +1,24 @@
+
+Thread 3:
+Conflicting load by thread 3 at 0x........ size 4
+   at 0x........: th (hg04_race.c:10)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Location 0x........ is 0 bytes inside local var "shared"
+declared at hg04_race.c:6, in frame #? of thread 2
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+Conflicting store by thread 3 at 0x........ size 4
+   at 0x........: th (hg04_race.c:10)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Location 0x........ is 0 bytes inside local var "shared"
+declared at hg04_race.c:6, in frame #? of thread 2
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+
+ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/hg04_race.vgtest b/drd/tests/hg04_race.vgtest
new file mode 100644
index 0000000..0f60ad4
--- /dev/null
+++ b/drd/tests/hg04_race.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread
+vgopts: --read-var-info=yes --num-callers=2
+prog: ../../helgrind/tests/hg04_race
diff --git a/drd/tests/hg05_race2.stderr.exp b/drd/tests/hg05_race2.stderr.exp
new file mode 100644
index 0000000..f9a47f4
--- /dev/null
+++ b/drd/tests/hg05_race2.stderr.exp
@@ -0,0 +1,24 @@
+
+Thread 3:
+Conflicting load by thread 3 at 0x........ size 4
+   at 0x........: th (hg05_race2.c:17)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Location 0x........ is 0 bytes inside foo.poot[5].plop[11],
+declared at hg05_race2.c:24, in frame #? of thread 1
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+Conflicting store by thread 3 at 0x........ size 4
+   at 0x........: th (hg05_race2.c:17)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Location 0x........ is 0 bytes inside foo.poot[5].plop[11],
+declared at hg05_race2.c:24, in frame #? of thread 1
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+
+ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/hg05_race2.stderr.exp-powerpc b/drd/tests/hg05_race2.stderr.exp-powerpc
new file mode 100644
index 0000000..e38c7ea
--- /dev/null
+++ b/drd/tests/hg05_race2.stderr.exp-powerpc
@@ -0,0 +1,22 @@
+
+Thread 3:
+Conflicting load by thread 3 at 0x........ size 4
+   at 0x........: th (hg05_race2.c:17)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Allocation context: unknown.
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+Conflicting store by thread 3 at 0x........ size 4
+   at 0x........: th (hg05_race2.c:17)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Allocation context: unknown.
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+
+ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/hg05_race2.vgtest b/drd/tests/hg05_race2.vgtest
new file mode 100644
index 0000000..d0de01a
--- /dev/null
+++ b/drd/tests/hg05_race2.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --num-callers=2
+prog: ../../helgrind/tests/hg05_race2
diff --git a/drd/tests/hg06_readshared.stderr.exp b/drd/tests/hg06_readshared.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/hg06_readshared.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/hg06_readshared.vgtest b/drd/tests/hg06_readshared.vgtest
new file mode 100644
index 0000000..18cb7c4
--- /dev/null
+++ b/drd/tests/hg06_readshared.vgtest
@@ -0,0 +1,2 @@
+prereq: ./supported_libpthread
+prog: ../../helgrind/tests/hg06_readshared
diff --git a/drd/tests/hold_lock.c b/drd/tests/hold_lock.c
new file mode 100644
index 0000000..cf5ad9c
--- /dev/null
+++ b/drd/tests/hold_lock.c
@@ -0,0 +1,79 @@
+/** Hold several types of synchronization objects locked as long as specified.
+ */
+
+#define _GNU_SOURCE 1
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+
+static void delay_ms(const int ms)
+{
+  struct timespec ts;
+
+  assert(ms >= 0);
+  ts.tv_sec = ms / 1000;
+  ts.tv_nsec = (ms % 1000) * 1000 * 1000;
+  nanosleep(&ts, 0);
+}
+
+int main(int argc, char** argv)
+{
+  int interval = 0;
+  int optchar;
+  pthread_mutex_t     mutex;
+  pthread_mutexattr_t mutexattr;
+  pthread_rwlock_t    rwlock;
+
+  while ((optchar = getopt(argc, argv, "i:")) != EOF)
+  {
+    switch (optchar)
+    {
+    case 'i':
+      interval = atoi(optarg);
+      break;
+    default:
+      fprintf(stderr, "Usage: %s [-i <interval time in ms>].\n", argv[0]);
+      break;
+    }
+  }
+
+  fprintf(stderr, "Locking mutex ...\n");
+
+  pthread_mutexattr_init(&mutexattr);
+  pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
+  pthread_mutex_init(&mutex, &mutexattr);
+  pthread_mutexattr_destroy(&mutexattr);
+  pthread_mutex_lock(&mutex);
+  delay_ms(interval);
+  pthread_mutex_lock(&mutex);
+  pthread_mutex_unlock(&mutex);
+  pthread_mutex_unlock(&mutex);
+  pthread_mutex_destroy(&mutex);
+
+  fprintf(stderr, "Locking rwlock exclusively ...\n");
+
+  pthread_rwlock_init(&rwlock, 0);
+  pthread_rwlock_wrlock(&rwlock);
+  delay_ms(interval);
+  pthread_rwlock_unlock(&rwlock);
+  pthread_rwlock_destroy(&rwlock);
+
+  fprintf(stderr, "Locking rwlock shared ...\n");
+
+  pthread_rwlock_init(&rwlock, 0);
+  pthread_rwlock_rdlock(&rwlock);
+  delay_ms(interval);
+  pthread_rwlock_rdlock(&rwlock);
+  pthread_rwlock_unlock(&rwlock);
+  pthread_rwlock_unlock(&rwlock);
+  pthread_rwlock_destroy(&rwlock);
+
+  fprintf(stderr, "Done.\n");
+
+  return 0;
+}
diff --git a/drd/tests/hold_lock_1.stderr.exp b/drd/tests/hold_lock_1.stderr.exp
new file mode 100644
index 0000000..1732197
--- /dev/null
+++ b/drd/tests/hold_lock_1.stderr.exp
@@ -0,0 +1,27 @@
+
+Locking mutex ...
+Acquired at:
+   at 0x........: pthread_mutex_lock (drd_pthread_intercepts.c:?)
+   by 0x........: main (hold_lock.c:?)
+Lock on mutex 0x........ was held during ... ms (threshold: 500 ms).
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: main (hold_lock.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (hold_lock.c:?)
+
+Locking rwlock exclusively ...
+Acquired at:
+   at 0x........: pthread_rwlock_wrlock (drd_pthread_intercepts.c:?)
+   by 0x........: main (hold_lock.c:?)
+Lock on rwlock 0x........ was held during ... ms (threshold: 500 ms).
+   at 0x........: pthread_rwlock_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: main (hold_lock.c:?)
+rwlock 0x........ was first observed at:
+   at 0x........: pthread_rwlock_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (hold_lock.c:?)
+
+Locking rwlock shared ...
+Done.
+
+ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/hold_lock_1.vgtest b/drd/tests/hold_lock_1.vgtest
new file mode 100644
index 0000000..aeeddb3
--- /dev/null
+++ b/drd/tests/hold_lock_1.vgtest
@@ -0,0 +1,4 @@
+prereq: ./supported_libpthread
+prog: hold_lock
+vgopts: --exclusive-threshold=500 --shared-threshold=2000
+args: -i 1000
diff --git a/drd/tests/hold_lock_2.stderr.exp b/drd/tests/hold_lock_2.stderr.exp
new file mode 100644
index 0000000..81e355c
--- /dev/null
+++ b/drd/tests/hold_lock_2.stderr.exp
@@ -0,0 +1,17 @@
+
+Locking mutex ...
+Locking rwlock exclusively ...
+Locking rwlock shared ...
+Acquired at:
+   at 0x........: pthread_rwlock_rdlock (drd_pthread_intercepts.c:?)
+   by 0x........: main (hold_lock.c:?)
+Lock on rwlock 0x........ was held during ... ms (threshold: 500 ms).
+   at 0x........: pthread_rwlock_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: main (hold_lock.c:?)
+rwlock 0x........ was first observed at:
+   at 0x........: pthread_rwlock_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (hold_lock.c:?)
+
+Done.
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/hold_lock_2.vgtest b/drd/tests/hold_lock_2.vgtest
new file mode 100644
index 0000000..d1611b1
--- /dev/null
+++ b/drd/tests/hold_lock_2.vgtest
@@ -0,0 +1,4 @@
+prereq: ./supported_libpthread
+prog: hold_lock
+vgopts: --exclusive-threshold=2000 --shared-threshold=500
+args: -i 1000
diff --git a/drd/tests/linuxthreads_det.c b/drd/tests/linuxthreads_det.c
new file mode 100644
index 0000000..ec3e8ed
--- /dev/null
+++ b/drd/tests/linuxthreads_det.c
@@ -0,0 +1,35 @@
+/** Test whether DRD recognizes LinuxThreads as LinuxThreads and NPTL as
+ *  NPTL.
+ */
+
+
+#include <pthread.h>
+#include <semaphore.h>
+#include <unistd.h>
+
+
+static pid_t s_main_thread_pid;
+
+
+void* thread_func(void* arg)
+{
+  if (s_main_thread_pid == getpid())
+  {
+    write(STDOUT_FILENO, "NPTL or non-Linux POSIX threads implementation detected.\n", 57);
+  }
+  else
+  {
+    write(STDOUT_FILENO, "Detected LinuxThreads as POSIX threads implementation.\n", 55);
+  }
+  return 0;
+}
+
+int main(int argc, char** argv)
+{
+  pthread_t threadid;
+
+  s_main_thread_pid = getpid();
+  pthread_create(&threadid, 0, thread_func, 0);
+  pthread_join(threadid, 0);
+  return 0;
+}
diff --git a/drd/tests/linuxthreads_det.stderr.exp b/drd/tests/linuxthreads_det.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/linuxthreads_det.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/linuxthreads_det.stderr.exp-linuxthreads b/drd/tests/linuxthreads_det.stderr.exp-linuxthreads
new file mode 100644
index 0000000..7fff629
--- /dev/null
+++ b/drd/tests/linuxthreads_det.stderr.exp-linuxthreads
@@ -0,0 +1,7 @@
+
+Detected the LinuxThreads threading library. Sorry, but DRD only supports
+the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD
+after having upgraded to a newer version of your Linux distribution.
+Giving up.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/linuxthreads_det.stdout.exp b/drd/tests/linuxthreads_det.stdout.exp
new file mode 100644
index 0000000..e9e7dcf
--- /dev/null
+++ b/drd/tests/linuxthreads_det.stdout.exp
@@ -0,0 +1 @@
+NPTL or non-Linux POSIX threads implementation detected.
diff --git a/drd/tests/linuxthreads_det.stdout.exp-linuxthreads b/drd/tests/linuxthreads_det.stdout.exp-linuxthreads
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/drd/tests/linuxthreads_det.stdout.exp-linuxthreads
diff --git a/drd/tests/linuxthreads_det.vgtest b/drd/tests/linuxthreads_det.vgtest
new file mode 100644
index 0000000..0c4269d
--- /dev/null
+++ b/drd/tests/linuxthreads_det.vgtest
@@ -0,0 +1,2 @@
+prog: linuxthreads_det
+vgopts: --read-var-info=yes
diff --git a/drd/tests/matinv.c b/drd/tests/matinv.c
new file mode 100644
index 0000000..a63649b
--- /dev/null
+++ b/drd/tests/matinv.c
@@ -0,0 +1,367 @@
+/** Compute the matrix inverse via Gauss-Jordan elimination.
+ *  This program uses only barriers to separate computation steps but no
+ *  mutexes. It is an example of a race-free program on which no data races
+ *  are reported by the happens-before algorithm (drd), but a lot of data races
+ *  (all false positives) are reported by the Eraser-algorithm (helgrind).
+ */
+
+
+#define _GNU_SOURCE
+
+/***********************/
+/* Include directives. */
+/***********************/
+
+#include <assert.h>
+#include <math.h>
+#include <limits.h>  // PTHREAD_STACK_MIN
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>  // getopt()
+
+
+/*********************/
+/* Type definitions. */
+/*********************/
+
+typedef double elem_t;
+
+struct gj_threadinfo
+{
+  pthread_barrier_t* b;
+  pthread_t tid;
+  elem_t* a;
+  int rows;
+  int cols;
+  int r0;
+  int r1;
+};
+
+
+/********************/
+/* Local variables. */
+/********************/
+
+static int s_nthread = 1;
+
+
+/*************************/
+/* Function definitions. */
+/*************************/
+
+/** Allocate memory for a matrix with the specified number of rows and
+ *  columns.
+ */
+static elem_t* new_matrix(const int rows, const int cols)
+{
+  assert(rows > 0);
+  assert(cols > 0);
+  return malloc(rows * cols * sizeof(elem_t));
+}
+
+/** Free the memory that was allocated for a matrix. */
+static void delete_matrix(elem_t* const a)
+{
+  free(a);
+}
+
+/** Fill in some numbers in a matrix. */
+static void init_matrix(elem_t* const a, const int rows, const int cols)
+{
+  int i, j;
+  for (i = 0; i < rows; i++)
+  {
+    for (j = 0; j < rows; j++)
+    {
+      a[i * cols + j] = 1.0 / (1 + abs(i-j));
+    }
+  }
+}
+
+/** Print all elements of a matrix. */
+void print_matrix(const char* const label,
+                  const elem_t* const a, const int rows, const int cols)
+{
+  int i, j;
+  printf("%s:\n", label);
+  for (i = 0; i < rows; i++)
+  {
+    for (j = 0; j < cols; j++)
+    {
+      printf("%g ", a[i * cols + j]);
+    }
+    printf("\n");
+  }
+}
+
+/** Copy a subset of the elements of a matrix into another matrix. */
+static void copy_matrix(const elem_t* const from,
+                        const int from_rows,
+                        const int from_cols,
+                        const int from_row_first,
+                        const int from_row_last,
+                        const int from_col_first,
+                        const int from_col_last,
+                        elem_t* const to,
+                        const int to_rows,
+                        const int to_cols,
+                        const int to_row_first,
+                        const int to_row_last,
+                        const int to_col_first,
+                        const int to_col_last)
+{
+  int i, j;
+
+  assert(from_row_last - from_row_first == to_row_last - to_row_first);
+  assert(from_col_last - from_col_first == to_col_last - to_col_first);
+
+  for (i = from_row_first; i < from_row_last; i++)
+  {
+    assert(i < from_rows);
+    assert(i - from_row_first + to_row_first < to_rows);
+    for (j = from_col_first; j < from_col_last; j++)
+    {
+      assert(j < from_cols);
+      assert(j - from_col_first + to_col_first < to_cols);
+      to[(i - from_row_first + to_col_first) * to_cols
+         + (j - from_col_first + to_col_first)]
+        = from[i * from_cols + j];
+    }
+  }
+}
+
+/** Compute the matrix product of a1 and a2. */
+static elem_t* multiply_matrices(const elem_t* const a1,
+                                 const int rows1,
+                                 const int cols1,
+                                 const elem_t* const a2,
+                                 const int rows2,
+                                 const int cols2)
+{
+  int i, j, k;
+  elem_t* prod;
+
+  assert(cols1 == rows2);
+
+  prod = new_matrix(rows1, cols2);
+  for (i = 0; i < rows1; i++)
+  {
+    for (j = 0; j < cols2; j++)
+    {
+      prod[i * cols2 + j] = 0;
+      for (k = 0; k < cols1; k++)
+      {
+        prod[i * cols2 + j] += a1[i * cols1 + k] * a2[k * cols2 + j];
+      }
+    }
+  }
+  return prod;
+}
+
+/** Apply the Gauss-Jordan elimination algorithm on the matrix p->a starting
+ *  at row r0 and up to but not including row r1. It is assumed that as many
+ *  threads execute this function concurrently as the count barrier p->b was
+ *  initialized with. If the matrix p->a is nonsingular, and if matrix p->a
+ *  has at least as many columns as rows, the result of this algorithm is that
+ *  submatrix p->a[0..p->rows-1,0..p->rows-1] is the identity matrix.
+ * @see http://en.wikipedia.org/wiki/Gauss-Jordan_elimination
+ */
+static void gj_threadfunc(struct gj_threadinfo* p)
+{
+  int i, j, k;
+  elem_t* const a = p->a;
+  const int rows = p->rows;
+  const int cols = p->cols;
+
+  for (i = 0; i < p->rows; i++)
+  {
+    if (pthread_barrier_wait(p->b) == PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      // Pivoting.
+      j = i;
+      for (k = i + 1; k < rows; k++)
+      {
+        if (a[k * cols + i] > a[j * cols + i])
+        {
+          j = k;
+        }
+      }
+      if (j != i)
+      {
+        for (k = 0; k < cols; k++)
+        {
+          const elem_t t = a[i * cols + k];
+          a[i * cols + k] = a[j * cols + k];
+          a[j * cols + k] = t;
+        }
+      }
+      // Normalize row i.
+      if (a[i * cols + i] != 0)
+      {
+        for (k = cols - 1; k >= 0; k--)
+        {
+          a[i * cols + k] /= a[i * cols + i];
+        }
+      }
+    }
+    pthread_barrier_wait(p->b);
+    // Reduce all rows j != i.
+    for (j = p->r0; j < p->r1; j++)
+    {
+      if (i != j)
+      {
+        const elem_t factor = a[j * cols + i];
+        for (k = 0; k < cols; k++)
+        {
+          a[j * cols + k] -= a[i * cols + k] * factor;
+        }
+      }
+    }
+  }
+}
+
+/** Multithreaded Gauss-Jordan algorithm. */
+static void gj(elem_t* const a, const int rows, const int cols)
+{
+  int i;
+  struct gj_threadinfo* t;
+  pthread_barrier_t b;
+  pthread_attr_t attr;
+  int err;
+
+  assert(rows <= cols);
+
+  t = malloc(sizeof(struct gj_threadinfo) * s_nthread);
+
+  pthread_barrier_init(&b, 0, s_nthread);
+
+  pthread_attr_init(&attr);
+  err = pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + 4096);
+  assert(err == 0);
+
+  for (i = 0; i < s_nthread; i++)
+  {
+    t[i].b = &b;
+    t[i].a = a;
+    t[i].rows = rows;
+    t[i].cols = cols;
+    t[i].r0 = i * rows / s_nthread;
+    t[i].r1 = (i+1) * rows / s_nthread;
+    pthread_create(&t[i].tid, &attr, (void*(*)(void*))gj_threadfunc, &t[i]);
+  }
+
+  pthread_attr_destroy(&attr);
+
+  for (i = 0; i < s_nthread; i++)
+  {
+    pthread_join(t[i].tid, 0);
+  }
+
+  pthread_barrier_destroy(&b);
+
+  free(t);
+}
+
+/** Matrix inversion via the Gauss-Jordan algorithm. */
+static elem_t* invert_matrix(const elem_t* const a, const int n)
+{
+  int i, j;
+  elem_t* const inv = new_matrix(n, n);
+  elem_t* const tmp = new_matrix(n, 2*n);
+  copy_matrix(a, n, n, 0, n, 0, n, tmp, n, 2 * n, 0, n, 0, n);
+  for (i = 0; i < n; i++)
+    for (j = 0; j < n; j++)
+      tmp[i * 2 * n + n + j] = (i == j);
+  gj(tmp, n, 2*n);
+  copy_matrix(tmp, n, 2*n, 0, n, n, 2*n, inv, n, n, 0, n, 0, n);
+  delete_matrix(tmp);
+  return inv;
+}
+
+/** Compute the average square error between the identity matrix and the
+ * product of matrix a with its inverse matrix.
+ */
+static double identity_error(const elem_t* const a, const int n)
+{
+  int i, j;
+  elem_t e = 0;
+  for (i = 0; i < n; i++)
+  {
+    for (j = 0; j < n; j++)
+    {
+      const elem_t d = a[i * n + j] - (i == j);
+      e += d * d;
+    }
+  }
+  return sqrt(e / (n * n));
+}
+
+/** Compute epsilon for the numeric type elem_t. Epsilon is defined as the
+ *  smallest number for which the sum of one and that number is different of
+ *  one. It is assumed that the underlying representation of elem_t uses
+ *  base two.
+ */
+static elem_t epsilon()
+{
+  elem_t eps;
+  for (eps = 1; 1 + eps != 1; eps /= 2)
+    ;
+  return 2 * eps;
+}
+
+int main(int argc, char** argv)
+{
+  int matrix_size;
+  int silent = 0;
+  int optchar;
+  elem_t *a, *inv, *prod;
+  elem_t eps;
+  double error;
+  double ratio;
+
+  while ((optchar = getopt(argc, argv, "qt:")) != EOF)
+  {
+    switch (optchar)
+    {
+    case 'q': silent = 1; break;
+    case 't': s_nthread = atoi(optarg); break;
+    default:
+      fprintf(stderr, "Error: unknown option '%c'.\n", optchar);
+      return 1;
+    }
+  }
+
+  if (optind + 1 != argc)
+  {
+    fprintf(stderr, "Error: wrong number of arguments.\n");
+  }
+  matrix_size = atoi(argv[optind]);
+
+  /* Error checking. */
+  assert(matrix_size >= 1);
+  assert(s_nthread >= 1);
+
+  eps = epsilon();
+  a = new_matrix(matrix_size, matrix_size);
+  init_matrix(a, matrix_size, matrix_size);
+  inv = invert_matrix(a, matrix_size);
+  prod = multiply_matrices(a, matrix_size, matrix_size,
+                           inv, matrix_size, matrix_size);
+  error = identity_error(prod, matrix_size);
+  ratio = error / (eps * matrix_size);
+  if (! silent)
+  {
+    printf("error = %g; epsilon = %g; error / (epsilon * n) = %g\n",
+           error, eps, ratio);
+  }
+  if (isfinite(ratio) && ratio < 100)
+    printf("Error within bounds.\n");
+  else
+    printf("Error out of bounds.\n");
+  delete_matrix(prod);
+  delete_matrix(inv);
+  delete_matrix(a);
+
+  return 0;
+}
diff --git a/drd/tests/matinv.stderr.exp b/drd/tests/matinv.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/matinv.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/matinv.stdout.exp b/drd/tests/matinv.stdout.exp
new file mode 100644
index 0000000..3035da4
--- /dev/null
+++ b/drd/tests/matinv.stdout.exp
@@ -0,0 +1 @@
+Error within bounds.
diff --git a/drd/tests/matinv.vgtest b/drd/tests/matinv.vgtest
new file mode 100644
index 0000000..da2a6e4
--- /dev/null
+++ b/drd/tests/matinv.vgtest
@@ -0,0 +1,3 @@
+prereq: test -e matinv && ./supported_libpthread
+prog: matinv
+args: 30 -t 15 -q
diff --git a/drd/tests/memory_allocation.c b/drd/tests/memory_allocation.c
new file mode 100644
index 0000000..1072489
--- /dev/null
+++ b/drd/tests/memory_allocation.c
@@ -0,0 +1,38 @@
+/**
+ * @brief Repeatedly allocate and free memory. Tests whether drd really frees
+ *        memory allocated by a client. See also
+ *        http://bugs.kde.org/show_bug.cgi?id=161036.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+
+int main()
+{
+  int i;
+  void* p;
+
+  for (i = 0; i < 100000; i++)
+    free(malloc(40960));
+
+  for (i = 0; i < 100000; i++)
+  {
+    p = realloc(NULL, 40960);
+    p = realloc(p, 50000);
+    p = realloc(p, 40000);
+    p = realloc(p, 0);
+    /*
+     * glibc returns a NULL pointer when the size argument passed to realloc()
+     * is zero, while Darwin's C library returns a non-NULL pointer. Both are
+     * allowed by POSIX.
+     */
+#if defined(__APPLE__)
+    if (p)
+      free(p);
+#else
+    assert(! p);
+#endif
+  }
+
+  return 0;
+}
diff --git a/drd/tests/memory_allocation.stderr.exp b/drd/tests/memory_allocation.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/memory_allocation.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/memory_allocation.vgtest b/drd/tests/memory_allocation.vgtest
new file mode 100644
index 0000000..40ca8ed
--- /dev/null
+++ b/drd/tests/memory_allocation.vgtest
@@ -0,0 +1,2 @@
+prog: memory_allocation
+prereq: ./supported_libpthread
diff --git a/drd/tests/monitor_example.cpp b/drd/tests/monitor_example.cpp
new file mode 100644
index 0000000..4a660cc
--- /dev/null
+++ b/drd/tests/monitor_example.cpp
@@ -0,0 +1,231 @@
+/*
+   An example that shows how to implement the monitor synchronization concept.
+   See also http://en.wikipedia.org/wiki/Monitor_(synchronization) for more
+   information about this concept.
+  
+   ----------------------------------------------------------------
+
+   Notice that the following BSD-style license applies to this one
+   file (monitor_example.cpp) only.  The rest of Valgrind is licensed
+   under the terms of the GNU General Public License, version 2,
+   unless otherwise indicated.  See the COPYING file in the source
+   distribution for details.
+
+   ----------------------------------------------------------------
+
+   This file is part of DRD, a heavyweight Valgrind tool for detecting
+   errors in multithreaded programs.
+
+   Copyright (C) 2008-2009 Bart Van Assche. All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   1. Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+   2. The origin of this software must not be misrepresented; you must 
+      not claim that you wrote the original software.  If you use this 
+      software in a product, an acknowledgment in the product 
+      documentation would be appreciated but is not required.
+
+   3. Altered source versions must be plainly marked as such, and must
+      not be misrepresented as being the original software.
+
+   4. The name of the author may not be used to endorse or promote 
+      products derived from this software without specific prior written 
+      permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+   ----------------------------------------------------------------
+
+   Notice that the above BSD-style license applies to this one
+   file (monitor_example.cpp) only.  The rest of Valgrind is licensed
+   under the terms of the GNU General Public License, version 2,
+   unless otherwise indicated.  See the COPYING file in the source
+   distribution for details.
+
+   ---------------------------------------------------------------- 
+*/
+
+
+#define _GNU_SOURCE 1
+
+
+#include "config.h"
+#include <cassert>
+#include <iostream>
+#include <pthread.h>
+
+
+class Monitor
+{
+public:
+  Monitor()
+    : m_mutex()
+    , m_cond()
+    , m_owner()
+    , m_recursion_count()
+  {
+    pthread_mutexattr_t mutexattr;
+    pthread_mutexattr_init(&mutexattr);
+    pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
+    pthread_mutex_init(&m_mutex, &mutexattr);
+    pthread_mutexattr_destroy(&mutexattr);
+    pthread_condattr_t condattr;
+    pthread_condattr_init(&condattr);
+#if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK)
+    pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC);
+#endif
+    pthread_cond_init(&m_cond, &condattr);
+    pthread_condattr_destroy(&condattr);
+  }
+  ~Monitor()
+  {
+    assert(m_recursion_count == 0);
+    pthread_cond_destroy(&m_cond);
+    pthread_mutex_destroy(&m_mutex);
+  }
+  void lock()
+  {
+    pthread_mutex_lock(&m_mutex);
+    assert(m_recursion_count >= 0);
+    if (++m_recursion_count == 1)
+    {
+      m_owner = pthread_self();
+    }
+  }
+  void unlock()
+  {
+    m_recursion_count--;
+    assert(m_recursion_count >= 0);
+    pthread_mutex_unlock(&m_mutex);
+  }
+  void wait()
+  {
+    assert(m_recursion_count == 1);
+    assert(m_owner == pthread_self());
+    m_recursion_count--;
+    pthread_cond_wait(&m_cond, &m_mutex);
+    m_recursion_count++;
+    m_owner = pthread_self();
+  }
+  void signal()
+  {
+    assert(m_recursion_count > 0);
+    pthread_cond_signal(&m_cond);
+  }
+  void broadcast_signal()
+  {
+    assert(m_recursion_count > 0);
+    pthread_cond_broadcast(&m_cond);
+  }
+  bool is_locked_by_self()
+  {
+    bool result;
+    pthread_mutex_lock(&m_mutex);
+    result = m_recursion_count > 0 && m_owner == pthread_self();
+    pthread_mutex_unlock(&m_mutex);
+    return result;
+  }
+
+private:
+  Monitor(const Monitor&);
+  Monitor& operator=(const Monitor&);
+
+  pthread_mutex_t m_mutex;
+  pthread_cond_t  m_cond;
+  pthread_t       m_owner;
+  int             m_recursion_count;
+};
+
+
+class ScopedLock
+{
+public:
+  ScopedLock(Monitor& m)
+    : m_monitor(m)
+    , m_locked(false)
+  { lock(); }
+  ~ScopedLock()
+  { if (m_locked) unlock(); }
+  void lock()
+  { assert(! m_locked); m_monitor.lock(); m_locked = true; }
+  void unlock()
+  { assert(m_locked); m_locked = false; m_monitor.unlock(); }
+
+private:
+  ScopedLock(const ScopedLock&);
+  ScopedLock& operator=(const ScopedLock&);
+
+  Monitor& m_monitor;
+  bool     m_locked;
+};
+
+
+class StateVariable
+{
+public:
+  StateVariable()
+    : m_state()
+  { }
+  int get()
+  {
+    ScopedLock sl(m_monitor);
+    return m_state;
+  }
+  void set(const int state)
+  {
+    ScopedLock sl(m_monitor);
+    m_state = state;
+    m_monitor.signal();
+  }
+  void wait(const int state)
+  {
+    ScopedLock sl(m_monitor);
+    while (m_state != state)
+      m_monitor.wait();
+  }
+
+private:
+  Monitor m_monitor;
+  int     m_state;
+};
+
+
+static StateVariable s_sv;
+
+
+static void* thread_func(void*)
+{
+  s_sv.wait(1);
+  s_sv.set(2);
+  s_sv.wait(3);
+  s_sv.set(4);
+  return 0;
+}
+
+int main(int, char**)
+{
+  pthread_t tid;
+  pthread_create(&tid, 0, thread_func, 0);
+  s_sv.set(1);
+  s_sv.wait(2);
+  s_sv.set(3);
+  s_sv.wait(4);
+  pthread_join(tid, 0);
+  std::cerr << "Finished successfully.\n";
+  return 0;
+}
diff --git a/drd/tests/monitor_example.stderr.exp b/drd/tests/monitor_example.stderr.exp
new file mode 100644
index 0000000..a4e94d2
--- /dev/null
+++ b/drd/tests/monitor_example.stderr.exp
@@ -0,0 +1,4 @@
+
+Finished successfully.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/monitor_example.vgtest b/drd/tests/monitor_example.vgtest
new file mode 100644
index 0000000..27264aa
--- /dev/null
+++ b/drd/tests/monitor_example.vgtest
@@ -0,0 +1,2 @@
+prereq: ./supported_libpthread
+prog: monitor_example
diff --git a/drd/tests/new_delete.cpp b/drd/tests/new_delete.cpp
new file mode 100644
index 0000000..45664c1
--- /dev/null
+++ b/drd/tests/new_delete.cpp
@@ -0,0 +1,19 @@
+/** Simple regression test triggering the C++ operators new and delete. */
+
+#include <stdio.h>
+
+int main(int argc, char** argv)
+{
+  int zero = 0;
+  int* p = new int;
+  int* q = new int[733];
+  delete[] q;
+  delete p;
+
+  q = new int[zero];
+  delete q;
+
+  fprintf(stderr, "Success.\n");
+
+  return 0;
+}
diff --git a/drd/tests/new_delete.stderr.exp b/drd/tests/new_delete.stderr.exp
new file mode 100644
index 0000000..06ad776
--- /dev/null
+++ b/drd/tests/new_delete.stderr.exp
@@ -0,0 +1,4 @@
+
+Success.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/new_delete.vgtest b/drd/tests/new_delete.vgtest
new file mode 100644
index 0000000..1d9a37c
--- /dev/null
+++ b/drd/tests/new_delete.vgtest
@@ -0,0 +1,2 @@
+prereq: ./supported_libpthread
+prog: new_delete
diff --git a/drd/tests/omp_matinv.c b/drd/tests/omp_matinv.c
new file mode 100644
index 0000000..cd402ab
--- /dev/null
+++ b/drd/tests/omp_matinv.c
@@ -0,0 +1,346 @@
+/** Compute the matrix inverse via Gauss-Jordan elimination.
+ *  This program uses OpenMP separate computation steps but no
+ *  mutexes. It is an example of a race-free program on which no data races
+ *  are reported by the happens-before algorithm (drd), but a lot of data races
+ *  (all false positives) are reported by the Eraser-algorithm (helgrind).
+ */
+
+
+#define _GNU_SOURCE
+
+/***********************/
+/* Include directives. */
+/***********************/
+
+#include <assert.h>
+#include <math.h>
+#include <omp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>  // getopt()
+
+
+/*********************/
+/* Type definitions. */
+/*********************/
+
+typedef double elem_t;
+
+
+/********************/
+/* Local variables. */
+/********************/
+
+static int s_trigger_race;
+
+
+/*************************/
+/* Function definitions. */
+/*************************/
+
+/** Allocate memory for a matrix with the specified number of rows and
+ *  columns.
+ */
+static elem_t* new_matrix(const int rows, const int cols)
+{
+  assert(rows > 0);
+  assert(cols > 0);
+  return malloc(rows * cols * sizeof(elem_t));
+}
+
+/** Free the memory that was allocated for a matrix. */
+static void delete_matrix(elem_t* const a)
+{
+  free(a);
+}
+
+/** Fill in some numbers in a matrix. */
+static void init_matrix(elem_t* const a, const int rows, const int cols)
+{
+  int i, j;
+  for (i = 0; i < rows; i++)
+  {
+    for (j = 0; j < rows; j++)
+    {
+      a[i * cols + j] = 1.0 / (1 + abs(i-j));
+    }
+  }
+}
+
+/** Print all elements of a matrix. */
+void print_matrix(const char* const label,
+                  const elem_t* const a, const int rows, const int cols)
+{
+  int i, j;
+  printf("%s:\n", label);
+  for (i = 0; i < rows; i++)
+  {
+    for (j = 0; j < cols; j++)
+    {
+      printf("%g ", a[i * cols + j]);
+    }
+    printf("\n");
+  }
+}
+
+/** Copy a subset of the elements of a matrix into another matrix. */
+static void copy_matrix(const elem_t* const from,
+                        const int from_rows,
+                        const int from_cols,
+                        const int from_row_first,
+                        const int from_row_last,
+                        const int from_col_first,
+                        const int from_col_last,
+                        elem_t* const to,
+                        const int to_rows,
+                        const int to_cols,
+                        const int to_row_first,
+                        const int to_row_last,
+                        const int to_col_first,
+                        const int to_col_last)
+{
+  int i, j;
+
+  assert(from_row_last - from_row_first == to_row_last - to_row_first);
+  assert(from_col_last - from_col_first == to_col_last - to_col_first);
+
+  for (i = from_row_first; i < from_row_last; i++)
+  {
+    assert(i < from_rows);
+    assert(i - from_row_first + to_row_first < to_rows);
+    for (j = from_col_first; j < from_col_last; j++)
+    {
+      assert(j < from_cols);
+      assert(j - from_col_first + to_col_first < to_cols);
+      to[(i - from_row_first + to_col_first) * to_cols
+         + (j - from_col_first + to_col_first)]
+        = from[i * from_cols + j];
+    }
+  }
+}
+
+/** Compute the matrix product of a1 and a2. */
+static elem_t* multiply_matrices(const elem_t* const a1,
+                                 const int rows1,
+                                 const int cols1,
+                                 const elem_t* const a2,
+                                 const int rows2,
+                                 const int cols2)
+{
+  int i, j, k;
+  elem_t* prod;
+
+  assert(cols1 == rows2);
+
+  prod = new_matrix(rows1, cols2);
+  for (i = 0; i < rows1; i++)
+  {
+    for (j = 0; j < cols2; j++)
+    {
+      prod[i * cols2 + j] = 0;
+      for (k = 0; k < cols1; k++)
+      {
+        prod[i * cols2 + j] += a1[i * cols1 + k] * a2[k * cols2 + j];
+      }
+    }
+  }
+  return prod;
+}
+
+/** Apply the Gauss-Jordan elimination algorithm on the matrix p->a starting
+ *  at row r0 and up to but not including row r1. It is assumed that as many
+ *  threads execute this function concurrently as the count barrier p->b was
+ *  initialized with. If the matrix p->a is nonsingular, and if matrix p->a
+ *  has at least as many columns as rows, the result of this algorithm is that
+ *  submatrix p->a[0..p->rows-1,0..p->rows-1] is the identity matrix.
+ * @see http://en.wikipedia.org/wiki/Gauss-Jordan_elimination
+ */
+static void gj(elem_t* const a, const int rows, const int cols)
+{
+  int i, j, k;
+
+  for (i = 0; i < rows; i++)
+  {
+    {
+      // Pivoting.
+      j = i;
+      for (k = i + 1; k < rows; k++)
+      {
+        if (a[k * cols + i] > a[j * cols + i])
+        {
+          j = k;
+        }
+      }
+      if (j != i)
+      {
+        for (k = 0; k < cols; k++)
+        {
+          const elem_t t = a[i * cols + k];
+          a[i * cols + k] = a[j * cols + k];
+          a[j * cols + k] = t;
+        }
+      }
+      // Normalize row i.
+      if (a[i * cols + i] != 0)
+      {
+        for (k = cols - 1; k >= 0; k--)
+        {
+          a[i * cols + k] /= a[i * cols + i];
+        }
+      }
+    }
+
+    // Reduce all rows j != i.
+
+    if (s_trigger_race)
+    {
+#     pragma omp parallel for private(j)
+      for (j = 0; j < rows; j++)
+      {
+        if (i != j)
+        {
+          const elem_t factor = a[j * cols + i];
+          for (k = 0; k < cols; k++)
+          {
+            a[j * cols + k] -= a[i * cols + k] * factor;
+          }
+        }
+      }
+    }
+    else
+    {
+#     pragma omp parallel for private(j, k)
+      for (j = 0; j < rows; j++)
+      {
+        if (i != j)
+        {
+          const elem_t factor = a[j * cols + i];
+          for (k = 0; k < cols; k++)
+          {
+            a[j * cols + k] -= a[i * cols + k] * factor;
+          }
+        }
+      }
+    }
+  }
+}
+
+/** Matrix inversion via the Gauss-Jordan algorithm. */
+static elem_t* invert_matrix(const elem_t* const a, const int n)
+{
+  int i, j;
+  elem_t* const inv = new_matrix(n, n);
+  elem_t* const tmp = new_matrix(n, 2*n);
+  copy_matrix(a, n, n, 0, n, 0, n, tmp, n, 2 * n, 0, n, 0, n);
+  for (i = 0; i < n; i++)
+    for (j = 0; j < n; j++)
+      tmp[i * 2 * n + n + j] = (i == j);
+  gj(tmp, n, 2*n);
+  copy_matrix(tmp, n, 2*n, 0, n, n, 2*n, inv, n, n, 0, n, 0, n);
+  delete_matrix(tmp);
+  return inv;
+}
+
+/** Compute the average square error between the identity matrix and the
+ * product of matrix a with its inverse matrix.
+ */
+static double identity_error(const elem_t* const a, const int n)
+{
+  int i, j;
+  elem_t e = 0;
+  for (i = 0; i < n; i++)
+  {
+    for (j = 0; j < n; j++)
+    {
+      const elem_t d = a[i * n + j] - (i == j);
+      e += d * d;
+    }
+  }
+  return sqrt(e / (n * n));
+}
+
+/** Compute epsilon for the numeric type elem_t. Epsilon is defined as the
+ *  smallest number for which the sum of one and that number is different of
+ *  one. It is assumed that the underlying representation of elem_t uses
+ *  base two.
+ */
+static elem_t epsilon()
+{
+  elem_t eps;
+  for (eps = 1; 1 + eps != 1; eps /= 2)
+    ;
+  return 2 * eps;
+}
+
+static void usage(const char* const exe)
+{
+  printf("Usage: %s [-h] [-q] [-r] [-t<n>] <m>\n"
+         "-h: display this information.\n"
+         "-q: quiet mode -- do not print computed error.\n"
+         "-r: trigger a race condition.\n"
+         "-t<n>: use <n> threads.\n"
+         "<m>: matrix size.\n",
+         exe);
+}
+
+int main(int argc, char** argv)
+{
+  int matrix_size;
+  int nthread = 1;
+  int silent = 0;
+  int optchar;
+  elem_t *a, *inv, *prod;
+  elem_t eps;
+  double error;
+  double ratio;
+
+  while ((optchar = getopt(argc, argv, "hqrt:")) != EOF)
+  {
+    switch (optchar)
+    {
+    case 'h': usage(argv[0]); return 1;
+    case 'q': silent = 1; break;
+    case 'r': s_trigger_race = 1; break;
+    case 't': nthread = atoi(optarg); break;
+    default:
+      return 1;
+    }
+  }
+
+  if (optind + 1 != argc)
+  {
+    fprintf(stderr, "Error: wrong number of arguments.\n");
+    return 1;
+  }
+  matrix_size = atoi(argv[optind]);
+
+  /* Error checking. */
+  assert(matrix_size >= 1);
+  assert(nthread >= 1);
+
+  omp_set_num_threads(nthread);
+  omp_set_dynamic(0);
+
+  eps = epsilon();
+  a = new_matrix(matrix_size, matrix_size);
+  init_matrix(a, matrix_size, matrix_size);
+  inv = invert_matrix(a, matrix_size);
+  prod = multiply_matrices(a, matrix_size, matrix_size,
+                           inv, matrix_size, matrix_size);
+  error = identity_error(prod, matrix_size);
+  ratio = error / (eps * matrix_size);
+  if (! silent)
+  {
+    printf("error = %g; epsilon = %g; error / (epsilon * n) = %g\n",
+           error, eps, ratio);
+  }
+  if (isfinite(ratio) && ratio < 100)
+    printf("Error within bounds.\n");
+  else
+    printf("Error out of bounds.\n");
+  delete_matrix(prod);
+  delete_matrix(inv);
+  delete_matrix(a);
+
+  return 0;
+}
diff --git a/drd/tests/omp_matinv.stderr.exp b/drd/tests/omp_matinv.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/omp_matinv.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/omp_matinv.stdout.exp b/drd/tests/omp_matinv.stdout.exp
new file mode 100644
index 0000000..3035da4
--- /dev/null
+++ b/drd/tests/omp_matinv.stdout.exp
@@ -0,0 +1 @@
+Error within bounds.
diff --git a/drd/tests/omp_matinv.vgtest b/drd/tests/omp_matinv.vgtest
new file mode 100644
index 0000000..c9d5ec1
--- /dev/null
+++ b/drd/tests/omp_matinv.vgtest
@@ -0,0 +1,4 @@
+prereq: ./run_openmp_test ./omp_matinv
+prog: omp_matinv
+vgopts: --check-stack-var=yes --read-var-info=yes
+args: 30 -t 15 -q
diff --git a/drd/tests/omp_matinv_racy.stderr.exp b/drd/tests/omp_matinv_racy.stderr.exp
new file mode 100644
index 0000000..8340d6c
--- /dev/null
+++ b/drd/tests/omp_matinv_racy.stderr.exp
@@ -0,0 +1 @@
+ERROR SUMMARY: 76 errors from 7 contexts
diff --git a/drd/tests/omp_matinv_racy.stdout.exp b/drd/tests/omp_matinv_racy.stdout.exp
new file mode 100644
index 0000000..3035da4
--- /dev/null
+++ b/drd/tests/omp_matinv_racy.stdout.exp
@@ -0,0 +1 @@
+Error within bounds.
diff --git a/drd/tests/omp_matinv_racy.vgtest b/drd/tests/omp_matinv_racy.vgtest
new file mode 100644
index 0000000..96a0f0f
--- /dev/null
+++ b/drd/tests/omp_matinv_racy.vgtest
@@ -0,0 +1,5 @@
+prereq: ./run_openmp_test ./omp_matinv
+prog: omp_matinv
+vgopts: --check-stack-var=yes --read-var-info=yes
+args: 3 -t 2 -q -r
+stderr_filter: filter_error_summary
diff --git a/drd/tests/omp_prime.c b/drd/tests/omp_prime.c
new file mode 100644
index 0000000..bfa67ec
--- /dev/null
+++ b/drd/tests/omp_prime.c
@@ -0,0 +1,114 @@
+/** An OpenMP example.
+ *  Based on the example listed on the following web page:
+ *  http://developers.sun.com/sunstudio/downloads/ssx/tha/tha_using.html
+ */
+
+
+#include <assert.h>
+#include <math.h>
+#include <omp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>  // getopt()
+#include "../../drd/drd.h"
+
+
+static int is_prime(int* const pflag, int v)
+{
+  int i;
+  int bound = floor(sqrt ((double)v)) + 1;
+
+  for (i = 2; i < bound; i++)
+  {
+    /* No need to check against known composites */
+    if (!pflag[i])
+      continue;
+    if (v % i == 0)
+    {
+      pflag[v] = 0;
+      return 0;
+    }
+  }
+  return (v > 1);
+}
+
+int main(int argc, char **argv)
+{
+  int i;
+  int total = 0;
+  int trace_total = 0;
+  int silent = 0;
+  int n;
+  int num_threads = 2;
+  int optchar;
+  int* primes;
+  int* pflag;
+
+  while ((optchar = getopt(argc, argv, "qt:v")) != EOF)
+  {
+    switch (optchar)
+    {
+    case 'q':
+      silent = 1;
+      break;
+    case 't':
+      num_threads = atoi(optarg);
+      break;
+    case 'v':
+      trace_total = 1;
+      break;
+    default:
+      fprintf(stderr, "Error: unknown option '%c'.\n", optchar);
+      return 1;
+    }
+  }
+
+  if (optind + 1 != argc)
+  {
+    fprintf(stderr, "Error: wrong number of arguments.\n");
+    return 1;
+  }
+  n = atoi(argv[optind]);
+
+  // Not the most user-friendly way to do error checking, but better than
+  // nothing.
+  assert(n > 2);
+  assert(num_threads >= 1);
+
+  primes = malloc(n * sizeof(primes[0]));
+  pflag  = malloc(n * sizeof(pflag[0]));
+
+  omp_set_num_threads(num_threads);
+  omp_set_dynamic(0);
+
+  for (i = 0; i < n; i++) {
+    pflag[i] = 1;
+  }
+
+  if (trace_total)
+    DRD_TRACE_VAR(total);
+
+#pragma omp parallel for
+  for (i = 2; i < n; i++)
+  {
+    if (is_prime(pflag, i))
+    {
+      primes[total] = i;
+      total++;
+    }
+  }
+  if (! silent)
+  {
+    printf("Number of prime numbers between 2 and %d: %d\n",
+           n, total);
+    for (i = 0; i < total; i++)
+    {
+      printf("%d\n", primes[i]);
+    }
+  }
+
+  free(pflag);
+  free(primes);
+
+  return 0;
+}
diff --git a/drd/tests/omp_prime_racy.stderr.exp b/drd/tests/omp_prime_racy.stderr.exp
new file mode 100644
index 0000000..629d6fc
--- /dev/null
+++ b/drd/tests/omp_prime_racy.stderr.exp
@@ -0,0 +1 @@
+ERROR SUMMARY: 3 errors from 3 contexts
diff --git a/drd/tests/omp_prime_racy.vgtest b/drd/tests/omp_prime_racy.vgtest
new file mode 100644
index 0000000..59381c9
--- /dev/null
+++ b/drd/tests/omp_prime_racy.vgtest
@@ -0,0 +1,5 @@
+prereq: ./run_openmp_test ./omp_prime
+prog: omp_prime
+vgopts: --check-stack-var=yes --read-var-info=yes
+args: 4 -q
+stderr_filter: filter_error_summary
diff --git a/drd/tests/omp_printf.c b/drd/tests/omp_printf.c
new file mode 100644
index 0000000..3f6f5fa
--- /dev/null
+++ b/drd/tests/omp_printf.c
@@ -0,0 +1,71 @@
+/* Simple OpenMP test program that calls printf() from a parallel section. */
+
+#include <assert.h>  // assert()
+#include <omp.h>
+#include <stdio.h>
+#include <stdlib.h>  // atoi()
+#include <unistd.h>  // getopt()
+
+static void usage(const char* const exe)
+{
+  fprintf(stderr,
+          "Usage: %s [-h] [-i <n>] [-q] [-t<n>]\n"
+          "-h: display this information.\n"
+          "-i <n>: number of loop iterations.\n"
+          "-q: quiet mode -- do not print computed error.\n"
+          "-t <n>: number of OMP threads.\n",
+          exe);
+}
+
+int main(int argc, char** argv)
+{
+  int i;
+  int optchar;
+  int silent = 0;
+  int tid;
+  int num_iterations = 2;
+  int num_threads = 2;
+
+  while ((optchar = getopt(argc, argv, "hi:qt:")) != EOF)
+  {
+    switch (optchar)
+    {
+    case 'h': usage(argv[0]); return 1;
+    case 'i': num_iterations = atoi(optarg); break;
+    case 'q': silent = 1; break;
+    case 't': num_threads = atoi(optarg); break;
+    default:
+      return 1;
+    }
+  }
+
+  /*
+   * Not the most user-friendly way of error checking, but still better than
+   * no error checking.
+   */
+  assert(num_iterations > 0);
+  assert(num_threads > 0);
+
+  omp_set_num_threads(num_threads);
+  omp_set_dynamic(0);
+
+#pragma omp parallel for private(tid)
+  for (i = 0; i < num_iterations; i++)
+  {
+    tid = omp_get_thread_num();
+    if (! silent)
+    {
+      fprintf(stderr,
+              "iteration %d; thread number = %d; number of threads = %d\n",
+              i, tid, omp_get_num_threads());
+    }
+    else
+    {
+      fprintf(stderr, "%s", "");
+    }
+  }
+
+  fprintf(stderr, "Finished.\n");
+
+  return 0;
+}
diff --git a/drd/tests/omp_printf.stderr.exp b/drd/tests/omp_printf.stderr.exp
new file mode 100644
index 0000000..a7089bb
--- /dev/null
+++ b/drd/tests/omp_printf.stderr.exp
@@ -0,0 +1,4 @@
+
+Finished.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/omp_printf.vgtest b/drd/tests/omp_printf.vgtest
new file mode 100644
index 0000000..0725404
--- /dev/null
+++ b/drd/tests/omp_printf.vgtest
@@ -0,0 +1,4 @@
+prereq: ./run_openmp_test ./omp_printf
+prog: omp_printf
+vgopts: --check-stack-var=yes --read-var-info=yes
+args: -i 100 -q -t 10
diff --git a/drd/tests/pth_barrier.c b/drd/tests/pth_barrier.c
new file mode 100644
index 0000000..e0b40a7
--- /dev/null
+++ b/drd/tests/pth_barrier.c
@@ -0,0 +1,110 @@
+/* Test whether all data races are detected in a multithreaded program with
+ * barriers.
+ */
+
+
+#define _GNU_SOURCE
+
+/***********************/
+/* Include directives. */
+/***********************/
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+/*********************/
+/* Type definitions. */
+/*********************/
+
+struct threadinfo
+{
+  pthread_barrier_t* b;
+  pthread_t          tid;
+  int*               array;
+  int                iterations;
+};
+
+
+/********************/
+/* Local variables. */
+/********************/
+
+static int s_silent;
+
+
+/*************************/
+/* Function definitions. */
+/*************************/
+
+/** Single thread, which touches p->iterations elements of array p->array.
+ * Each modification of an element of p->array is a data race. */
+static void* threadfunc(struct threadinfo* p)
+{
+  int i;
+  int* const array = p->array;
+  pthread_barrier_t* const b = p->b;
+  if (! s_silent)
+    printf("thread %lx iteration 0\n", pthread_self());
+  pthread_barrier_wait(b);
+  for (i = 0; i < p->iterations; i++)
+  {
+    if (! s_silent)
+      printf("thread %lx iteration %d; writing to %p\n",
+             pthread_self(), i + 1, &array[i]);
+    array[i] = i;
+    pthread_barrier_wait(b);
+  }
+  return 0;
+}
+
+/** Actual test, consisting of nthread threads. */
+static void barriers_and_races(const int nthread, const int iterations)
+{
+  int i;
+  struct threadinfo* t;
+  pthread_barrier_t b;
+  int* array;
+
+  t = malloc(nthread * sizeof(struct threadinfo));
+  array = malloc(iterations * sizeof(array[0]));
+
+  if (! s_silent)
+    printf("&array[0] = %p\n", array);
+
+  pthread_barrier_init(&b, 0, nthread);
+
+  for (i = 0; i < nthread; i++)
+  {
+    t[i].b = &b;
+    t[i].array = array;
+    t[i].iterations = iterations;
+    pthread_create(&t[i].tid, 0, (void*(*)(void*))threadfunc, &t[i]);
+  }
+
+  for (i = 0; i < nthread; i++)
+  {
+    pthread_join(t[i].tid, 0);
+  }
+
+  pthread_barrier_destroy(&b);
+
+  free(array);
+  free(t);
+}
+
+int main(int argc, char** argv)
+{
+  int nthread;
+  int iterations;
+
+  nthread    = (argc > 1) ? atoi(argv[1]) : 2;
+  iterations = (argc > 2) ? atoi(argv[2]) : 3;
+  s_silent   = (argc > 3) ? atoi(argv[3]) : 0;
+
+  barriers_and_races(nthread, iterations);
+
+  return 0;
+}
diff --git a/drd/tests/pth_barrier.stderr.exp b/drd/tests/pth_barrier.stderr.exp
new file mode 100644
index 0000000..a9dad78
--- /dev/null
+++ b/drd/tests/pth_barrier.stderr.exp
@@ -0,0 +1 @@
+ERROR SUMMARY: 1 errors from 1 contexts
diff --git a/drd/tests/pth_barrier.vgtest b/drd/tests/pth_barrier.vgtest
new file mode 100644
index 0000000..adc781d
--- /dev/null
+++ b/drd/tests/pth_barrier.vgtest
@@ -0,0 +1,4 @@
+prereq: test -e pth_barrier && ./supported_libpthread
+prog: pth_barrier
+args: 2 1 1
+stderr_filter: filter_error_summary
diff --git a/drd/tests/pth_barrier2.stderr.exp b/drd/tests/pth_barrier2.stderr.exp
new file mode 100644
index 0000000..bb25d52
--- /dev/null
+++ b/drd/tests/pth_barrier2.stderr.exp
@@ -0,0 +1 @@
+ERROR SUMMARY: 32 errors from 1 contexts
diff --git a/drd/tests/pth_barrier2.vgtest b/drd/tests/pth_barrier2.vgtest
new file mode 100644
index 0000000..1fe9408
--- /dev/null
+++ b/drd/tests/pth_barrier2.vgtest
@@ -0,0 +1,4 @@
+prereq: test -e pth_barrier && ./supported_libpthread
+prog: pth_barrier
+args: 2 32 1
+stderr_filter: filter_error_summary
diff --git a/drd/tests/pth_barrier3.stderr.exp b/drd/tests/pth_barrier3.stderr.exp
new file mode 100644
index 0000000..6c5b8a3
--- /dev/null
+++ b/drd/tests/pth_barrier3.stderr.exp
@@ -0,0 +1 @@
+ERROR SUMMARY: 31 errors from 1 contexts
diff --git a/drd/tests/pth_barrier3.vgtest b/drd/tests/pth_barrier3.vgtest
new file mode 100644
index 0000000..c17edb1
--- /dev/null
+++ b/drd/tests/pth_barrier3.vgtest
@@ -0,0 +1,4 @@
+prereq: test -e pth_barrier && ./supported_libpthread
+prog: pth_barrier
+args: 32 1 1
+stderr_filter: filter_error_summary
diff --git a/drd/tests/pth_barrier_race.c b/drd/tests/pth_barrier_race.c
new file mode 100644
index 0000000..2255a0e
--- /dev/null
+++ b/drd/tests/pth_barrier_race.c
@@ -0,0 +1,48 @@
+/*
+ * Test program that triggers a race between pthread_barrier_wait() and
+ * pthread_barrier_destroy(): proper synchronization is missing between
+ * the pthread_barrier_wait() and the pthread_barrier_destroy() calls. This
+ * test program is based on the example that was posted on February 5, 2009 by
+ * Christoph Bartoschek on the valgrind-users mailing list. Redistribution of
+ * the source code below is permitted under the GPLv2 license.
+ *
+ * See also http://article.gmane.org/gmane.comp.debugging.valgrind/8945/match=pthread_barrier_wait
+ */
+
+
+#define _GNU_SOURCE
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static pthread_barrier_t* barrier;
+
+
+static void* thread(void* arg)
+{
+  pthread_barrier_wait(barrier);
+  return NULL;
+}
+
+int main()
+{
+  pthread_t tid;
+
+  barrier = (pthread_barrier_t *) malloc(sizeof(*barrier));
+  pthread_barrier_init(barrier, NULL, 2);
+
+  pthread_create(&tid, NULL, thread, NULL);
+
+  pthread_barrier_wait(barrier);
+  /*
+   * The sleep() call below ensures that the pthread_barrier_destroy() call
+   * happens after the created thread has returned from pthread_barrier_wait().
+   */
+  sleep(1);
+  pthread_barrier_destroy(barrier);
+  free(barrier);
+
+  pthread_join(tid, NULL);
+  return 0;
+}
diff --git a/drd/tests/pth_barrier_race.stderr.exp b/drd/tests/pth_barrier_race.stderr.exp
new file mode 100644
index 0000000..15b69ba
--- /dev/null
+++ b/drd/tests/pth_barrier_race.stderr.exp
@@ -0,0 +1,14 @@
+
+Destruction of barrier not synchronized with barrier wait call: barrier 0x........
+   at 0x........: pthread_barrier_destroy (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_barrier_race.c:?)
+Conflicting wait call by thread 2:
+   at 0x........: pthread_barrier_wait (drd_pthread_intercepts.c:?)
+   by 0x........: thread (pth_barrier_race.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+barrier 0x........ was first observed at:
+   at 0x........: pthread_barrier_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_barrier_race.c:?)
+
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/pth_barrier_race.vgtest b/drd/tests/pth_barrier_race.vgtest
new file mode 100644
index 0000000..a08cdb5
--- /dev/null
+++ b/drd/tests/pth_barrier_race.vgtest
@@ -0,0 +1,3 @@
+prereq: test -e pth_barrier_race && ./supported_libpthread
+vgopts: --num-callers=3
+prog: pth_barrier_race
diff --git a/drd/tests/pth_barrier_reinit.c b/drd/tests/pth_barrier_reinit.c
new file mode 100644
index 0000000..fc87b19
--- /dev/null
+++ b/drd/tests/pth_barrier_reinit.c
@@ -0,0 +1,17 @@
+/** Trigger barrier reinitialization, which is not allowed by the POSIX
+ *  threads standard. See also http://www.opengroup.org/onlinepubs/000095399/functions/pthread_barrier_init.html.
+ */
+
+
+#define _GNU_SOURCE
+
+#include <pthread.h>
+
+
+int main(int argc, char** argv)
+{
+  pthread_barrier_t b;
+  pthread_barrier_init(&b, 0, 1);
+  pthread_barrier_init(&b, 0, 1);
+  return 0;
+}
diff --git a/drd/tests/pth_barrier_reinit.stderr.exp b/drd/tests/pth_barrier_reinit.stderr.exp
new file mode 100644
index 0000000..36dcd50
--- /dev/null
+++ b/drd/tests/pth_barrier_reinit.stderr.exp
@@ -0,0 +1,10 @@
+
+Barrier reinitialization: barrier 0x........
+   at 0x........: pthread_barrier_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_barrier_reinit.c:?)
+barrier 0x........ was first observed at:
+   at 0x........: pthread_barrier_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_barrier_reinit.c:?)
+
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/pth_barrier_reinit.vgtest b/drd/tests/pth_barrier_reinit.vgtest
new file mode 100644
index 0000000..a649c30
--- /dev/null
+++ b/drd/tests/pth_barrier_reinit.vgtest
@@ -0,0 +1,2 @@
+prereq: test -e pth_barrier_reinit && ./supported_libpthread
+prog: pth_barrier_reinit
diff --git a/drd/tests/pth_broadcast.c b/drd/tests/pth_broadcast.c
new file mode 100644
index 0000000..5276a34
--- /dev/null
+++ b/drd/tests/pth_broadcast.c
@@ -0,0 +1,184 @@
+/** Broadcast a (POSIX threads) signal to all running threads, where the
+ *  number of threads can be specified on the command line. This test program
+ *  is intended not only to test the correctness of drd but also to test
+ *  whether performance does not degrade too much when the number of threads
+ *  increases.
+ */
+
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+// Counting semaphore.
+
+struct csema
+{
+  pthread_mutex_t  m_mutex;
+  pthread_cond_t   m_cond;
+  int              m_count;
+};
+
+void csema_ctr(struct csema* p)
+{
+  memset(p, 0, sizeof(*p));
+  pthread_mutex_init(&p->m_mutex, 0);
+  pthread_cond_init(&p->m_cond, 0);
+}
+
+void csema_dtr(struct csema* p)
+{
+  pthread_cond_destroy(&p->m_cond);
+  pthread_mutex_destroy(&p->m_mutex);
+}
+
+void csema_p(struct csema* p, const int n)
+{
+  pthread_mutex_lock(&p->m_mutex);
+  while (p->m_count < n)
+    pthread_cond_wait(&p->m_cond, &p->m_mutex);
+  p->m_count -= n;
+  pthread_cond_signal(&p->m_cond);
+  pthread_mutex_unlock(&p->m_mutex);
+}
+
+void csema_v(struct csema* p)
+{
+  pthread_mutex_lock(&p->m_mutex);
+  p->m_count++;
+  pthread_cond_signal(&p->m_cond);
+  pthread_mutex_unlock(&p->m_mutex);
+}
+
+
+struct cthread
+{
+  pthread_t     m_thread;
+  int           m_threadnum;
+  struct csema* m_sema;
+};
+
+void cthread_ctr(struct cthread* p)
+{
+  p->m_thread = 0;
+  p->m_sema   = 0;
+}
+
+void cthread_dtr(struct cthread* p)
+{ }
+
+
+// Local variables.
+
+static int s_debug = 0;
+static int s_trace = 0;
+static int s_signal_count;
+static pthread_mutex_t s_mutex;
+static pthread_cond_t  s_cond;
+
+
+// Function definitions.
+
+static void thread_func(struct cthread* thread_info)
+{
+  int i;
+
+  pthread_mutex_lock(&s_mutex);
+
+  for (i = 0; i < s_signal_count; i++)
+  {
+    if (s_trace)
+    {
+      printf("thread %d [%d] (1)\n", thread_info->m_threadnum, i);
+    }
+    csema_v(thread_info->m_sema);
+
+    // Wait until the main thread signals us via pthread_cond_broadcast().
+    pthread_cond_wait(&s_cond, &s_mutex);
+    if (s_trace)
+    {
+      printf("thread %d [%d] (2)\n", thread_info->m_threadnum, i);
+    }
+  }
+
+  pthread_mutex_unlock(&s_mutex);
+}
+
+int main(int argc, char** argv)
+{
+  int optchar;
+  int thread_count;
+
+  while ((optchar = getopt(argc, argv, "d")) != EOF)
+  {
+    switch (optchar)
+    {
+    case 'd':
+      s_debug = 1;
+      break;
+    default:
+      assert(0);
+      break;
+    }
+  }
+
+  /* This test should complete in 15s or less. If the test does not complete */
+  /* within that time, abort the test via the signal SIGALRM.                */
+  alarm(100);
+
+  s_signal_count = argc > optind ? atoi(argv[optind]) : 10;
+  thread_count = argc > optind + 1 ? atoi(argv[optind + 1]) : 10;
+
+  if (s_debug)
+    printf("&s_cond = %p\n", &s_cond);
+
+  pthread_mutex_init(&s_mutex, 0);
+  pthread_cond_init(&s_cond, 0);
+  {
+    int i;
+    struct csema sema;
+    struct cthread* p;
+    struct cthread* thread_vec;
+
+    csema_ctr(&sema);
+    thread_vec = malloc(sizeof(struct cthread) * thread_count);
+    for (p = thread_vec; p != thread_vec + thread_count; p++)
+    {
+      cthread_ctr(p);
+      p->m_threadnum = p - thread_vec;
+      p->m_sema = &sema;
+      pthread_create(&p->m_thread, 0,
+                     (void*(*)(void*))thread_func, &*p);
+    }
+    for (i = 0; i < s_signal_count; i++)
+    {
+      if (s_trace)
+        printf("main [%d] (1)\n", i);
+      csema_p(&sema, thread_count);
+      if (s_trace)
+        printf("main [%d] (2)\n", i);
+      pthread_mutex_lock(&s_mutex);
+      pthread_cond_broadcast(&s_cond);
+      pthread_mutex_unlock(&s_mutex);
+      if (s_trace)
+        printf("main [%d] (3)\n", i);
+    }
+    for (i = 0; i < thread_count; i++)
+    {
+      pthread_join(thread_vec[i].m_thread, 0);
+      cthread_dtr(&thread_vec[i]);
+    }
+    free(thread_vec);
+    csema_dtr(&sema);
+  }
+  pthread_cond_destroy(&s_cond);
+  pthread_mutex_destroy(&s_mutex);
+
+  fprintf(stderr, "Done.\n");
+
+  return 0;
+}
diff --git a/drd/tests/pth_broadcast.stderr.exp b/drd/tests/pth_broadcast.stderr.exp
new file mode 100644
index 0000000..d16127f
--- /dev/null
+++ b/drd/tests/pth_broadcast.stderr.exp
@@ -0,0 +1,4 @@
+
+Done.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/pth_broadcast.vgtest b/drd/tests/pth_broadcast.vgtest
new file mode 100644
index 0000000..010e024
--- /dev/null
+++ b/drd/tests/pth_broadcast.vgtest
@@ -0,0 +1,2 @@
+prereq: ./supported_libpthread
+prog: pth_broadcast
diff --git a/drd/tests/pth_cancel_locked.c b/drd/tests/pth_cancel_locked.c
new file mode 100644
index 0000000..86c15b8
--- /dev/null
+++ b/drd/tests/pth_cancel_locked.c
@@ -0,0 +1,51 @@
+/** Cancel a thread that holds a lock on a mutex. */
+
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdio.h>
+
+
+pthread_cond_t  s_cond;
+pthread_mutex_t s_mutex1;
+pthread_mutex_t s_mutex2;
+
+
+static void* thread(void* arg)
+{
+  /* Lock s_mutex2. */
+  pthread_mutex_lock(&s_mutex2);
+  /* Inform the main thread that s_mutex2 has been locked, and wait for pthread_cancel(). */
+  pthread_mutex_lock(&s_mutex1);
+  pthread_cond_signal(&s_cond);
+  pthread_cond_wait(&s_cond, &s_mutex1);
+  return 0;
+}
+
+int main(int argc, char** argv)
+{
+  pthread_t tid;
+
+  /* Initialize synchronization objects. */
+  pthread_cond_init(&s_cond, 0);
+  pthread_mutex_init(&s_mutex1, 0);
+  pthread_mutex_init(&s_mutex2, 0);
+
+  /* Create thread. */
+  pthread_mutex_lock(&s_mutex1);
+  pthread_create(&tid, 0, &thread, 0);
+
+  /* Wait until the created thread has locked s_mutex2. */
+  pthread_cond_wait(&s_cond, &s_mutex1);
+  pthread_mutex_unlock(&s_mutex1);
+
+  /* Cancel the created thread. */
+  pthread_cancel(tid);
+
+  /* Join the created thread. */
+  pthread_join(tid, 0);
+
+  fprintf(stderr, "Test finished.\n");
+
+  return 0;
+}
diff --git a/drd/tests/pth_cancel_locked.stderr.exp b/drd/tests/pth_cancel_locked.stderr.exp
new file mode 100644
index 0000000..e00753e
--- /dev/null
+++ b/drd/tests/pth_cancel_locked.stderr.exp
@@ -0,0 +1,11 @@
+
+Mutex still locked at thread exit: mutex 0x........, recursion count 1, owner 2.
+   at 0x........: pthread_join (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_cancel_locked.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_cancel_locked.c:?)
+
+Test finished.
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/pth_cancel_locked.stderr.exp-darwin b/drd/tests/pth_cancel_locked.stderr.exp-darwin
new file mode 100644
index 0000000..00a2f8f
--- /dev/null
+++ b/drd/tests/pth_cancel_locked.stderr.exp-darwin
@@ -0,0 +1,18 @@
+
+Mutex still locked at thread exit: mutex 0x........, recursion count 1, owner 2.
+   at 0x........: pthread_join (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_cancel_locked.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_cancel_locked.c:?)
+
+Mutex still locked at thread exit: mutex 0x........, recursion count 1, owner 2.
+   at 0x........: pthread_join (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_cancel_locked.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_cancel_locked.c:?)
+
+Test finished.
+
+ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/pth_cancel_locked.vgtest b/drd/tests/pth_cancel_locked.vgtest
new file mode 100644
index 0000000..d27ddf1
--- /dev/null
+++ b/drd/tests/pth_cancel_locked.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes
+prog: pth_cancel_locked
diff --git a/drd/tests/pth_cleanup_handler.c b/drd/tests/pth_cleanup_handler.c
new file mode 100644
index 0000000..ada1750
--- /dev/null
+++ b/drd/tests/pth_cleanup_handler.c
@@ -0,0 +1,66 @@
+/*
+ * Test program for verifying whether pthread cleanup handlers are invoked
+ * correctly.
+ */
+
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+
+static pthread_mutex_t s_mutex;
+
+
+static void cleanup_handler(void* param)
+{
+  fprintf(stderr, "Cleanup handler has been called.\n");
+  pthread_mutex_unlock(&s_mutex);
+}
+
+static void* f(void *p)
+{
+  if (pthread_mutex_lock(&s_mutex) != 0)
+  {
+    fprintf(stderr, "pthread_mutex_lock()\n");
+    exit(1);
+  }
+
+  pthread_cleanup_push(cleanup_handler, NULL);
+  pthread_exit(0);
+  pthread_cleanup_pop(true);
+}
+
+
+int main()
+{
+  pthread_t pt1, pt2;
+
+  // Make sure the program exits in case a deadlock has been triggered.
+  alarm(2);
+
+  if (pthread_mutex_init(&s_mutex, NULL) != 0)
+  {
+    fprintf(stderr, "pthread_mutex_init()\n");
+    exit(1);
+  }
+  if (pthread_create(&pt1, NULL, f, NULL) != 0)
+  {
+    fprintf(stderr, "pthread_create()\n");
+    exit(1);
+  }
+  if (pthread_create(&pt2, NULL, f, NULL) != 0)
+  {
+    fprintf(stderr, "pthread_create()\n");
+    exit(1);
+  }
+
+  pthread_join(pt1, 0);
+  pthread_join(pt2, 0);
+
+  fprintf(stderr, "Test succeeded.\n");
+
+  return 0;
+}
diff --git a/drd/tests/pth_cleanup_handler.stderr.exp b/drd/tests/pth_cleanup_handler.stderr.exp
new file mode 100644
index 0000000..d218bb9
--- /dev/null
+++ b/drd/tests/pth_cleanup_handler.stderr.exp
@@ -0,0 +1,6 @@
+
+Cleanup handler has been called.
+Cleanup handler has been called.
+Test succeeded.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/pth_cleanup_handler.vgtest b/drd/tests/pth_cleanup_handler.vgtest
new file mode 100644
index 0000000..cd94e9e
--- /dev/null
+++ b/drd/tests/pth_cleanup_handler.vgtest
@@ -0,0 +1,3 @@
+prereq: test -e pth_cleanup_handler && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes
+prog: pth_cleanup_handler
diff --git a/drd/tests/pth_cond_race.c b/drd/tests/pth_cond_race.c
new file mode 100644
index 0000000..303a5d8
--- /dev/null
+++ b/drd/tests/pth_cond_race.c
@@ -0,0 +1,71 @@
+/* Unit test for drd that triggers a race on the use of a POSIX condition
+   variable. By Bart Van Assche.
+*/
+
+#include <assert.h>
+#include <stdio.h>      // printf()
+#include <pthread.h>
+#include <unistd.h>    // usleep()
+
+
+// Local functions declarations.
+
+static void* thread_func(void* thread_arg);
+
+
+// Local variables.
+
+static pthread_mutex_t s_mutex;
+static pthread_cond_t  s_cond;
+static int             s_use_mutex = 0;
+
+
+// Function definitions.
+
+int main(int argc, char** argv)
+{
+  int optchar;
+  pthread_t threadid;
+
+  while ((optchar = getopt(argc, argv, "m")) != EOF)
+  {
+    switch (optchar)
+    {
+    case 'm':
+      s_use_mutex = 1;
+      break;
+    default:
+      assert(0);
+    }
+  }
+
+  pthread_cond_init(&s_cond, 0);
+  pthread_mutex_init(&s_mutex, 0);
+  pthread_mutex_lock(&s_mutex);
+
+  pthread_create(&threadid, 0, thread_func, 0);
+
+  pthread_cond_wait(&s_cond, &s_mutex);
+  pthread_mutex_unlock(&s_mutex);
+
+  pthread_join(threadid, 0);
+
+  pthread_mutex_destroy(&s_mutex);
+  pthread_cond_destroy(&s_cond);
+
+  return 0;
+}
+
+static void* thread_func(void* thread_arg)
+{
+  // Wait until the main thread has entered pthread_cond_wait().
+  pthread_mutex_lock(&s_mutex);
+  pthread_mutex_unlock(&s_mutex);
+
+  // Signal the condition variable.
+  if (s_use_mutex) pthread_mutex_lock(&s_mutex);
+  pthread_cond_signal(&s_cond);
+  if (s_use_mutex) pthread_mutex_unlock(&s_mutex);
+
+  return 0;
+}
diff --git a/drd/tests/pth_cond_race.stderr.exp b/drd/tests/pth_cond_race.stderr.exp
new file mode 100644
index 0000000..4c73f5f
--- /dev/null
+++ b/drd/tests/pth_cond_race.stderr.exp
@@ -0,0 +1,15 @@
+
+Thread 2:
+Probably a race condition: condition variable 0x........ has been signaled but the associated mutex 0x........ is not locked by the signalling thread.
+   at 0x........: pthread_cond_signal (drd_pthread_intercepts.c:?)
+   by 0x........: thread_func (pth_cond_race.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+cond 0x........ was first observed at:
+   at 0x........: pthread_cond_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_cond_race.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_cond_race.c:?)
+
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/pth_cond_race.vgtest b/drd/tests/pth_cond_race.vgtest
new file mode 100644
index 0000000..201ec98
--- /dev/null
+++ b/drd/tests/pth_cond_race.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread
+vgopts: --num-callers=3
+prog: pth_cond_race
diff --git a/drd/tests/pth_cond_race2.stderr.exp b/drd/tests/pth_cond_race2.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/pth_cond_race2.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/pth_cond_race2.vgtest b/drd/tests/pth_cond_race2.vgtest
new file mode 100644
index 0000000..dec9dd1
--- /dev/null
+++ b/drd/tests/pth_cond_race2.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread
+prog: pth_cond_race
+args: -m
diff --git a/drd/tests/pth_cond_race3.stderr.exp b/drd/tests/pth_cond_race3.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/pth_cond_race3.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/pth_cond_race3.vgtest b/drd/tests/pth_cond_race3.vgtest
new file mode 100644
index 0000000..8e6b9cc
--- /dev/null
+++ b/drd/tests/pth_cond_race3.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread
+prog: pth_cond_race
+vgopts: --report-signal-unlocked=no
diff --git a/drd/tests/pth_create_chain.c b/drd/tests/pth_create_chain.c
new file mode 100644
index 0000000..2de7689
--- /dev/null
+++ b/drd/tests/pth_create_chain.c
@@ -0,0 +1,54 @@
+// Create threads in such a way that there is a realistic chance that the
+// parent thread finishes before the created thread finishes.
+
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <pthread.h>
+
+
+static pthread_t s_thread[1000];
+static int       s_arg[1000];
+
+static void* thread_func(void* p)
+{
+  int thread_count = *(int*)(p);
+  if (thread_count > 0)
+  {
+    thread_count--;
+    // std::cout << "create " << thread_count << std::endl;
+    s_arg[thread_count] = thread_count;
+    pthread_create(&s_thread[thread_count], 0, thread_func,
+                   &s_arg[thread_count]);
+#if 0
+    std::cout << "created " << thread_count << "(" << s_thread[thread_count]
+              << ")" << std::endl;
+#endif
+  }
+  return 0;
+}
+
+int main(int argc, char** argv)
+{
+  unsigned thread_count;
+  int i;
+
+  thread_count = argc > 1 ? atoi(argv[1]) : 50;
+  assert(thread_count <= sizeof(s_thread) / sizeof(s_thread[0]));
+  assert(thread_count >= 1);
+  thread_count--;
+  // std::cout << "create " << thread_count << std::endl;
+  pthread_create(&s_thread[thread_count], 0, thread_func,
+                 &thread_count);
+#if 0
+  std::cout << "created " << thread_count << "(" << s_thread[thread_count]
+            << ")" << std::endl;
+#endif
+  for (i = thread_count; i >= 0; i--)
+  {
+    // std::cout << "join " << i << "(" << s_thread[i] << ")" << std::endl;
+    pthread_join(s_thread[i], 0);
+  }
+  return 0;
+}
diff --git a/drd/tests/pth_create_chain.stderr.exp b/drd/tests/pth_create_chain.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/pth_create_chain.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/pth_create_chain.vgtest b/drd/tests/pth_create_chain.vgtest
new file mode 100644
index 0000000..b8c2422
--- /dev/null
+++ b/drd/tests/pth_create_chain.vgtest
@@ -0,0 +1,2 @@
+prereq: ./supported_libpthread && [ `uname -m` != ppc ] && [ `uname -m` != ppc64 ]
+prog: pth_create_chain 100
diff --git a/drd/tests/pth_create_glibc_2_0.c b/drd/tests/pth_create_glibc_2_0.c
new file mode 100644
index 0000000..a8dcc8a
--- /dev/null
+++ b/drd/tests/pth_create_glibc_2_0.c
@@ -0,0 +1,39 @@
+/*
+ * Test program that invokes pthread_create@GLIBC_2.0().
+ *
+ * Note: pthread_create@GLIBC_2.0() is only available in 32-bit glibc versions,
+ * not in 64-bit versions.
+ */
+
+
+#include <pthread.h>
+#include <stdio.h>
+
+
+extern int pthread_create_glibc_2_0(pthread_t*, const pthread_attr_t*,
+                                    void *(*)(void*), void*);
+
+__asm__(".symver pthread_create_glibc_2_0, pthread_create@GLIBC_2.0");
+
+
+static void* thread_func(void *arg)
+{
+  fprintf(stderr, "The thread.\n");
+  return 0;
+}
+
+int main(int argc, char** argv)
+{
+  int result;
+  pthread_t thr;
+
+  result = (*pthread_create_glibc_2_0)(&thr, 0, thread_func, 0);
+  if (result != 0)
+  {
+    fprintf(stderr, "pthread_create() failed.\n");
+    return 1;
+  }
+  pthread_join(thr, 0);
+  fprintf(stderr, "Finished.\n");
+  return 0;
+}
diff --git a/drd/tests/pth_create_glibc_2_0.stderr.exp b/drd/tests/pth_create_glibc_2_0.stderr.exp
new file mode 100644
index 0000000..e5bd5a8
--- /dev/null
+++ b/drd/tests/pth_create_glibc_2_0.stderr.exp
@@ -0,0 +1,5 @@
+
+The thread.
+Finished.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/pth_create_glibc_2_0.vgtest b/drd/tests/pth_create_glibc_2_0.vgtest
new file mode 100644
index 0000000..4cdf46b
--- /dev/null
+++ b/drd/tests/pth_create_glibc_2_0.vgtest
@@ -0,0 +1,3 @@
+prereq: test -e pth_create_glibc_2_0 && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes
+prog: pth_create_glibc_2_0
diff --git a/drd/tests/pth_detached.c b/drd/tests/pth_detached.c
new file mode 100644
index 0000000..696cd4b
--- /dev/null
+++ b/drd/tests/pth_detached.c
@@ -0,0 +1,97 @@
+/* Test whether detached threads are handled properly. */
+
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static int s_finished_count;
+static pthread_mutex_t s_mutex;
+
+
+static void increment_finished_count()
+{
+  pthread_mutex_lock(&s_mutex);
+  s_finished_count++;
+  pthread_mutex_unlock(&s_mutex);
+}
+
+static int get_finished_count()
+{
+  int result;
+  pthread_mutex_lock(&s_mutex);
+  result = s_finished_count;
+  pthread_mutex_unlock(&s_mutex);
+  return result;
+}
+
+static void* thread_func1(void* arg)
+{
+  write(STDOUT_FILENO, ".", 1);
+  increment_finished_count();
+  return 0;
+}
+
+static void* thread_func2(void* arg)
+{
+  pthread_detach(pthread_self());
+  write(STDOUT_FILENO, ".", 1);
+  increment_finished_count();
+  return 0;
+}
+
+int main(int argc, char** argv)
+{
+  const int count1 = argc > 1 ? atoi(argv[1]) : 100;
+  const int count2 = argc > 2 ? atoi(argv[2]) : 100;
+  int thread_arg[count1 > count2 ? count1 : count2];
+  int i;
+  int detachstate;
+  pthread_attr_t attr;
+
+  for (i = 0; i < count1 || i < count2; i++)
+    thread_arg[i] = i;
+
+  pthread_mutex_init(&s_mutex, 0);
+
+  pthread_attr_init(&attr);
+  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+  assert(pthread_attr_getdetachstate(&attr, &detachstate) == 0);
+  assert(detachstate == PTHREAD_CREATE_DETACHED);
+  pthread_attr_setstacksize(&attr, 16384);
+  // Create count1 detached threads by setting the "detached" property via
+  // thread attributes.
+  for (i = 0; i < count1; i++)
+  {
+    pthread_t thread;
+    pthread_create(&thread, &attr, thread_func1, &thread_arg[i]);
+  }
+  // Create count2 detached threads by letting the threads detach themselves.
+  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+  assert(pthread_attr_getdetachstate(&attr, &detachstate) == 0);
+  assert(detachstate == PTHREAD_CREATE_JOINABLE);
+  for (i = 0; i < count2; i++)
+  {
+    pthread_t thread;
+    pthread_create(&thread, &attr, thread_func2, &thread_arg[i]);
+  }
+  pthread_attr_destroy(&attr);
+
+  // Wait until all detached threads have written their output to stdout.
+  while (get_finished_count() < count1 + count2)
+  {
+    struct timespec delay = { 0, 1 * 1000 * 1000 };
+    nanosleep(&delay, 0);
+  }
+
+  write(STDOUT_FILENO, "\n", 1);
+
+  pthread_mutex_destroy(&s_mutex);
+
+  sleep(1);
+
+  return 0;
+}
diff --git a/drd/tests/pth_detached.stderr.exp b/drd/tests/pth_detached.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/pth_detached.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/pth_detached.stdout.exp b/drd/tests/pth_detached.stdout.exp
new file mode 100644
index 0000000..f3229c5
--- /dev/null
+++ b/drd/tests/pth_detached.stdout.exp
@@ -0,0 +1 @@
+..
diff --git a/drd/tests/pth_detached.vgtest b/drd/tests/pth_detached.vgtest
new file mode 100644
index 0000000..f78b9cc
--- /dev/null
+++ b/drd/tests/pth_detached.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread
+prog: pth_detached
+args: 1 1
diff --git a/drd/tests/pth_detached2.stderr.exp b/drd/tests/pth_detached2.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/pth_detached2.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/pth_detached2.stdout.exp b/drd/tests/pth_detached2.stdout.exp
new file mode 100644
index 0000000..01bfb02
--- /dev/null
+++ b/drd/tests/pth_detached2.stdout.exp
@@ -0,0 +1 @@
+....................
diff --git a/drd/tests/pth_detached2.vgtest b/drd/tests/pth_detached2.vgtest
new file mode 100644
index 0000000..bcd950a
--- /dev/null
+++ b/drd/tests/pth_detached2.vgtest
@@ -0,0 +1,4 @@
+prereq: ./supported_libpthread
+vgopts: --read-var-info=yes
+prog: pth_detached
+args: 10 10
diff --git a/drd/tests/pth_detached_sem.c b/drd/tests/pth_detached_sem.c
new file mode 100644
index 0000000..c91be67
--- /dev/null
+++ b/drd/tests/pth_detached_sem.c
@@ -0,0 +1,89 @@
+/**
+ * Test whether detached threads are handled properly.
+ * This test program is based on pth_detached.c, with the difference that
+ * in this test program the main thread uses a counting semaphore instead
+ * of a counter protected by a mutex to wait until all detached threads
+ * finished.
+ */
+
+
+#include <assert.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static sem_t s_sem;
+
+
+static void increment_finished_count()
+{
+  sem_post(&s_sem);
+}
+
+static void* thread_func1(void* arg)
+{
+  write(STDOUT_FILENO, ".", 1);
+  increment_finished_count();
+  return 0;
+}
+
+static void* thread_func2(void* arg)
+{
+  pthread_detach(pthread_self());
+  write(STDOUT_FILENO, ".", 1);
+  increment_finished_count();
+  return 0;
+}
+
+int main(int argc, char** argv)
+{
+  const int count1 = argc > 1 ? atoi(argv[1]) : 100;
+  const int count2 = argc > 2 ? atoi(argv[2]) : 100;
+  int thread_arg[count1 > count2 ? count1 : count2];
+  int i;
+  int detachstate;
+  pthread_attr_t attr;
+
+  for (i = 0; i < count1 || i < count2; i++)
+    thread_arg[i] = i;
+
+  sem_init(&s_sem, 0, 0);
+
+  pthread_attr_init(&attr);
+  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+  assert(pthread_attr_getdetachstate(&attr, &detachstate) == 0);
+  assert(detachstate == PTHREAD_CREATE_DETACHED);
+  pthread_attr_setstacksize(&attr, 16384);
+  // Create count1 detached threads by setting the "detached" property via
+  // thread attributes.
+  for (i = 0; i < count1; i++)
+  {
+    pthread_t thread;
+    pthread_create(&thread, &attr, thread_func1, &thread_arg[i]);
+  }
+  // Create count2 detached threads by letting the threads detach themselves.
+  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+  assert(pthread_attr_getdetachstate(&attr, &detachstate) == 0);
+  assert(detachstate == PTHREAD_CREATE_JOINABLE);
+  for (i = 0; i < count2; i++)
+  {
+    pthread_t thread;
+    pthread_create(&thread, &attr, thread_func2, &thread_arg[i]);
+  }
+  pthread_attr_destroy(&attr);
+
+  // Wait until all detached threads have written their output to stdout.
+  for (i = 0; i < count1 + count2; i++)
+  {
+    sem_wait(&s_sem);
+  }
+
+  write(STDOUT_FILENO, "\n", 1);
+
+  sem_destroy(&s_sem);
+
+  return 0;
+}
diff --git a/drd/tests/pth_detached_sem.stderr.exp b/drd/tests/pth_detached_sem.stderr.exp
new file mode 100644
index 0000000..e1e0bbb
--- /dev/null
+++ b/drd/tests/pth_detached_sem.stderr.exp
@@ -0,0 +1 @@
+ERROR SUMMARY: 0 errors from 0 contexts
diff --git a/drd/tests/pth_detached_sem.stdout.exp b/drd/tests/pth_detached_sem.stdout.exp
new file mode 100644
index 0000000..01bfb02
--- /dev/null
+++ b/drd/tests/pth_detached_sem.stdout.exp
@@ -0,0 +1 @@
+....................
diff --git a/drd/tests/pth_detached_sem.vgtest b/drd/tests/pth_detached_sem.vgtest
new file mode 100644
index 0000000..8d82ad1
--- /dev/null
+++ b/drd/tests/pth_detached_sem.vgtest
@@ -0,0 +1,4 @@
+prereq: ./supported_libpthread && ./supported_sem_init
+prog: pth_detached_sem
+args: 10 10
+stderr_filter: filter_error_summary
diff --git a/drd/tests/pth_inconsistent_cond_wait.c b/drd/tests/pth_inconsistent_cond_wait.c
new file mode 100644
index 0000000..618b540
--- /dev/null
+++ b/drd/tests/pth_inconsistent_cond_wait.c
@@ -0,0 +1,135 @@
+/** Trigger two kinds of errors: once that condition variable s_cond is
+ *  associated with two different mutexes (s_mutex1 and s_mutex2), and two
+ *  times that pthread_cond_signal() is called without that the mutex
+ *  associated with the condition variable is locked.
+ */
+
+
+#include <errno.h>     // ETIMEDOUT
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdlib.h>    // malloc()
+#include <string.h>    // memset()
+#include <sys/time.h>  // gettimeofday()
+#include <time.h>      // struct timespec
+#include <fcntl.h>     // O_CREAT
+#include <unistd.h>
+#include "../../config.h"
+
+
+#define PTH_CALL(expr)                                  \
+  do                                                    \
+  {                                                     \
+    int err = (expr);                                   \
+    if (! s_quiet && err)				\
+    {                                                   \
+      fprintf(stderr,                                   \
+              "%s:%d %s returned error code %d (%s)\n", \
+              __FILE__,                                 \
+              __LINE__,                                 \
+              #expr,                                    \
+              err,                                      \
+              strerror(err));                           \
+    }                                                   \
+  } while (0)
+
+
+static pthread_cond_t  s_cond;
+static pthread_mutex_t s_mutex1;
+static pthread_mutex_t s_mutex2;
+static sem_t*          s_sem;
+static int             s_quiet;
+
+
+static sem_t* create_semaphore(const char* const name)
+{
+#ifdef __APPLE__
+  sem_t* p = sem_open(name, O_CREAT, 0600, 0);
+  return p;
+#else
+  sem_t* p = malloc(sizeof(*p));
+  if (p)
+    sem_init(p, 0, 0);
+  return p;
+#endif
+}
+
+static void destroy_semaphore(const char* const name, sem_t* p)
+{
+#ifdef __APPLE__
+  sem_close(p);
+  sem_unlink(name);
+#else
+  sem_destroy(p);
+  free(p);
+#endif
+}
+
+static void* thread_func(void* mutex)
+{
+  struct timeval now;
+  struct timespec deadline;
+
+  PTH_CALL(pthread_mutex_lock(mutex));
+  sem_post(s_sem);
+  gettimeofday(&now, 0);
+  memset(&deadline, 0, sizeof(deadline));
+  deadline.tv_sec  = now.tv_sec + 2;
+  deadline.tv_nsec = now.tv_usec * 1000;
+  PTH_CALL(pthread_cond_timedwait(&s_cond, mutex, &deadline));
+  PTH_CALL(pthread_mutex_unlock(mutex));
+  return 0;
+}
+
+int main(int argc, char** argv)
+{
+  char semaphore_name[32];
+  int optchar;
+  pthread_t tid1;
+  pthread_t tid2;
+
+  while ((optchar = getopt(argc, argv, "q")) != EOF)
+  {
+    switch (optchar)
+    {
+    case 'q': s_quiet = 1; break;
+    default:
+      fprintf(stderr, "Error: unknown option '%c'.\n", optchar);
+      return 1;
+    }
+  }
+
+  /* Initialize synchronization objects. */
+  snprintf(semaphore_name, sizeof(semaphore_name), "semaphore-%d", getpid());
+  s_sem = create_semaphore(semaphore_name);
+  PTH_CALL(pthread_cond_init(&s_cond, 0));
+  PTH_CALL(pthread_mutex_init(&s_mutex1, 0));
+  PTH_CALL(pthread_mutex_init(&s_mutex2, 0));
+
+  /* Create two threads. */
+  PTH_CALL(pthread_create(&tid1, 0, &thread_func, &s_mutex1));
+  PTH_CALL(pthread_create(&tid2, 0, &thread_func, &s_mutex2));
+
+  /* Wait until both threads have called sem_post(). */
+  sem_wait(s_sem);
+  sem_wait(s_sem);
+  destroy_semaphore(semaphore_name, s_sem);
+  s_sem = 0;
+
+  /* Wait until both threads are waiting inside pthread_cond_wait(). */
+  PTH_CALL(pthread_mutex_lock(&s_mutex1));
+  PTH_CALL(pthread_mutex_lock(&s_mutex2));
+  PTH_CALL(pthread_mutex_unlock(&s_mutex2));
+  PTH_CALL(pthread_mutex_unlock(&s_mutex1));
+
+  /* Signal s_cond twice. */
+  PTH_CALL(pthread_cond_signal(&s_cond));
+  PTH_CALL(pthread_cond_signal(&s_cond));
+
+  /* Join both threads. */
+  PTH_CALL(pthread_join(tid1, 0));
+  PTH_CALL(pthread_join(tid2, 0));
+
+  return 0;
+}
diff --git a/drd/tests/pth_inconsistent_cond_wait.stderr.exp1 b/drd/tests/pth_inconsistent_cond_wait.stderr.exp1
new file mode 100644
index 0000000..ef294c3
--- /dev/null
+++ b/drd/tests/pth_inconsistent_cond_wait.stderr.exp1
@@ -0,0 +1,39 @@
+
+Thread 3:
+Inconsistent association of condition variable and mutex: condition variable 0x........, mutexes 0x........ and 0x........
+   at 0x........: pthread_cond_timedwait (drd_pthread_intercepts.c:?)
+   by 0x........: thread_func (pth_inconsistent_cond_wait.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+cond 0x........ was first observed at:
+   at 0x........: pthread_cond_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_inconsistent_cond_wait.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_inconsistent_cond_wait.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_inconsistent_cond_wait.c:?)
+
+Thread 1:
+Probably a race condition: condition variable 0x........ has been signaled but the associated mutex 0x........ is not locked by the signalling thread.
+   at 0x........: pthread_cond_signal (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_inconsistent_cond_wait.c:?)
+cond 0x........ was first observed at:
+   at 0x........: pthread_cond_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_inconsistent_cond_wait.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_inconsistent_cond_wait.c:?)
+
+Probably a race condition: condition variable 0x........ has been signaled but the associated mutex 0x........ is not locked by the signalling thread.
+   at 0x........: pthread_cond_signal (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_inconsistent_cond_wait.c:?)
+cond 0x........ was first observed at:
+   at 0x........: pthread_cond_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_inconsistent_cond_wait.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_inconsistent_cond_wait.c:?)
+
+
+ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/pth_inconsistent_cond_wait.stderr.exp2 b/drd/tests/pth_inconsistent_cond_wait.stderr.exp2
new file mode 100644
index 0000000..ad24a27
--- /dev/null
+++ b/drd/tests/pth_inconsistent_cond_wait.stderr.exp2
@@ -0,0 +1,39 @@
+
+Thread 2:
+Inconsistent association of condition variable and mutex: condition variable 0x........, mutexes 0x........ and 0x........
+   at 0x........: pthread_cond_timedwait (drd_pthread_intercepts.c:?)
+   by 0x........: thread_func (pth_inconsistent_cond_wait.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+cond 0x........ was first observed at:
+   at 0x........: pthread_cond_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_inconsistent_cond_wait.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_inconsistent_cond_wait.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_inconsistent_cond_wait.c:?)
+
+Thread 1:
+Probably a race condition: condition variable 0x........ has been signaled but the associated mutex 0x........ is not locked by the signalling thread.
+   at 0x........: pthread_cond_signal (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_inconsistent_cond_wait.c:?)
+cond 0x........ was first observed at:
+   at 0x........: pthread_cond_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_inconsistent_cond_wait.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_inconsistent_cond_wait.c:?)
+
+Probably a race condition: condition variable 0x........ has been signaled but the associated mutex 0x........ is not locked by the signalling thread.
+   at 0x........: pthread_cond_signal (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_inconsistent_cond_wait.c:?)
+cond 0x........ was first observed at:
+   at 0x........: pthread_cond_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_inconsistent_cond_wait.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_inconsistent_cond_wait.c:?)
+
+
+ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/pth_inconsistent_cond_wait.vgtest b/drd/tests/pth_inconsistent_cond_wait.vgtest
new file mode 100644
index 0000000..0c5a82c
--- /dev/null
+++ b/drd/tests/pth_inconsistent_cond_wait.vgtest
@@ -0,0 +1,4 @@
+prereq: ./supported_libpthread
+vgopts: --num-callers=3
+prog: pth_inconsistent_cond_wait
+args: -q
diff --git a/drd/tests/pth_mutex_reinit.c b/drd/tests/pth_mutex_reinit.c
new file mode 100644
index 0000000..1c72e81
--- /dev/null
+++ b/drd/tests/pth_mutex_reinit.c
@@ -0,0 +1,36 @@
+/* Test program that triggers mutex reinitialization. */
+
+
+#define _GNU_SOURCE
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+int main(int argc, char** argv)
+{
+  pthread_mutex_t m;
+  pthread_mutexattr_t attr;
+
+  pthread_mutexattr_init(&attr);
+  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
+  pthread_mutex_init(&m, &attr);
+  pthread_mutexattr_destroy(&attr);
+  pthread_mutex_lock(&m);
+  pthread_mutex_unlock(&m);
+
+  pthread_mutexattr_init(&attr);
+  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+  pthread_mutex_init(&m, &attr);
+  pthread_mutexattr_destroy(&attr);
+  pthread_mutex_lock(&m);
+  pthread_mutex_unlock(&m);
+
+  pthread_mutex_destroy(&m);
+
+  fprintf(stderr, "Done.\n");
+
+  return 0;
+}
diff --git a/drd/tests/pth_mutex_reinit.stderr.exp b/drd/tests/pth_mutex_reinit.stderr.exp
new file mode 100644
index 0000000..9307666
--- /dev/null
+++ b/drd/tests/pth_mutex_reinit.stderr.exp
@@ -0,0 +1,11 @@
+
+Mutex reinitialization: mutex 0x........, recursion count 0, owner 1.
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_mutex_reinit.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_mutex_reinit.c:?)
+
+Done.
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/pth_mutex_reinit.vgtest b/drd/tests/pth_mutex_reinit.vgtest
new file mode 100644
index 0000000..369301d
--- /dev/null
+++ b/drd/tests/pth_mutex_reinit.vgtest
@@ -0,0 +1,3 @@
+prereq: test -e pth_mutex_reinit && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes
+prog: pth_mutex_reinit
diff --git a/drd/tests/pth_once.stderr.exp b/drd/tests/pth_once.stderr.exp
new file mode 100644
index 0000000..e1e0bbb
--- /dev/null
+++ b/drd/tests/pth_once.stderr.exp
@@ -0,0 +1 @@
+ERROR SUMMARY: 0 errors from 0 contexts
diff --git a/drd/tests/pth_once.vgtest b/drd/tests/pth_once.vgtest
new file mode 100644
index 0000000..338b5fc
--- /dev/null
+++ b/drd/tests/pth_once.vgtest
@@ -0,0 +1,5 @@
+prereq: test -e tsan_unittest && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes
+prog: tsan_unittest
+args: 106
+stderr_filter: filter_error_summary
diff --git a/drd/tests/pth_process_shared_mutex.c b/drd/tests/pth_process_shared_mutex.c
new file mode 100644
index 0000000..1344761
--- /dev/null
+++ b/drd/tests/pth_process_shared_mutex.c
@@ -0,0 +1,30 @@
+/*
+ * Test program that locks and unlocks a process-shared mutex.
+ * See also https://bugs.kde.org/show_bug.cgi?id=187048.
+ */
+
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <pthread.h>
+
+
+int main()
+{
+  pthread_mutex_t mutex;
+  pthread_mutexattr_t attr;
+
+  pthread_mutexattr_init(&attr);
+  pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
+  pthread_mutex_init(&mutex, &attr);
+  pthread_mutexattr_destroy(&attr);
+
+  pthread_mutex_lock(&mutex);
+  pthread_mutex_unlock(&mutex);
+  pthread_mutex_destroy(&mutex);
+
+  fprintf(stderr, "Finished.\n");
+
+  return 0;
+}
diff --git a/drd/tests/pth_process_shared_mutex.stderr.exp b/drd/tests/pth_process_shared_mutex.stderr.exp
new file mode 100644
index 0000000..a7089bb
--- /dev/null
+++ b/drd/tests/pth_process_shared_mutex.stderr.exp
@@ -0,0 +1,4 @@
+
+Finished.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/pth_process_shared_mutex.vgtest b/drd/tests/pth_process_shared_mutex.vgtest
new file mode 100644
index 0000000..4d5089c
--- /dev/null
+++ b/drd/tests/pth_process_shared_mutex.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread
+prog: pth_process_shared_mutex
+vgopts: --read-var-info=yes --check-stack-var=yes
diff --git a/drd/tests/pth_spinlock.c b/drd/tests/pth_spinlock.c
new file mode 100644
index 0000000..0f56a0b
--- /dev/null
+++ b/drd/tests/pth_spinlock.c
@@ -0,0 +1,57 @@
+/** pthread_spinloc_t test. */
+
+
+/* Make sure pthread_spinlock_t is available when compiling with older glibc
+ * versions (2.3 or before).
+ */
+#define _GNU_SOURCE
+
+#include <pthread.h>
+#include <stdio.h>   /* fprintf() */
+#include <stdlib.h>  /* atoi() */
+
+
+static pthread_barrier_t  s_barrier;
+static pthread_spinlock_t s_spinlock;
+static int s_iterations;
+static int s_counter;
+
+
+static void* thread_func(void* arg)
+{
+  int i;
+
+  pthread_barrier_wait(&s_barrier);
+  for (i = s_iterations; i > 0; i--)
+  {
+    pthread_spin_lock(&s_spinlock);
+    s_counter++;
+    pthread_spin_unlock(&s_spinlock);
+  }
+  return 0;
+}
+
+int main(int argc, char** argv)
+{
+  int i;
+  const int n_threads = 10;
+  pthread_t tid[n_threads];
+
+  s_iterations = argc > 1 ? atoi(argv[1]) : 1000;
+
+  fprintf(stderr, "Start of test.\n");
+  pthread_barrier_init(&s_barrier, 0, n_threads);
+  pthread_spin_init(&s_spinlock, 0);
+  for (i = 0; i < n_threads; i++)
+    pthread_create(&tid[i], 0, thread_func, 0);
+  for (i = 0; i < n_threads; i++)
+    pthread_join(tid[i], 0);
+  pthread_spin_destroy(&s_spinlock);
+  pthread_barrier_destroy(&s_barrier);
+  if (s_counter == n_threads * s_iterations)
+    fprintf(stderr, "Test successful.\n");
+  else
+    fprintf(stderr, "Test failed: counter = %d, should be %d\n",
+            s_counter, n_threads * s_iterations);
+  return 0;
+}
diff --git a/drd/tests/pth_spinlock.stderr.exp b/drd/tests/pth_spinlock.stderr.exp
new file mode 100644
index 0000000..21dba22
--- /dev/null
+++ b/drd/tests/pth_spinlock.stderr.exp
@@ -0,0 +1,5 @@
+
+Start of test.
+Test successful.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/pth_spinlock.vgtest b/drd/tests/pth_spinlock.vgtest
new file mode 100644
index 0000000..48aa40d
--- /dev/null
+++ b/drd/tests/pth_spinlock.vgtest
@@ -0,0 +1,3 @@
+prereq: test -e pth_spinlock && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes
+prog: pth_spinlock
diff --git a/drd/tests/pth_uninitialized_cond.c b/drd/tests/pth_uninitialized_cond.c
new file mode 100644
index 0000000..6acfbc7
--- /dev/null
+++ b/drd/tests/pth_uninitialized_cond.c
@@ -0,0 +1,28 @@
+/* Test program to verify whether DRD only complains about uninitialized
+ * condition variables for dynamically allocated memory.
+ */
+
+
+#include <pthread.h>
+#include <stdio.h>
+
+
+static pthread_cond_t s_cond1 = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t s_cond2 = PTHREAD_COND_INITIALIZER;
+
+
+int main(int argc, char** argv)
+{
+    fprintf(stderr, "Statically initialized condition variable.\n");
+
+    pthread_cond_signal(&s_cond1);
+
+    fprintf(stderr, "Uninitialized condition variable.\n");
+
+    *((char*)&s_cond2 + sizeof(s_cond2) - 1) ^= 1;
+    pthread_cond_signal(&s_cond2);
+
+    fprintf(stderr, "Done.\n");
+
+    return 0;
+}
diff --git a/drd/tests/pth_uninitialized_cond.stderr.exp b/drd/tests/pth_uninitialized_cond.stderr.exp
new file mode 100644
index 0000000..a693944
--- /dev/null
+++ b/drd/tests/pth_uninitialized_cond.stderr.exp
@@ -0,0 +1,10 @@
+
+Statically initialized condition variable.
+Uninitialized condition variable.
+condition variable has not been initialized: cond 0x........
+   at 0x........: pthread_cond_signal (drd_pthread_intercepts.c:?)
+   by 0x........: main (pth_uninitialized_cond.c:?)
+
+Done.
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/pth_uninitialized_cond.vgtest b/drd/tests/pth_uninitialized_cond.vgtest
new file mode 100644
index 0000000..fe03139
--- /dev/null
+++ b/drd/tests/pth_uninitialized_cond.vgtest
@@ -0,0 +1,3 @@
+prereq: test -e pth_uninitialized_cond && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes
+prog: pth_uninitialized_cond
diff --git a/drd/tests/qt4_atomic.cpp b/drd/tests/qt4_atomic.cpp
new file mode 100644
index 0000000..b3b84f6
--- /dev/null
+++ b/drd/tests/qt4_atomic.cpp
@@ -0,0 +1,65 @@
+/// Test program that uses the QAtomicInt class.
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include "config.h"
+#include <QAtomicInt>     // class QAtomicInt
+#include <cassert>
+#include <cstdio>         // fprintf()
+#include <cstdlib>        // atoi()
+#include <new>
+#include <pthread.h>      // pthread_barrier_t
+#include <vector>
+
+
+static pthread_barrier_t s_barrier;
+static QAtomicInt* s_pAtomicInt;
+
+
+void* thread_func(void* pArg)
+{
+  const int iArg = *reinterpret_cast<int*>(pArg);
+
+  pthread_barrier_wait(&s_barrier);
+
+  while (! s_pAtomicInt->testAndSetOrdered(iArg, iArg + 1))
+    ;
+
+  return NULL;
+}
+
+int main(int argc, char** argv)
+{
+  int i;
+  const int n_threads = 10;
+  std::vector<int>       thread_arg(n_threads);
+  std::vector<pthread_t> tid(n_threads);
+
+  fprintf(stderr, "Start of test.\n");
+
+  pthread_barrier_init(&s_barrier, 0, n_threads);
+  s_pAtomicInt = new QAtomicInt();
+  for (i = 0; i < n_threads; i++)
+  {
+    thread_arg[i] = i;
+    pthread_create(&tid[i], 0, thread_func, &thread_arg[i]);
+  }
+  for (i = 0; i < n_threads; i++)
+  {
+    pthread_join(tid[i], NULL);
+  }
+  pthread_barrier_destroy(&s_barrier);
+
+  if (*s_pAtomicInt == n_threads)
+    fprintf(stderr, "Test successful.\n");
+  else
+    fprintf(stderr, "Test failed: counter = %d, should be %d\n",
+            static_cast<int>(*s_pAtomicInt), n_threads);
+
+  delete s_pAtomicInt;
+  s_pAtomicInt = 0;
+
+  return 0;
+}
diff --git a/drd/tests/qt4_atomic.stderr.exp b/drd/tests/qt4_atomic.stderr.exp
new file mode 100644
index 0000000..21dba22
--- /dev/null
+++ b/drd/tests/qt4_atomic.stderr.exp
@@ -0,0 +1,5 @@
+
+Start of test.
+Test successful.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/qt4_atomic.vgtest b/drd/tests/qt4_atomic.vgtest
new file mode 100644
index 0000000..a35435a
--- /dev/null
+++ b/drd/tests/qt4_atomic.vgtest
@@ -0,0 +1,3 @@
+prereq: test -e qt4_atomic
+vgopts: --check-stack-var=yes
+prog: qt4_atomic
diff --git a/drd/tests/qt4_mutex.cpp b/drd/tests/qt4_mutex.cpp
new file mode 100644
index 0000000..c20b163
--- /dev/null
+++ b/drd/tests/qt4_mutex.cpp
@@ -0,0 +1,92 @@
+/// Qt4 mutex test.
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include "config.h"
+#include <QMutex>         // class QMutex
+#include <QThread>        // class QThread
+#include <cassert>
+#include <cstdio>         // fprintf()
+#include <cstdlib>        // atoi()
+#include <new>
+#include <pthread.h>      // pthread_barrier_t
+#include <vector>
+
+
+static pthread_barrier_t s_barrier;
+static QMutex* s_pMutex;
+static int s_iterations;
+static int s_counter;
+
+
+class IncThread: public QThread
+{
+  virtual void run();
+};
+
+void IncThread::run()
+{
+  int i;
+
+  pthread_barrier_wait(&s_barrier);
+  for (i = s_iterations; i > 0; i--)
+  {
+    s_pMutex->lock();
+    s_counter++;
+    s_pMutex->unlock();
+  }
+}
+
+int main(int argc, char** argv)
+{
+  int i;
+  const int n_threads = 10;
+  std::vector<QThread*> tid(n_threads);
+
+  s_iterations = argc > 1 ? atoi(argv[1]) : 1000;
+
+  fprintf(stderr, "Start of test.\n");
+
+  {
+    // Stack-allocated mutex.
+    QMutex M(QMutex::Recursive);
+    M.lock();
+    assert(M.tryLock());
+    M.unlock();
+    M.unlock();
+  }
+#if defined(HAVE_QTCORE_QMUTEX_TRYLOCK_INT)
+  {
+    QMutex M(QMutex::NonRecursive);
+    assert(M.tryLock(1));
+    assert(! M.tryLock(1));
+    M.unlock();
+  }
+#endif
+
+  pthread_barrier_init(&s_barrier, 0, n_threads);
+  s_pMutex = new QMutex();
+  for (i = 0; i < n_threads; i++)
+  {
+    tid[i] = new IncThread;
+    tid[i]->start();
+  }
+  for (i = 0; i < n_threads; i++)
+  {
+    tid[i]->wait();
+    delete tid[i];
+  }
+  delete s_pMutex;
+  s_pMutex = 0;
+  pthread_barrier_destroy(&s_barrier);
+
+  if (s_counter == n_threads * s_iterations)
+    fprintf(stderr, "Test successful.\n");
+  else
+    fprintf(stderr, "Test failed: counter = %d, should be %d\n",
+            s_counter, n_threads * s_iterations);
+
+  return 0;
+}
diff --git a/drd/tests/qt4_mutex.stderr.exp b/drd/tests/qt4_mutex.stderr.exp
new file mode 100644
index 0000000..21dba22
--- /dev/null
+++ b/drd/tests/qt4_mutex.stderr.exp
@@ -0,0 +1,5 @@
+
+Start of test.
+Test successful.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/qt4_mutex.vgtest b/drd/tests/qt4_mutex.vgtest
new file mode 100644
index 0000000..1015fff
--- /dev/null
+++ b/drd/tests/qt4_mutex.vgtest
@@ -0,0 +1,3 @@
+prereq: test -e qt4_mutex
+vgopts: --check-stack-var=yes
+prog: qt4_mutex
diff --git a/drd/tests/qt4_rwlock.cpp b/drd/tests/qt4_rwlock.cpp
new file mode 100644
index 0000000..db9cf24
--- /dev/null
+++ b/drd/tests/qt4_rwlock.cpp
@@ -0,0 +1,93 @@
+/// Qt4 reader-writer lock test.
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <QThread>               // class QThread
+#include <QReadWriteLock>        // class QReadWriteLock
+#include <cstdio>                // fprintf()
+#include <cstdlib>               // atoi()
+#include <new>
+#include <pthread.h>             // pthread_barrier_t
+#include <vector>
+
+
+static pthread_barrier_t s_barrier;
+static QReadWriteLock* s_pRWlock;
+static int s_iterations;
+static int s_counter;
+
+
+class IncThread: public QThread
+{
+public:
+  IncThread();
+  virtual ~IncThread();
+
+private:
+  virtual void run();
+};
+
+IncThread::IncThread()
+{ }
+
+IncThread::~IncThread()
+{ }
+
+void IncThread::run()
+{
+  int i;
+
+  pthread_barrier_wait(&s_barrier);
+  for (i = s_iterations; i > 0; i--)
+  {
+    s_pRWlock->lockForWrite();
+    s_counter++;
+    s_pRWlock->unlock();
+  }
+}
+
+int main(int argc, char** argv)
+{
+  int i;
+  const int n_threads = 10;
+  std::vector<QThread*> tid(n_threads);
+
+  s_iterations = argc > 1 ? atoi(argv[1]) : 1000;
+
+  fprintf(stderr, "Start of test.\n");
+
+  {
+    // Stack-allocated reader-writer lock.
+    QReadWriteLock RWL;
+    RWL.lockForRead();
+    RWL.unlock();
+    RWL.lockForWrite();
+    RWL.unlock();
+  }
+
+  pthread_barrier_init(&s_barrier, 0, n_threads);
+  s_pRWlock = new QReadWriteLock();
+  for (i = 0; i < n_threads; i++)
+  {
+    tid[i] = new IncThread;
+    tid[i]->start();
+  }
+  for (i = 0; i < n_threads; i++)
+  {
+    tid[i]->wait();
+    delete tid[i];
+  }
+  delete s_pRWlock;
+  s_pRWlock = 0;
+  pthread_barrier_destroy(&s_barrier);
+
+  if (s_counter == n_threads * s_iterations)
+    fprintf(stderr, "Test successful.\n");
+  else
+    fprintf(stderr, "Test failed: counter = %d, should be %d\n",
+            s_counter, n_threads * s_iterations);
+
+  return 0;
+}
diff --git a/drd/tests/qt4_rwlock.stderr.exp b/drd/tests/qt4_rwlock.stderr.exp
new file mode 100644
index 0000000..21dba22
--- /dev/null
+++ b/drd/tests/qt4_rwlock.stderr.exp
@@ -0,0 +1,5 @@
+
+Start of test.
+Test successful.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/qt4_rwlock.vgtest b/drd/tests/qt4_rwlock.vgtest
new file mode 100644
index 0000000..8619d93
--- /dev/null
+++ b/drd/tests/qt4_rwlock.vgtest
@@ -0,0 +1,3 @@
+prereq: test -e qt4_rwlock
+vgopts: --check-stack-var=yes
+prog: qt4_rwlock
diff --git a/drd/tests/qt4_semaphore.cpp b/drd/tests/qt4_semaphore.cpp
new file mode 100644
index 0000000..5143c75
--- /dev/null
+++ b/drd/tests/qt4_semaphore.cpp
@@ -0,0 +1,82 @@
+/// Qt4 semaphore test.
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <QThread>           // class QMutex
+#include <QSemaphore>        // class QSemaphore
+#include <cstdio>            // fprintf()
+#include <cstdlib>           // atoi()
+#include <new>
+#include <pthread.h>         // pthread_barrier_t
+#include <vector>
+
+
+static pthread_barrier_t s_barrier;
+static QSemaphore* s_pSema;
+static int s_iterations;
+static int s_counter;
+
+
+class IncThread: public QThread
+{
+  virtual void run();
+};
+
+void IncThread::run()
+{
+  int i;
+
+  pthread_barrier_wait(&s_barrier);
+  for (i = s_iterations; i > 0; i--)
+  {
+    s_pSema->acquire();
+    s_counter++;
+    s_pSema->release();
+  }
+}
+
+int main(int argc, char** argv)
+{
+  int i;
+  const int n_threads = 10;
+  std::vector<QThread*> tid(n_threads);
+
+  s_iterations = argc > 1 ? atoi(argv[1]) : 1000;
+
+  fprintf(stderr, "Start of test.\n");
+
+  {
+    // Stack-allocated semaphore.
+    QSemaphore S(1);
+    S.acquire();
+    S.release();
+    S.acquire();
+    S.release();
+  }
+
+  pthread_barrier_init(&s_barrier, 0, n_threads);
+  s_pSema = new QSemaphore(1);
+  for (i = 0; i < n_threads; i++)
+  {
+    tid[i] = new IncThread;
+    tid[i]->start();
+  }
+  for (i = 0; i < n_threads; i++)
+  {
+    tid[i]->wait();
+    delete tid[i];
+  }
+  delete s_pSema;
+  s_pSema = 0;
+  pthread_barrier_destroy(&s_barrier);
+
+  if (s_counter == n_threads * s_iterations)
+    fprintf(stderr, "Test successful.\n");
+  else
+    fprintf(stderr, "Test failed: counter = %d, should be %d\n",
+            s_counter, n_threads * s_iterations);
+
+  return 0;
+}
diff --git a/drd/tests/qt4_semaphore.stderr.exp b/drd/tests/qt4_semaphore.stderr.exp
new file mode 100644
index 0000000..21dba22
--- /dev/null
+++ b/drd/tests/qt4_semaphore.stderr.exp
@@ -0,0 +1,5 @@
+
+Start of test.
+Test successful.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/qt4_semaphore.vgtest b/drd/tests/qt4_semaphore.vgtest
new file mode 100644
index 0000000..771ac15
--- /dev/null
+++ b/drd/tests/qt4_semaphore.vgtest
@@ -0,0 +1,3 @@
+prereq: test -e qt4_semaphore
+vgopts: --check-stack-var=yes
+prog: qt4_semaphore
diff --git a/drd/tests/read_after_free.c b/drd/tests/read_after_free.c
new file mode 100644
index 0000000..1319cb2
--- /dev/null
+++ b/drd/tests/read_after_free.c
@@ -0,0 +1,45 @@
+#define _GNU_SOURCE 1
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+static char* s_mem;
+static volatile int s_freed;
+
+static void* thread_func(void* arg)
+{
+    // Busy-wait until pthread_create() has finished.
+    while (s_freed == 0)
+        pthread_yield();
+    free(s_mem);
+    __sync_add_and_fetch(&s_freed, 1);
+    return NULL;
+}
+
+int main(int argc, char** argv)
+{
+    pthread_t tid;
+    int quiet;
+    char result;
+
+    quiet = argc > 1;
+
+    s_mem = malloc(10);
+    if (!quiet)
+        fprintf(stderr, "Pointer to allocated memory: %p\n", s_mem);
+    assert(s_mem);
+    pthread_create(&tid, NULL, thread_func, NULL);
+    __sync_add_and_fetch(&s_freed, 1);
+    // Busy-wait until the memory has been freed.
+    while (s_freed == 1)
+        pthread_yield();
+    // Read-after-free.
+    result = s_mem[0];
+    if (!quiet)
+        fprintf(stderr, "Read-after-free result: %d\n", result);
+    pthread_join(tid, NULL);
+    fprintf(stderr, "Done.\n");
+    return 0;
+}
diff --git a/drd/tests/read_after_free.stderr.exp b/drd/tests/read_after_free.stderr.exp
new file mode 100644
index 0000000..7463c72
--- /dev/null
+++ b/drd/tests/read_after_free.stderr.exp
@@ -0,0 +1,8 @@
+
+Conflicting load by thread 1 at 0x........ size 1
+   at 0x........: main (read_after_free.c:?)
+Allocation context: unknown.
+
+Done.
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/read_after_free.vgtest b/drd/tests/read_after_free.vgtest
new file mode 100644
index 0000000..c8b1c2b
--- /dev/null
+++ b/drd/tests/read_after_free.vgtest
@@ -0,0 +1,4 @@
+prereq: test -e read_after_free && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --free-is-write=yes --show-confl-seg=no
+prog: read_after_free
+args: -q
diff --git a/drd/tests/recursive_mutex.c b/drd/tests/recursive_mutex.c
new file mode 100644
index 0000000..7d8ff2d
--- /dev/null
+++ b/drd/tests/recursive_mutex.c
@@ -0,0 +1,75 @@
+/** Initialize several kinds of mutexes and lock each mutex twice.
+ *  Note: locking a regular mutex twice causes a deadlock.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+#include "../../config.h"
+
+
+static void lock_twice(pthread_mutex_t* const p)
+{
+  if (pthread_mutex_trylock(p) != 0)
+    fprintf(stderr, "first lock call failed !\n");
+  if (pthread_mutex_trylock(p) != 0)
+    fprintf(stderr, "second lock call failed !\n");
+  if (pthread_mutex_unlock(p) != 0)
+    fprintf(stderr, "first unlock call failed !\n");
+  if (pthread_mutex_unlock(p) != 0)
+    fprintf(stderr, "second unlock call failed !\n");
+}
+
+int main(int argc, char** argv)
+{
+#if defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
+  {
+    pthread_mutex_t m = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+
+    fprintf(stderr, "Recursive mutex (statically initialized).\n");
+    lock_twice(&m);
+    pthread_mutex_destroy(&m);
+  }
+#endif
+#if defined(HAVE_PTHREAD_MUTEX_RECURSIVE_NP)
+  {
+    pthread_mutex_t m;
+    pthread_mutexattr_t attr;
+
+    fprintf(stderr, "\nRecursive mutex (initialized via mutex attributes).\n");
+    pthread_mutexattr_init(&attr);
+    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
+    pthread_mutex_init(&m, &attr);
+    pthread_mutexattr_destroy(&attr);
+    lock_twice(&m);
+    pthread_mutex_destroy(&m);
+  }
+#endif
+#if defined(HAVE_PTHREAD_MUTEX_ERRORCHECK_NP)
+  {
+    pthread_mutex_t m;
+    pthread_mutexattr_t attr;
+
+    fprintf(stderr, "\nError checking mutex.\n");
+    pthread_mutexattr_init(&attr);
+    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
+    pthread_mutex_init(&m, &attr);
+    pthread_mutexattr_destroy(&attr);
+    lock_twice(&m);
+    pthread_mutex_destroy(&m);
+  }
+#endif
+
+  {
+    pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+
+    fprintf(stderr, "\nNon-recursive mutex.\n");
+    lock_twice(&m);
+  }
+
+  fprintf(stderr, "\nDone.\n");
+
+  return 0;
+}
diff --git a/drd/tests/recursive_mutex.stderr.exp-darwin b/drd/tests/recursive_mutex.stderr.exp-darwin
new file mode 100644
index 0000000..04a1839
--- /dev/null
+++ b/drd/tests/recursive_mutex.stderr.exp-darwin
@@ -0,0 +1,17 @@
+
+
+Non-recursive mutex.
+second lock call failed !
+Mutex not locked by calling thread: mutex 0x........, recursion count 0, owner 1.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: lock_twice (recursive_mutex.c:?)
+   by 0x........: main (recursive_mutex.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_trylock (drd_pthread_intercepts.c:?)
+   by 0x........: lock_twice (recursive_mutex.c:?)
+   by 0x........: main (recursive_mutex.c:?)
+
+
+Done.
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/recursive_mutex.stderr.exp-linux b/drd/tests/recursive_mutex.stderr.exp-linux
new file mode 100644
index 0000000..efa983a
--- /dev/null
+++ b/drd/tests/recursive_mutex.stderr.exp-linux
@@ -0,0 +1,32 @@
+
+Recursive mutex (statically initialized).
+
+Recursive mutex (initialized via mutex attributes).
+
+Error checking mutex.
+second lock call failed !
+Mutex not locked by calling thread: mutex 0x........, recursion count 0, owner 1.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: lock_twice (recursive_mutex.c:?)
+   by 0x........: main (recursive_mutex.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (recursive_mutex.c:?)
+
+second unlock call failed !
+
+Non-recursive mutex.
+second lock call failed !
+Mutex not locked by calling thread: mutex 0x........, recursion count 0, owner 1.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: lock_twice (recursive_mutex.c:?)
+   by 0x........: main (recursive_mutex.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_trylock (drd_pthread_intercepts.c:?)
+   by 0x........: lock_twice (recursive_mutex.c:?)
+   by 0x........: main (recursive_mutex.c:?)
+
+
+Done.
+
+ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/recursive_mutex.vgtest b/drd/tests/recursive_mutex.vgtest
new file mode 100644
index 0000000..1db3ea2
--- /dev/null
+++ b/drd/tests/recursive_mutex.vgtest
@@ -0,0 +1,4 @@
+prereq: ./supported_libpthread
+vgopts: --check-stack-var=yes --read-var-info=yes
+prog: recursive_mutex
+stderr_filter: filter_stderr_and_thread_no
diff --git a/drd/tests/run_openmp_test b/drd/tests/run_openmp_test
new file mode 100755
index 0000000..f507676
--- /dev/null
+++ b/drd/tests/run_openmp_test
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+# Shell script with one argument (path of an OpenMP executable) that exits
+# with status 0 if the OpenMP test program should be run and that exits with
+# status 1 if the OpenMP test program should not be run.
+
+test -e "$1" || exit $?
+
+./supported_libpthread || exit $?
+
+# Do not accept any statically linked executable.
+if /usr/bin/file "$1" | grep -q 'statically linked'; then
+  exit 1
+fi
+
+if [ "$(uname)" = Linux ]; then
+
+  # Let the dynamic linker/loader print the path of libgomp. See also man ld.so
+  libgomp_path="$(LD_TRACE_LOADED_OBJECTS=1 "$1" \
+    | while read soname arrow path offset; \
+   do if [ "${soname#libgomp.so}" != "${soname}" ]; then echo $path; fi; done)"
+
+  # Inspect the output of nm. If nm does not find any symbol information,
+  # echo 1. If the symbol gomp_barrier_init is found, echo 0. Otherwise echo
+  # nothing. The second case occurs if gcc has been compiled with 
+  # --disable-linux-futex, and the last case occurs if gcc has been compiled
+  # with --enable-linux-futex.
+  rc="$(nm "${libgomp_path}" 2>&1 \
+        |
+        while read line
+        do
+          if [ "${line%: no symbols}" != "${line}" ]; then
+            echo 1
+            break
+          elif [ "${line% gomp_barrier_init}" != "${line}" ]; then
+            echo 0
+            break
+          fi
+        done)"
+  exit ${rc:-1}
+
+fi
diff --git a/drd/tests/rwlock_race.c b/drd/tests/rwlock_race.c
new file mode 100644
index 0000000..e07524f
--- /dev/null
+++ b/drd/tests/rwlock_race.c
@@ -0,0 +1,56 @@
+/** Cause a race inside code protected by a reader lock.
+ */
+
+
+/* Needed for older glibc's (2.3 and older, at least) who don't
+   otherwise "know" about pthread_rwlock_anything or about
+   PTHREAD_MUTEX_RECURSIVE (amongst things). */
+
+#define _GNU_SOURCE 1
+
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+
+static pthread_rwlock_t s_rwlock;
+static int s_racy;
+
+static void sleep_ms(const int ms)
+{
+  struct timespec delay = { ms / 1000, (ms % 1000) * 1000 * 1000 };
+  nanosleep(&delay, 0);
+}
+
+static void* thread_func(void* arg)
+{
+  pthread_rwlock_rdlock(&s_rwlock);
+  s_racy++;
+  pthread_rwlock_unlock(&s_rwlock);
+  sleep_ms(100);
+  return 0;
+}
+
+int main(int argc, char** argv)
+{
+  pthread_t thread1;
+  pthread_t thread2;
+
+#if 0
+  int res;
+  VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_TRACE_ADDR,
+                             &s_racy, 0, 0, 0, 0);
+#endif
+
+  pthread_rwlock_init(&s_rwlock, 0);
+  pthread_create(&thread1, 0, thread_func, 0);
+  pthread_create(&thread2, 0, thread_func, 0);
+  pthread_join(thread1, 0);
+  pthread_join(thread2, 0);
+  pthread_rwlock_destroy(&s_rwlock);
+
+  fprintf(stderr, "Result: %d\n", s_racy);
+
+  return 0;
+}
diff --git a/drd/tests/rwlock_race.stderr.exp b/drd/tests/rwlock_race.stderr.exp
new file mode 100644
index 0000000..124b2c4
--- /dev/null
+++ b/drd/tests/rwlock_race.stderr.exp
@@ -0,0 +1,17 @@
+
+Thread 3:
+Conflicting load by thread 3 at 0x........ size 4
+   at 0x........: thread_func (rwlock_race.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Location 0x........ is 0 bytes inside local var "s_racy"
+declared at rwlock_race.c:18, in frame #? of thread 3
+
+Conflicting store by thread 3 at 0x........ size 4
+   at 0x........: thread_func (rwlock_race.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Location 0x........ is 0 bytes inside local var "s_racy"
+declared at rwlock_race.c:18, in frame #? of thread 3
+
+Result: 2
+
+ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/rwlock_race.stderr.exp2 b/drd/tests/rwlock_race.stderr.exp2
new file mode 100644
index 0000000..f48bc6a
--- /dev/null
+++ b/drd/tests/rwlock_race.stderr.exp2
@@ -0,0 +1,17 @@
+
+Thread 3:
+Conflicting load by thread 3 at 0x........ size 4
+   at 0x........: thread (rwlock_race.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Location 0x........ is 0 bytes inside local var "s_racy"
+declared at rwlock_race.c:17, in frame #? of thread 3
+
+Conflicting store by thread 3 at 0x........ size 4
+   at 0x........: thread (rwlock_race.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Location 0x........ is 0 bytes inside local var "s_racy"
+declared at rwlock_race.c:17, in frame #? of thread 3
+
+Result: 2
+
+ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/rwlock_race.vgtest b/drd/tests/rwlock_race.vgtest
new file mode 100644
index 0000000..b5834eb
--- /dev/null
+++ b/drd/tests/rwlock_race.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread
+vgopts: --show-confl-seg=no --read-var-info=yes --num-callers=2
+prog: rwlock_race
diff --git a/drd/tests/rwlock_test.c b/drd/tests/rwlock_test.c
new file mode 100644
index 0000000..65cfd5b
--- /dev/null
+++ b/drd/tests/rwlock_test.c
@@ -0,0 +1,115 @@
+/**
+ * @file  rwlock_test.c
+ *
+ * @brief Multithreaded test program that triggers various access patterns
+ *        without triggering any race conditions.
+ */
+
+
+#define _GNU_SOURCE 1
+
+#include <assert.h>
+#include <limits.h>  /* PTHREAD_STACK_MIN */
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>  /* malloc() */
+#include <string.h>  /* strerror() */
+#include <unistd.h>  /* getopt() */
+
+static int s_num_threads = 10;
+static int s_num_iterations = 1000;
+static pthread_mutex_t s_mutex;
+static long long s_grand_sum; /* protected by s_mutex. */
+static pthread_rwlock_t s_rwlock;
+static int s_counter; /* protected by s_rwlock. */
+
+static void* thread_func(void* arg)
+{
+  int i, r;
+  int sum1 = 0, sum2 = 0;
+
+  for (i = s_num_iterations; i > 0; i--)
+  {
+    r = pthread_rwlock_rdlock(&s_rwlock);
+    assert(! r);
+    sum1 += s_counter;
+    r = pthread_rwlock_unlock(&s_rwlock);
+    assert(! r);
+    r = pthread_rwlock_wrlock(&s_rwlock);
+    assert(! r);
+    sum2 += s_counter++;
+    r = pthread_rwlock_unlock(&s_rwlock);
+    assert(! r);
+  }
+
+  pthread_mutex_lock(&s_mutex);
+  s_grand_sum += sum2;
+  pthread_mutex_unlock(&s_mutex);
+
+  return 0;
+}
+
+int main(int argc, char** argv)
+{
+  pthread_attr_t attr;
+  pthread_t* tid;
+  int threads_created;
+  int optchar;
+  int err;
+  int i;
+  int expected_counter;
+  long long expected_grand_sum;
+
+  while ((optchar = getopt(argc, argv, "i:t:")) != EOF)
+  {
+    switch (optchar)
+    {
+    case 'i':
+      s_num_iterations = atoi(optarg);
+      break;
+    case 't':
+      s_num_threads = atoi(optarg);
+      break;
+    default:
+      fprintf(stderr, "Error: unknown option '%c'.\n", optchar);
+      return 1;
+    }
+  }
+
+  pthread_mutex_init(&s_mutex, NULL);
+  pthread_rwlock_init(&s_rwlock, NULL);
+
+  pthread_attr_init(&attr);
+  err = pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + 4096);
+  assert(err == 0);
+
+  tid = calloc(s_num_threads, sizeof(*tid));
+  threads_created = 0;
+  for (i = 0; i < s_num_threads; i++)
+  {
+    err = pthread_create(&tid[i], &attr, thread_func, 0);
+    if (err)
+      printf("failed to create thread %d: %s\n", i, strerror(err));
+    else
+      threads_created++;
+  }
+
+  pthread_attr_destroy(&attr);
+
+  for (i = 0; i < s_num_threads; i++)
+  {
+    if (tid[i])
+      pthread_join(tid[i], 0);
+  }
+  free(tid);
+
+  expected_counter = threads_created * s_num_iterations;
+  fprintf(stderr, "s_counter - expected_counter = %d\n",
+          s_counter - expected_counter);
+  expected_grand_sum = 1ULL * expected_counter * (expected_counter - 1) / 2;
+  fprintf(stderr, "s_grand_sum - expected_grand_sum = %lld\n",
+          s_grand_sum - expected_grand_sum);
+  fprintf(stderr, "Finished.\n");
+
+  return 0;
+}
diff --git a/drd/tests/rwlock_test.stderr.exp b/drd/tests/rwlock_test.stderr.exp
new file mode 100644
index 0000000..3063f40
--- /dev/null
+++ b/drd/tests/rwlock_test.stderr.exp
@@ -0,0 +1,6 @@
+
+s_counter - expected_counter = 0
+s_grand_sum - expected_grand_sum = 0
+Finished.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/rwlock_test.vgtest b/drd/tests/rwlock_test.vgtest
new file mode 100644
index 0000000..b8c874e
--- /dev/null
+++ b/drd/tests/rwlock_test.vgtest
@@ -0,0 +1,2 @@
+vgopts: --check-stack-var=yes --read-var-info=yes --show-confl-seg=no
+prog: rwlock_test
diff --git a/drd/tests/rwlock_type_checking.c b/drd/tests/rwlock_type_checking.c
new file mode 100644
index 0000000..e4697af
--- /dev/null
+++ b/drd/tests/rwlock_type_checking.c
@@ -0,0 +1,37 @@
+/**
+ * @file  rwlock_type_checking.c
+ *
+ * @brief Test whether DRD reports attempts to use a user-defined rwlock as
+ *        a POSIX rwlock and vice versa.
+ */
+
+
+#define _GNU_SOURCE 1
+
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include "../../config.h"
+#include "../../drd/drd.h"
+
+
+int main(int argc, char** argv)
+{
+  pthread_rwlock_t posix_rwlock;
+  pthread_rwlock_t user_defined_rwlock;
+
+  memset(&user_defined_rwlock, 0, sizeof(user_defined_rwlock));
+  ANNOTATE_RWLOCK_CREATE(&user_defined_rwlock);
+  pthread_rwlock_init(&posix_rwlock, 0);
+
+  pthread_rwlock_init((pthread_rwlock_t*)&user_defined_rwlock, 0);
+
+  ANNOTATE_READERLOCK_RELEASED(&posix_rwlock);
+
+  pthread_rwlock_destroy(&posix_rwlock);
+  ANNOTATE_RWLOCK_DESTROY(&user_defined_rwlock);
+
+  fprintf(stderr, "Finished.\n");
+
+  return 0;
+}
diff --git a/drd/tests/rwlock_type_checking.stderr.exp b/drd/tests/rwlock_type_checking.stderr.exp
new file mode 100644
index 0000000..b3d2dc9
--- /dev/null
+++ b/drd/tests/rwlock_type_checking.stderr.exp
@@ -0,0 +1,16 @@
+
+Attempt to use a user-defined rwlock as a POSIX rwlock: rwlock 0x.........
+   at 0x........: pthread_rwlock_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (rwlock_type_checking.c:?)
+rwlock 0x........ was first observed at:
+   at 0x........: main (rwlock_type_checking.c:?)
+
+Attempt to use a POSIX rwlock as a user-defined rwlock: rwlock 0x.........
+   at 0x........: main (rwlock_type_checking.c:?)
+rwlock 0x........ was first observed at:
+   at 0x........: pthread_rwlock_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (rwlock_type_checking.c:?)
+
+Finished.
+
+ERROR SUMMARY: 4 errors from 2 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/rwlock_type_checking.vgtest b/drd/tests/rwlock_type_checking.vgtest
new file mode 100644
index 0000000..a7eb0f4
--- /dev/null
+++ b/drd/tests/rwlock_type_checking.vgtest
@@ -0,0 +1,4 @@
+prereq: test -e rwlock_type_checking && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no
+prog: rwlock_type_checking
+stderr_filter: filter_stderr
diff --git a/drd/tests/sem_as_mutex.c b/drd/tests/sem_as_mutex.c
new file mode 100644
index 0000000..5a8cb13
--- /dev/null
+++ b/drd/tests/sem_as_mutex.c
@@ -0,0 +1,105 @@
+/* Use a semaphore to implement mutual exclusion. */
+
+
+#include <assert.h>
+#include <stdio.h>     /* printf() */
+#include <pthread.h>
+#include <semaphore.h>
+#include <unistd.h>    /* sleep() */
+
+
+/* Local functions declarations. */
+
+static void* thread_func(void*);
+
+
+/* Local variables. */
+
+/* s_sem protects s_d3. */
+static sem_t s_sem;
+
+static double s_d1; /* accessed before thread creation and in the created */
+                    /* thread (not a race). */
+static double s_d2; /* accessed in the created thread and after the join */
+                    /* (not a race). */
+static double s_d3; /* accessed simultaneously from both threads (race). */
+static int    s_debug     = 0;
+static int    s_do_printf = 0;
+static int    s_do_mutual_exclusion = 0;
+
+
+/* Function definitions. */
+
+int main(int argc, char** argv)
+{
+  int optchar;
+  pthread_t threadid;
+
+  while ((optchar = getopt(argc, argv, "dmp")) != EOF)
+  {
+    switch (optchar)
+    {
+    case 'd':
+      s_debug = 1;
+      break;
+    case 'm':
+      s_do_mutual_exclusion = 1;
+      break;
+    case 'p':
+      s_do_printf = 1;
+      break;
+    default:
+      assert(0);
+    }
+  }
+
+  sem_init(&s_sem, 0, 1);
+
+  /*
+   * Switch to line-buffered mode, such that timing information can be
+   * obtained for each printf() call with strace.
+   */
+  setlinebuf(stdout);
+
+  if (s_debug)
+  {
+    printf("&s_d1 = %p; &s_d2 = %p; &s_d3 = %p\n", &s_d1, &s_d2, &s_d3);
+  }
+
+  s_d1 = 1;
+  s_d3 = 3;
+
+  pthread_create(&threadid, 0, thread_func, 0);
+
+  sleep(1); /* Wait until thread_func() finished. */
+
+  {
+    if (s_do_mutual_exclusion) sem_wait(&s_sem);
+    s_d3++;
+    if (s_do_mutual_exclusion) sem_post(&s_sem);
+  }
+
+  /* Wait until the thread finished. */
+  pthread_join(threadid, 0);
+  if (s_do_printf) printf("s_d2 = %g (should be 2)\n", s_d2);
+  if (s_do_printf) printf("s_d3 = %g (should be 5)\n", s_d3);
+
+  sem_destroy(&s_sem);
+
+  return 0;
+}
+
+static void* thread_func(void* thread_arg)
+{
+  if (s_do_printf)
+  {
+    printf("s_d1 = %g (should be 1)\n", s_d1);
+  }
+  s_d2 = 2;
+  {
+    if (s_do_mutual_exclusion) sem_wait(&s_sem);
+    s_d3++;
+    if (s_do_mutual_exclusion) sem_post(&s_sem);
+  }
+  return 0;
+}
diff --git a/drd/tests/sem_as_mutex.stderr.exp b/drd/tests/sem_as_mutex.stderr.exp
new file mode 100644
index 0000000..1646a6c
--- /dev/null
+++ b/drd/tests/sem_as_mutex.stderr.exp
@@ -0,0 +1,21 @@
+
+Conflicting load by thread 1 at 0x........ size 8
+   at 0x........: main (sem_as_mutex.c:?)
+Location 0x........ is 0 bytes inside local var "s_d3"
+declared at sem_as_mutex.c:25, in frame #? of thread 1
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+Conflicting store by thread 1 at 0x........ size 8
+   at 0x........: main (sem_as_mutex.c:?)
+Location 0x........ is 0 bytes inside local var "s_d3"
+declared at sem_as_mutex.c:25, in frame #? of thread 1
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+
+ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/sem_as_mutex.vgtest b/drd/tests/sem_as_mutex.vgtest
new file mode 100644
index 0000000..dc059a0
--- /dev/null
+++ b/drd/tests/sem_as_mutex.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread && ./supported_sem_init
+vgopts: --check-stack-var=yes --read-var-info=yes
+prog: sem_as_mutex
diff --git a/drd/tests/sem_as_mutex2.stderr.exp b/drd/tests/sem_as_mutex2.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/sem_as_mutex2.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/sem_as_mutex2.vgtest b/drd/tests/sem_as_mutex2.vgtest
new file mode 100644
index 0000000..235a19b
--- /dev/null
+++ b/drd/tests/sem_as_mutex2.vgtest
@@ -0,0 +1,4 @@
+prereq: ./supported_libpthread && ./supported_sem_init
+vgopts: --check-stack-var=yes --read-var-info=yes
+prog: sem_as_mutex
+args: -m
diff --git a/drd/tests/sem_as_mutex3.stderr.exp b/drd/tests/sem_as_mutex3.stderr.exp
new file mode 100644
index 0000000..97b09a1
--- /dev/null
+++ b/drd/tests/sem_as_mutex3.stderr.exp
@@ -0,0 +1,12 @@
+
+Conflicting load by thread 1 at 0x........ size 8
+   at 0x........: main (sem_as_mutex.c:?)
+Location 0x........ is 0 bytes inside local var "s_d3"
+declared at sem_as_mutex.c:25, in frame #? of thread 1
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/sem_as_mutex3.vgtest b/drd/tests/sem_as_mutex3.vgtest
new file mode 100644
index 0000000..a838b84
--- /dev/null
+++ b/drd/tests/sem_as_mutex3.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread && ./supported_sem_init
+vgopts: --check-stack-var=yes --first-race-only=yes --read-var-info=yes
+prog: sem_as_mutex
diff --git a/drd/tests/sem_open.c b/drd/tests/sem_open.c
new file mode 100644
index 0000000..d452009
--- /dev/null
+++ b/drd/tests/sem_open.c
@@ -0,0 +1,118 @@
+/* Use a semaphore to implement mutual exclusion. */
+
+#include <assert.h>
+#include <fcntl.h>     /* O_CREAT */
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>     /* printf() */
+#include <stdlib.h>    /* exit()  */
+#include <unistd.h>    /* sleep() */
+
+/* Local functions declarations. */
+
+static void* thread_func(void*);
+
+
+/* Local variables. */
+
+/* s_sem protects s_d3. */
+static sem_t* s_sem;
+
+static double s_d1; /* accessed before thread creation and in the created */
+                    /* thread (not a race). */
+static double s_d2; /* accessed in the created thread and after the join */
+                    /* (not a race). */
+static double s_d3; /* accessed simultaneously from both threads (race). */
+static int    s_debug     = 0;
+static int    s_do_printf = 0;
+static int    s_do_mutual_exclusion = 0;
+
+
+/* Function definitions. */
+
+int main(int argc, char** argv)
+{
+  int optchar;
+  pthread_t threadid;
+  char semaphore_name[32];
+
+  while ((optchar = getopt(argc, argv, "dmp")) != EOF)
+  {
+    switch (optchar)
+    {
+    case 'd':
+      s_debug = 1;
+      break;
+    case 'm':
+      s_do_mutual_exclusion = 1;
+      break;
+    case 'p':
+      s_do_printf = 1;
+      break;
+    default:
+      assert(0);
+    }
+  }
+
+  /*
+   * Use the ipcs and ipcrm commands to clean up named semaphores left by
+   * aborted instances of this process.
+   */
+  snprintf(semaphore_name, sizeof(semaphore_name), "drd-sem-open-test");
+  s_sem = sem_open(semaphore_name, O_CREAT, 0600, 1);
+  if (s_sem == SEM_FAILED)
+  {
+    fprintf(stderr, "Failed to create a semaphore with name %s\n",
+            semaphore_name);
+    exit(1);
+  }
+
+  /*
+   * Switch to line-buffered mode, such that timing information can be
+   * obtained for each printf() call with strace.
+   */
+  setlinebuf(stdout);
+
+  if (s_debug)
+  {
+    printf("&s_d1 = %p; &s_d2 = %p; &s_d3 = %p\n", &s_d1, &s_d2, &s_d3);
+  }
+
+  s_d1 = 1;
+  s_d3 = 3;
+
+  pthread_create(&threadid, 0, thread_func, 0);
+
+  sleep(1); /* Wait until thread_func() finished. */
+
+  {
+    if (s_do_mutual_exclusion) sem_wait(s_sem);
+    s_d3++;
+    if (s_do_mutual_exclusion) sem_post(s_sem);
+  }
+
+  /* Wait until the thread finished. */
+  pthread_join(threadid, 0);
+  if (s_do_printf) printf("s_d2 = %g (should be 2)\n", s_d2);
+  if (s_do_printf) printf("s_d3 = %g (should be 5)\n", s_d3);
+
+  sem_close(s_sem);
+  sem_unlink(semaphore_name);
+
+  return 0;
+}
+
+static void* thread_func(void* thread_arg)
+{
+  if (s_do_printf)
+  {
+    printf("s_d1 = %g (should be 1)\n", s_d1);
+  }
+  s_d2 = 2;
+  {
+    if (s_do_mutual_exclusion) sem_wait(s_sem);
+    s_d3++;
+    if (s_do_mutual_exclusion) sem_post(s_sem);
+  }
+  return 0;
+}
diff --git a/drd/tests/sem_open.stderr.exp b/drd/tests/sem_open.stderr.exp
new file mode 100644
index 0000000..4e769e5
--- /dev/null
+++ b/drd/tests/sem_open.stderr.exp
@@ -0,0 +1,21 @@
+
+Conflicting load by thread 1 at 0x........ size 8
+   at 0x........: main (sem_open.c:?)
+Location 0x........ is 0 bytes inside local var "s_d3"
+declared at sem_open.c:25, in frame #? of thread 1
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+Conflicting store by thread 1 at 0x........ size 8
+   at 0x........: main (sem_open.c:?)
+Location 0x........ is 0 bytes inside local var "s_d3"
+declared at sem_open.c:25, in frame #? of thread 1
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+
+ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/sem_open.vgtest b/drd/tests/sem_open.vgtest
new file mode 100644
index 0000000..08bb5cc
--- /dev/null
+++ b/drd/tests/sem_open.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread
+vgopts: --check-stack-var=yes --read-var-info=yes
+prog: sem_open
diff --git a/drd/tests/sem_open2.stderr.exp b/drd/tests/sem_open2.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/sem_open2.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/sem_open2.vgtest b/drd/tests/sem_open2.vgtest
new file mode 100644
index 0000000..a1ece0e
--- /dev/null
+++ b/drd/tests/sem_open2.vgtest
@@ -0,0 +1,4 @@
+prereq: ./supported_libpthread
+vgopts: --check-stack-var=yes --read-var-info=yes
+prog: sem_open
+args: -m
diff --git a/drd/tests/sem_open3.stderr.exp b/drd/tests/sem_open3.stderr.exp
new file mode 100644
index 0000000..3c2d392
--- /dev/null
+++ b/drd/tests/sem_open3.stderr.exp
@@ -0,0 +1,12 @@
+
+Conflicting load by thread 1 at 0x........ size 8
+   at 0x........: main (sem_open.c:?)
+Location 0x........ is 0 bytes inside local var "s_d3"
+declared at sem_open.c:25, in frame #? of thread 1
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/sem_open3.vgtest b/drd/tests/sem_open3.vgtest
new file mode 100644
index 0000000..02e49d0
--- /dev/null
+++ b/drd/tests/sem_open3.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread
+vgopts: --check-stack-var=yes --first-race-only=yes --read-var-info=yes
+prog: sem_open
diff --git a/drd/tests/sem_open_traced.stderr.exp b/drd/tests/sem_open_traced.stderr.exp
new file mode 100644
index 0000000..78543e4
--- /dev/null
+++ b/drd/tests/sem_open_traced.stderr.exp
@@ -0,0 +1,9 @@
+
+[1] sem_open      0x........ name drd-sem-open-test oflag 0x........ mode 0600 value 1
+[2] sem_wait      0x........ value 1 -> 0
+[2] sem_post      0x........ value 0 -> 1
+[1] sem_wait      0x........ value 1 -> 0
+[1] sem_post      0x........ value 0 -> 1
+[1] sem_close     0x........ value 1
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/sem_open_traced.vgtest b/drd/tests/sem_open_traced.vgtest
new file mode 100644
index 0000000..9a3012f
--- /dev/null
+++ b/drd/tests/sem_open_traced.vgtest
@@ -0,0 +1,4 @@
+prereq: ./supported_libpthread
+vgopts: --check-stack-var=yes --read-var-info=yes --trace-semaphore=yes
+prog: sem_open
+args: -m
diff --git a/drd/tests/sigalrm.c b/drd/tests/sigalrm.c
new file mode 100644
index 0000000..408eaf8
--- /dev/null
+++ b/drd/tests/sigalrm.c
@@ -0,0 +1,88 @@
+#include "../../config.h"
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#ifdef HAVE_ASM_UNISTD_H
+#include <asm/unistd.h> // __NR_gettid
+#endif
+#include "../drd.h"
+
+
+static int s_debug = 0;
+
+
+static int getktid()
+{
+#ifdef __NR_gettid
+  return syscall(__NR_gettid);
+#else
+  return -1;
+#endif
+}
+
+static void print_thread_id(const char* const label)
+{
+  if (s_debug)
+  {
+    char msg[256];
+    snprintf(msg, sizeof(msg),
+             "%spid %d / kernel thread ID %d / Valgrind thread ID %d\n",
+             label, getpid(), getktid(), DRD_GET_VALGRIND_THREADID);
+    write(STDOUT_FILENO, msg, strlen(msg));
+  }
+}
+
+static void SignalHandler(const int iSignal)
+{
+  print_thread_id("Signal was delivered to ");
+}
+
+void* thread_func(void* thread_arg)
+{
+  print_thread_id("thread: ");
+
+  sleep(10);
+  //assert(result < 0 && errno == EINTR);
+
+  return 0;
+}
+
+int main(int argc, char** argv)
+{
+  int vgthreadid;
+  pthread_t threadid;
+  struct timespec tsDelay;
+
+  // Primitive argument parsing.
+  if (argc > 1)
+    s_debug = 1;
+
+  vgthreadid = DRD_GET_VALGRIND_THREADID;
+
+  print_thread_id("main: ");
+
+  {
+    struct sigaction sa;
+    memset(&sa, 0, sizeof(sa));
+    sa.sa_handler = &SignalHandler;
+    sigemptyset(&sa.sa_mask);
+    sigaction(SIGALRM, &sa, 0);
+  }
+
+  pthread_create(&threadid, 0, thread_func, 0);
+  // Wait until the thread is inside clock_nanosleep().
+  tsDelay.tv_sec = 0;
+  tsDelay.tv_nsec = 20 * 1000 * 1000;
+  nanosleep(&tsDelay, 0);
+  // And send SIGALRM to the thread.
+  pthread_kill(threadid, SIGALRM);
+  pthread_join(threadid, 0);
+
+  return 0;
+}
diff --git a/drd/tests/sigalrm.stderr.exp b/drd/tests/sigalrm.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/sigalrm.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/sigalrm.vgtest b/drd/tests/sigalrm.vgtest
new file mode 100644
index 0000000..cb371bc
--- /dev/null
+++ b/drd/tests/sigalrm.vgtest
@@ -0,0 +1,2 @@
+prereq: ./supported_libpthread
+prog: sigalrm
diff --git a/drd/tests/sigaltstack.stderr.exp b/drd/tests/sigaltstack.stderr.exp
new file mode 100644
index 0000000..b95833f
--- /dev/null
+++ b/drd/tests/sigaltstack.stderr.exp
@@ -0,0 +1,6 @@
+calling sigaltstack, stack base is 0x........
+setting sigaction
+res = 0
+raising the signal
+caught signal, local var is on 0x........
+done
diff --git a/drd/tests/sigaltstack.vgtest b/drd/tests/sigaltstack.vgtest
new file mode 100644
index 0000000..a079d60
--- /dev/null
+++ b/drd/tests/sigaltstack.vgtest
@@ -0,0 +1,2 @@
+prog: ../../memcheck/tests/sigaltstack
+vgopts: -q
diff --git a/drd/tests/supported_libpthread b/drd/tests/supported_libpthread
new file mode 100755
index 0000000..d42ea1a
--- /dev/null
+++ b/drd/tests/supported_libpthread
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+# Exit with status 0 if a supported version of libpthread is found (NPTL or
+# non-Linux libpthread) and exit with status 1 if a non-supported version of
+# libpthread is found (LinuxThreads).
+
+if [ "$(uname)" = "Linux" ]; then
+  if [ ! -x /usr/bin/getconf ]; then
+    echo "Error: could not find the program /usr/bin/getconf."
+    echo "Please install the glibc-common package."
+    # Assume NPTL.
+    exit 0
+  fi
+  libpthread_version="$(/usr/bin/getconf GNU_LIBPTHREAD_VERSION 2>/dev/null)"
+  if [ "${libpthread_version#NPTL}" != "${libpthread_version}" ]; then
+    # NPTL
+    exit 0
+  fi
+  # configuration string is empty or does start with "linuxthreads".
+  exit 1
+fi
+
+# Another OS than Linux, which is also fine.
+exit 0
diff --git a/drd/tests/supported_sem_init b/drd/tests/supported_sem_init
new file mode 100755
index 0000000..3b9f83a
--- /dev/null
+++ b/drd/tests/supported_sem_init
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# Exit with status 0 if the system this script runs on supports sem_init()
+# (Linux) and exit with status 1 if not (Darwin).
+
+[ "$(uname)" != "Darwin" ]
diff --git a/drd/tests/tc01_simple_race.stderr.exp b/drd/tests/tc01_simple_race.stderr.exp
new file mode 100644
index 0000000..2c21712
--- /dev/null
+++ b/drd/tests/tc01_simple_race.stderr.exp
@@ -0,0 +1,13 @@
+
+Conflicting load by thread 1 at 0x........ size 4
+   at 0x........: main (tc01_simple_race.c:28)
+Location 0x........ is 0 bytes inside global var "x"
+declared at tc01_simple_race.c:9
+
+Conflicting store by thread 1 at 0x........ size 4
+   at 0x........: main (tc01_simple_race.c:28)
+Location 0x........ is 0 bytes inside global var "x"
+declared at tc01_simple_race.c:9
+
+
+ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc01_simple_race.vgtest b/drd/tests/tc01_simple_race.vgtest
new file mode 100644
index 0000000..5ceb452
--- /dev/null
+++ b/drd/tests/tc01_simple_race.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread
+vgopts: --check-stack-var=yes --read-var-info=yes --show-confl-seg=no
+prog: ../../helgrind/tests/tc01_simple_race
diff --git a/drd/tests/tc02_simple_tls.stderr.exp b/drd/tests/tc02_simple_tls.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/tc02_simple_tls.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc02_simple_tls.vgtest b/drd/tests/tc02_simple_tls.vgtest
new file mode 100644
index 0000000..016d749
--- /dev/null
+++ b/drd/tests/tc02_simple_tls.vgtest
@@ -0,0 +1,2 @@
+prereq: ./supported_libpthread
+prog: ../../helgrind/tests/tc02_simple_tls
diff --git a/drd/tests/tc03_re_excl.stderr.exp b/drd/tests/tc03_re_excl.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/tc03_re_excl.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc03_re_excl.vgtest b/drd/tests/tc03_re_excl.vgtest
new file mode 100644
index 0000000..ee5f031
--- /dev/null
+++ b/drd/tests/tc03_re_excl.vgtest
@@ -0,0 +1,2 @@
+prereq: ./supported_libpthread
+prog: ../../helgrind/tests/tc03_re_excl
diff --git a/drd/tests/tc04_free_lock.stderr.exp b/drd/tests/tc04_free_lock.stderr.exp
new file mode 100644
index 0000000..8208334
--- /dev/null
+++ b/drd/tests/tc04_free_lock.stderr.exp
@@ -0,0 +1,34 @@
+
+Destroying locked mutex: mutex 0x........, recursion count 1, owner 1.
+   at 0x........: free (vg_replace_malloc.c:...)
+   by 0x........: main (tc04_free_lock.c:24)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc04_free_lock.c:20)
+
+Destroying locked mutex: mutex 0x........, recursion count 1, owner 1.
+   at 0x........: bar (tc04_free_lock.c:40)
+   by 0x........: main (tc04_free_lock.c:26)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_lock (drd_pthread_intercepts.c:?)
+   by 0x........: bar (tc04_free_lock.c:38)
+   by 0x........: main (tc04_free_lock.c:26)
+
+Destroying locked mutex: mutex 0x........, recursion count 1, owner 1.
+   at 0x........: foo (tc04_free_lock.c:49)
+   by 0x........: main (tc04_free_lock.c:27)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: foo (tc04_free_lock.c:46)
+   by 0x........: main (tc04_free_lock.c:27)
+
+Destroying locked mutex: mutex 0x........, recursion count 1, owner 1.
+   at 0x........: bar (tc04_free_lock.c:40)
+   by 0x........: main (tc04_free_lock.c:28)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_lock (drd_pthread_intercepts.c:?)
+   by 0x........: bar (tc04_free_lock.c:38)
+   by 0x........: main (tc04_free_lock.c:28)
+
+
+ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc04_free_lock.vgtest b/drd/tests/tc04_free_lock.vgtest
new file mode 100644
index 0000000..c8ae55c
--- /dev/null
+++ b/drd/tests/tc04_free_lock.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread
+vgopts: --check-stack-var=yes
+prog: ../../helgrind/tests/tc04_free_lock
diff --git a/drd/tests/tc05_simple_race.stderr.exp b/drd/tests/tc05_simple_race.stderr.exp
new file mode 100644
index 0000000..a2fd0a2
--- /dev/null
+++ b/drd/tests/tc05_simple_race.stderr.exp
@@ -0,0 +1 @@
+ERROR SUMMARY: 2 errors from 2 contexts
diff --git a/drd/tests/tc05_simple_race.vgtest b/drd/tests/tc05_simple_race.vgtest
new file mode 100644
index 0000000..fe34a1f
--- /dev/null
+++ b/drd/tests/tc05_simple_race.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread
+prog: ../../helgrind/tests/tc05_simple_race
+stderr_filter: filter_error_summary
diff --git a/drd/tests/tc06_two_races.stderr.exp b/drd/tests/tc06_two_races.stderr.exp
new file mode 100644
index 0000000..4cbed89
--- /dev/null
+++ b/drd/tests/tc06_two_races.stderr.exp
@@ -0,0 +1 @@
+ERROR SUMMARY: 4 errors from 4 contexts
diff --git a/drd/tests/tc06_two_races.vgtest b/drd/tests/tc06_two_races.vgtest
new file mode 100644
index 0000000..7f80dba
--- /dev/null
+++ b/drd/tests/tc06_two_races.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread
+prog: ../../helgrind/tests/tc06_two_races
+stderr_filter: filter_error_summary
diff --git a/drd/tests/tc07_hbl1.stderr.exp b/drd/tests/tc07_hbl1.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/tc07_hbl1.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc07_hbl1.stdout.exp b/drd/tests/tc07_hbl1.stdout.exp
new file mode 100644
index 0000000..407de30
--- /dev/null
+++ b/drd/tests/tc07_hbl1.stdout.exp
@@ -0,0 +1 @@
+x = 2
diff --git a/drd/tests/tc07_hbl1.vgtest b/drd/tests/tc07_hbl1.vgtest
new file mode 100644
index 0000000..b8eb639
--- /dev/null
+++ b/drd/tests/tc07_hbl1.vgtest
@@ -0,0 +1,2 @@
+prereq: ./supported_libpthread
+prog: ../../helgrind/tests/tc07_hbl1
diff --git a/drd/tests/tc08_hbl2.stderr.exp b/drd/tests/tc08_hbl2.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/tc08_hbl2.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc08_hbl2.stdout.exp b/drd/tests/tc08_hbl2.stdout.exp
new file mode 100644
index 0000000..ce39ad5
--- /dev/null
+++ b/drd/tests/tc08_hbl2.stdout.exp
@@ -0,0 +1,3 @@
+child: new value 6
+child: new value 10
+done, x = 10
diff --git a/drd/tests/tc08_hbl2.vgtest b/drd/tests/tc08_hbl2.vgtest
new file mode 100644
index 0000000..1ee1841
--- /dev/null
+++ b/drd/tests/tc08_hbl2.vgtest
@@ -0,0 +1,2 @@
+prereq: ./supported_libpthread
+prog: ../../helgrind/tests/tc08_hbl2
diff --git a/drd/tests/tc09_bad_unlock.stderr.exp b/drd/tests/tc09_bad_unlock.stderr.exp
new file mode 100644
index 0000000..7f8e2cc
--- /dev/null
+++ b/drd/tests/tc09_bad_unlock.stderr.exp
@@ -0,0 +1,59 @@
+
+Mutex not locked by calling thread: mutex 0x........, recursion count 0, owner 1.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: nearly_main (tc09_bad_unlock.c:27)
+   by 0x........: main (tc09_bad_unlock.c:49)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: nearly_main (tc09_bad_unlock.c:23)
+   by 0x........: main (tc09_bad_unlock.c:49)
+
+Thread 2:
+Mutex not locked by calling thread: mutex 0x........, recursion count 1, owner 1.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: child_fn (tc09_bad_unlock.c:11)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: nearly_main (tc09_bad_unlock.c:31)
+   by 0x........: main (tc09_bad_unlock.c:49)
+
+Thread 1:
+The object at address 0x........ is not a mutex.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: nearly_main (tc09_bad_unlock.c:41)
+   by 0x........: main (tc09_bad_unlock.c:49)
+
+Destroying locked mutex: mutex 0x........, recursion count 1, owner 1.
+   at 0x........: nearly_main (tc09_bad_unlock.c:45)
+   by 0x........: main (tc09_bad_unlock.c:49)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: nearly_main (tc09_bad_unlock.c:31)
+   by 0x........: main (tc09_bad_unlock.c:49)
+
+---------------------
+Mutex not locked by calling thread: mutex 0x........, recursion count 0, owner 1.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: nearly_main (tc09_bad_unlock.c:27)
+   by 0x........: main (tc09_bad_unlock.c:50)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: nearly_main (tc09_bad_unlock.c:23)
+   by 0x........: main (tc09_bad_unlock.c:50)
+
+The object at address 0x........ is not a mutex.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: nearly_main (tc09_bad_unlock.c:41)
+   by 0x........: main (tc09_bad_unlock.c:50)
+
+Destroying locked mutex: mutex 0x........, recursion count 1, owner 1.
+   at 0x........: nearly_main (tc09_bad_unlock.c:45)
+   by 0x........: main (tc09_bad_unlock.c:50)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: nearly_main (tc09_bad_unlock.c:31)
+   by 0x........: main (tc09_bad_unlock.c:50)
+
+
+ERROR SUMMARY: 8 errors from 7 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc09_bad_unlock.stderr.exp-glibc2.8 b/drd/tests/tc09_bad_unlock.stderr.exp-glibc2.8
new file mode 100644
index 0000000..277705a
--- /dev/null
+++ b/drd/tests/tc09_bad_unlock.stderr.exp-glibc2.8
@@ -0,0 +1,59 @@
+
+Mutex not locked by calling thread: mutex 0x........, recursion count 0, owner 1.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: nearly_main (tc09_bad_unlock.c:27)
+   by 0x........: main (tc09_bad_unlock.c:49)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: nearly_main (tc09_bad_unlock.c:23)
+   by 0x........: main (tc09_bad_unlock.c:49)
+
+Thread 2:
+Mutex not locked by calling thread: mutex 0x........, recursion count 1, owner 1.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: child_fn (tc09_bad_unlock.c:11)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: nearly_main (tc09_bad_unlock.c:31)
+   by 0x........: main (tc09_bad_unlock.c:49)
+
+Thread 1:
+The object at address 0x........ is not a mutex.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: nearly_main (tc09_bad_unlock.c:41)
+   by 0x........: main (tc09_bad_unlock.c:49)
+
+Destroying locked mutex: mutex 0x........, recursion count 1, owner 1.
+   at 0x........: nearly_main (tc09_bad_unlock.c:45)
+   by 0x........: (below main)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: nearly_main (tc09_bad_unlock.c:31)
+   by 0x........: main (tc09_bad_unlock.c:49)
+
+---------------------
+Mutex not locked by calling thread: mutex 0x........, recursion count 0, owner 1.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: nearly_main (tc09_bad_unlock.c:27)
+   by 0x........: main (tc09_bad_unlock.c:50)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: nearly_main (tc09_bad_unlock.c:23)
+   by 0x........: main (tc09_bad_unlock.c:50)
+
+The object at address 0x........ is not a mutex.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: nearly_main (tc09_bad_unlock.c:41)
+   by 0x........: main (tc09_bad_unlock.c:50)
+
+Destroying locked mutex: mutex 0x........, recursion count 1, owner 1.
+   at 0x........: nearly_main (tc09_bad_unlock.c:45)
+   by 0x........: (below main)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: nearly_main (tc09_bad_unlock.c:31)
+   by 0x........: main (tc09_bad_unlock.c:50)
+
+
+ERROR SUMMARY: 8 errors from 7 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc09_bad_unlock.vgtest b/drd/tests/tc09_bad_unlock.vgtest
new file mode 100644
index 0000000..abd97fa
--- /dev/null
+++ b/drd/tests/tc09_bad_unlock.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread
+vgopts: --check-stack-var=yes --num-callers=3
+prog: ../../helgrind/tests/tc09_bad_unlock
diff --git a/drd/tests/tc10_rec_lock.stderr.exp b/drd/tests/tc10_rec_lock.stderr.exp
new file mode 100644
index 0000000..a37bbd4
--- /dev/null
+++ b/drd/tests/tc10_rec_lock.stderr.exp
@@ -0,0 +1,19 @@
+
+before lock #1
+before lock #2
+before lock #3
+before unlock #1
+before unlock #2
+before unlock #3
+before unlock #4
+Mutex not locked by calling thread: mutex 0x........, recursion count 0, owner 1.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: nearly_main (tc10_rec_lock.c:42)
+   by 0x........: main (tc10_rec_lock.c:47)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: nearly_main (tc10_rec_lock.c:24)
+   by 0x........: main (tc10_rec_lock.c:47)
+
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc10_rec_lock.vgtest b/drd/tests/tc10_rec_lock.vgtest
new file mode 100644
index 0000000..af3582f
--- /dev/null
+++ b/drd/tests/tc10_rec_lock.vgtest
@@ -0,0 +1,2 @@
+prereq: ./supported_libpthread
+prog: ../../helgrind/tests/tc10_rec_lock
diff --git a/drd/tests/tc11_XCHG.stderr.exp b/drd/tests/tc11_XCHG.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/tc11_XCHG.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc11_XCHG.stdout.exp b/drd/tests/tc11_XCHG.stdout.exp
new file mode 100644
index 0000000..2e9ba47
--- /dev/null
+++ b/drd/tests/tc11_XCHG.stdout.exp
@@ -0,0 +1 @@
+success
diff --git a/drd/tests/tc11_XCHG.vgtest b/drd/tests/tc11_XCHG.vgtest
new file mode 100644
index 0000000..75e4cfc
--- /dev/null
+++ b/drd/tests/tc11_XCHG.vgtest
@@ -0,0 +1,2 @@
+prereq: ./supported_libpthread
+prog: ../../helgrind/tests/tc11_XCHG
diff --git a/drd/tests/tc12_rwl_trivial.stderr.exp b/drd/tests/tc12_rwl_trivial.stderr.exp
new file mode 100644
index 0000000..6ba7b18
--- /dev/null
+++ b/drd/tests/tc12_rwl_trivial.stderr.exp
@@ -0,0 +1,10 @@
+
+Reader-writer lock not locked by calling thread: rwlock 0x.........
+   at 0x........: pthread_rwlock_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc12_rwl_trivial.c:35)
+rwlock 0x........ was first observed at:
+   at 0x........: pthread_rwlock_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc12_rwl_trivial.c:24)
+
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc12_rwl_trivial.vgtest b/drd/tests/tc12_rwl_trivial.vgtest
new file mode 100644
index 0000000..0cb3825
--- /dev/null
+++ b/drd/tests/tc12_rwl_trivial.vgtest
@@ -0,0 +1,2 @@
+prereq: ./supported_libpthread
+prog: ../../helgrind/tests/tc12_rwl_trivial
diff --git a/drd/tests/tc13_laog1.stderr.exp b/drd/tests/tc13_laog1.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/tc13_laog1.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc13_laog1.vgtest b/drd/tests/tc13_laog1.vgtest
new file mode 100644
index 0000000..67bae56
--- /dev/null
+++ b/drd/tests/tc13_laog1.vgtest
@@ -0,0 +1,2 @@
+prereq: ./supported_libpthread
+prog: ../../helgrind/tests/tc13_laog1
diff --git a/drd/tests/tc15_laog_lockdel.stderr.exp b/drd/tests/tc15_laog_lockdel.stderr.exp
new file mode 100644
index 0000000..ac7a574
--- /dev/null
+++ b/drd/tests/tc15_laog_lockdel.stderr.exp
@@ -0,0 +1,8 @@
+
+Establish order 1 -> 2
+Try order 2 -> 1.  This gives an error.
+Free 2 and re-allocate it.  This gives it a new identity,
+so a second locking sequence 2 -> 1 should now be OK.
+done
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc15_laog_lockdel.vgtest b/drd/tests/tc15_laog_lockdel.vgtest
new file mode 100644
index 0000000..0bed938
--- /dev/null
+++ b/drd/tests/tc15_laog_lockdel.vgtest
@@ -0,0 +1,2 @@
+prereq: ./supported_libpthread
+prog: ../../helgrind/tests/tc15_laog_lockdel
diff --git a/drd/tests/tc16_byterace.stderr.exp b/drd/tests/tc16_byterace.stderr.exp
new file mode 100644
index 0000000..e9b2f84
--- /dev/null
+++ b/drd/tests/tc16_byterace.stderr.exp
@@ -0,0 +1,13 @@
+
+Conflicting load by thread 1 at 0x........ size 1
+   at 0x........: main (tc16_byterace.c:34)
+Location 0x........ is 0 bytes inside bytes[4],
+a global variable declared at tc16_byterace.c:7
+
+Conflicting store by thread 1 at 0x........ size 1
+   at 0x........: main (tc16_byterace.c:34)
+Location 0x........ is 0 bytes inside bytes[4],
+a global variable declared at tc16_byterace.c:7
+
+
+ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc16_byterace.vgtest b/drd/tests/tc16_byterace.vgtest
new file mode 100644
index 0000000..0c81ddd
--- /dev/null
+++ b/drd/tests/tc16_byterace.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread
+vgopts: --check-stack-var=yes --read-var-info=yes --show-confl-seg=no
+prog: ../../helgrind/tests/tc16_byterace
diff --git a/drd/tests/tc17_sembar.stderr.exp b/drd/tests/tc17_sembar.stderr.exp
new file mode 100644
index 0000000..b3f318e
--- /dev/null
+++ b/drd/tests/tc17_sembar.stderr.exp
@@ -0,0 +1,5 @@
+
+starting
+done, result is 88, should be 88
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc17_sembar.vgtest b/drd/tests/tc17_sembar.vgtest
new file mode 100644
index 0000000..8cede49
--- /dev/null
+++ b/drd/tests/tc17_sembar.vgtest
@@ -0,0 +1,2 @@
+prereq: ./supported_libpthread
+prog: ../../helgrind/tests/tc17_sembar
diff --git a/drd/tests/tc18_semabuse.stderr.exp b/drd/tests/tc18_semabuse.stderr.exp
new file mode 100644
index 0000000..6c8c45b
--- /dev/null
+++ b/drd/tests/tc18_semabuse.stderr.exp
@@ -0,0 +1,17 @@
+
+Semaphore reinitialization: semaphore 0x........
+   at 0x........: sem_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc18_semabuse.c:26)
+semaphore 0x........ was first observed at:
+   at 0x........: sem_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc18_semabuse.c:23)
+
+Invalid semaphore: semaphore 0x........
+   at 0x........: sem_wait (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc18_semabuse.c:34)
+semaphore 0x........ was first observed at:
+   at 0x........: sem_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc18_semabuse.c:23)
+
+
+ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc18_semabuse.vgtest b/drd/tests/tc18_semabuse.vgtest
new file mode 100644
index 0000000..3cde116
--- /dev/null
+++ b/drd/tests/tc18_semabuse.vgtest
@@ -0,0 +1,2 @@
+prereq: ./supported_libpthread && ./supported_sem_init
+prog: ../../helgrind/tests/tc18_semabuse
diff --git a/drd/tests/tc19_shadowmem.stderr.exp-32bit b/drd/tests/tc19_shadowmem.stderr.exp-32bit
new file mode 100644
index 0000000..84367d8
--- /dev/null
+++ b/drd/tests/tc19_shadowmem.stderr.exp-32bit
@@ -0,0 +1,4224 @@
+
+
+===========================================================
+=== 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 ===
+===========================================================
+
+---------- char gran, 0 .. 99, skip 0 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:288)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 0 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 1 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:290)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 1 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 2 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:292)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 2 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 3 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:294)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 3 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 4 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:296)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 4 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 5 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:298)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 5 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 6 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:300)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 6 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 7 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:302)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 7 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 8 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:304)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 8 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 9 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:306)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 9 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 10 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:308)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 10 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 11 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:310)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 11 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 12 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:312)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 12 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 13 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:314)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 13 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 14 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:316)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 14 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 15 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:318)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 15 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 16 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:320)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 16 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 17 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:322)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 17 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 18 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:324)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 18 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 19 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:326)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 19 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 20 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:328)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 20 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 21 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:330)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 21 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 22 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:332)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 22 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 23 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:334)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 23 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 24 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:336)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 24 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 25 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:338)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 25 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 26 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:340)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 26 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 27 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:342)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 27 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 28 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:344)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 28 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 29 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:346)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 29 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 30 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:348)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 30 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 31 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:350)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 31 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 32 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:352)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 32 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 33 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:354)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 33 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 34 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:356)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 34 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 35 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:358)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 35 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 36 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:360)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 36 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 37 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:362)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 37 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 38 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:364)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 38 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 39 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:366)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 39 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 40 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:368)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 40 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 41 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:370)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 41 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 42 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:372)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 42 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 43 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:374)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 43 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 44 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:376)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 44 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 45 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:378)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 45 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 46 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:380)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 46 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 47 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:382)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 47 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 48 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:384)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 48 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 49 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:386)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 49 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 50 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:388)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 50 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 51 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:390)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 51 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 52 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:392)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 52 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 53 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:394)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 53 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 54 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:396)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 54 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 55 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:398)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 55 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 56 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:400)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 56 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 57 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:402)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 57 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 58 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:404)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 58 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 59 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:406)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 59 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 60 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:408)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 60 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 61 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:410)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 61 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 62 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:412)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 62 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 63 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:414)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 63 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 64 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:416)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 64 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 65 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:418)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 65 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 66 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:420)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 66 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 67 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:422)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 67 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 68 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:424)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 68 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 69 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:426)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 69 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 70 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:428)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 70 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 71 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:430)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 71 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 72 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:432)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 72 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 73 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:434)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 73 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 74 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:436)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 74 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 75 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:438)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 75 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 76 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:440)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 76 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 77 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:442)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 77 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 78 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:444)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 78 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 79 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:446)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 79 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 80 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:448)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 80 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 81 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:450)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 81 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 82 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:452)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 82 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 83 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:454)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 83 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 84 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:456)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 84 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 85 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:458)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 85 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 86 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:460)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 86 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 87 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:462)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 87 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 88 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:464)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 88 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 89 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:466)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 89 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 90 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:468)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 90 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 91 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:470)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 91 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 92 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:472)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 92 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 93 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:474)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 93 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 94 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:476)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 94 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 95 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:478)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 95 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 96 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:480)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 96 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 97 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:482)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 97 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 98 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:484)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 98 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+
+==========================================================
+=== 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 ===
+==========================================================
+
+---------- short gran, 0 .. 98, skip 0 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:288)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 0 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 1 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:290)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 1 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 2 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:292)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 2 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 3 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:294)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 3 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 4 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:296)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 4 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 5 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:298)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 5 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 6 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:300)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 6 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 7 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:302)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 7 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 8 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:304)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 8 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 9 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:306)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 9 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 10 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:308)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 10 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 11 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:310)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 11 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 12 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:312)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 12 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 13 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:314)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 13 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 14 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:316)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 14 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 15 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:318)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 15 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 16 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:320)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 16 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 17 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:322)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 17 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 18 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:324)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 18 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 19 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:326)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 19 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 20 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:328)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 20 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 21 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:330)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 21 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 22 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:332)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 22 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 23 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:334)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 23 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 24 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:336)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 24 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 25 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:338)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 25 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 26 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:340)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 26 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 27 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:342)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 27 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 28 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:344)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 28 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 29 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:346)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 29 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 30 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:348)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 30 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 31 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:350)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 31 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 32 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:352)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 32 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 33 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:354)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 33 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 34 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:356)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 34 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 35 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:358)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 35 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 36 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:360)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 36 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 37 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:362)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 37 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 38 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:364)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 38 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 39 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:366)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 39 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 40 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:368)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 40 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 41 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:370)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 41 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 42 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:372)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 42 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 43 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:374)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 43 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 44 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:376)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 44 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 45 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:378)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 45 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 46 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:380)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 46 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 47 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:382)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 47 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 48 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:384)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 48 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 49 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:386)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 49 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 50 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:388)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 50 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 51 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:390)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 51 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 52 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:392)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 52 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 53 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:394)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 53 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 54 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:396)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 54 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 55 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:398)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 55 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 56 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:400)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 56 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 57 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:402)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 57 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 58 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:404)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 58 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 59 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:406)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 59 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 60 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:408)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 60 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 61 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:410)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 61 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 62 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:412)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 62 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 63 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:414)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 63 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 64 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:416)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 64 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 65 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:418)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 65 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 66 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:420)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 66 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 67 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:422)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 67 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 68 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:424)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 68 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 69 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:426)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 69 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 70 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:428)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 70 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 71 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:430)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 71 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 72 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:432)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 72 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 73 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:434)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 73 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 74 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:436)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 74 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 75 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:438)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 75 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 76 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:440)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 76 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 77 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:442)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 77 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 78 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:444)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 78 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 79 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:446)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 79 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 80 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:448)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 80 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 81 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:450)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 81 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 82 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:452)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 82 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 83 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:454)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 83 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 84 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:456)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 84 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 85 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:458)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 85 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 86 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:460)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 86 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 87 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:462)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 87 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 88 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:464)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 88 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 89 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:466)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 89 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 90 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:468)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 90 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 91 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:470)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 91 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 92 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:472)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 92 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 93 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:474)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 93 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 94 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:476)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 94 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 95 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:478)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 95 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 96 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:480)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 96 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 97 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:482)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 97 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+
+==========================================================
+=== 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 ===
+==========================================================
+
+---------- int gran, 0 .. 96, skip 0 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:288)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 0 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 1 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:290)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 1 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 2 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:292)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 2 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 3 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:294)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 3 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 4 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:296)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 4 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 5 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:298)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 5 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 6 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:300)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 6 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 7 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:302)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 7 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 8 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:304)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 8 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 9 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:306)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 9 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 10 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:308)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 10 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 11 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:310)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 11 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 12 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:312)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 12 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 13 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:314)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 13 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 14 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:316)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 14 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 15 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:318)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 15 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 16 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:320)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 16 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 17 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:322)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 17 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 18 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:324)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 18 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 19 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:326)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 19 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 20 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:328)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 20 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 21 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:330)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 21 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 22 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:332)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 22 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 23 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:334)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 23 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 24 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:336)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 24 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 25 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:338)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 25 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 26 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:340)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 26 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 27 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:342)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 27 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 28 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:344)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 28 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 29 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:346)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 29 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 30 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:348)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 30 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 31 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:350)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 31 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 32 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:352)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 32 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 33 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:354)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 33 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 34 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:356)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 34 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 35 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:358)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 35 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 36 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:360)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 36 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 37 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:362)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 37 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 38 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:364)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 38 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 39 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:366)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 39 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 40 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:368)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 40 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 41 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:370)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 41 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 42 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:372)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 42 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 43 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:374)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 43 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 44 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:376)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 44 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 45 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:378)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 45 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 46 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:380)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 46 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 47 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:382)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 47 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 48 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:384)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 48 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 49 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:386)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 49 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 50 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:388)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 50 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 51 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:390)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 51 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 52 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:392)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 52 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 53 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:394)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 53 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 54 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:396)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 54 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 55 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:398)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 55 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 56 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:400)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 56 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 57 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:402)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 57 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 58 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:404)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 58 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 59 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:406)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 59 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 60 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:408)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 60 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 61 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:410)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 61 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 62 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:412)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 62 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 63 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:414)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 63 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 64 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:416)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 64 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 65 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:418)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 65 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 66 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:420)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 66 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 67 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:422)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 67 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 68 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:424)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 68 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 69 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:426)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 69 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 70 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:428)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 70 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 71 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:430)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 71 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 72 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:432)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 72 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 73 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:434)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 73 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 74 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:436)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 74 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 75 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:438)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 75 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 76 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:440)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 76 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 77 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:442)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 77 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 78 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:444)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 78 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 79 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:446)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 79 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 80 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:448)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 80 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 81 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:450)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 81 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 82 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:452)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 82 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 83 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:454)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 83 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 84 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:456)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 84 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 85 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:458)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 85 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 86 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:460)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 86 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 87 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:462)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 87 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 88 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:464)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 88 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 89 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:466)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 89 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 90 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:468)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 90 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 91 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:470)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 91 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 92 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:472)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 92 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 93 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:474)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 93 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 94 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:476)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 94 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 95 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:478)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 95 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+
+==========================================================
+=== 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 ===
+==========================================================
+
+---------- double gran, 0 .. 92, skip 0 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:288)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 0 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:288)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 4 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 1 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:290)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 1 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:290)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 5 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 2 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:292)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 2 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:292)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 6 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 3 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:294)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 3 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:294)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 7 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 4 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:296)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 4 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:296)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 8 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 5 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:298)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 5 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:298)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 9 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 6 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:300)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 6 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:300)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 10 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 7 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:302)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 7 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:302)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 11 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 8 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:304)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 8 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:304)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 12 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 9 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:306)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 9 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:306)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 13 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 10 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:308)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 10 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:308)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 14 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 11 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:310)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 11 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:310)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 15 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 12 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:312)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 12 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:312)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 16 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 13 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:314)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 13 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:314)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 17 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 14 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:316)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 14 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:316)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 18 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 15 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:318)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 15 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:318)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 19 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 16 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:320)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 16 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:320)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 20 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 17 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:322)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 17 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:322)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 21 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 18 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:324)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 18 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:324)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 22 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 19 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:326)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 19 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:326)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 23 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 20 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:328)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 20 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:328)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 24 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 21 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:330)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 21 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:330)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 25 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 22 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:332)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 22 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:332)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 26 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 23 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:334)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 23 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:334)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 27 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 24 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:336)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 24 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:336)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 28 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 25 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:338)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 25 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:338)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 29 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 26 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:340)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 26 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:340)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 30 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 27 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:342)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 27 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:342)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 31 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 28 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:344)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 28 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:344)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 32 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 29 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:346)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 29 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:346)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 33 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 30 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:348)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 30 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:348)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 34 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 31 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:350)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 31 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:350)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 35 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 32 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:352)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 32 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:352)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 36 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 33 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:354)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 33 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:354)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 37 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 34 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:356)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 34 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:356)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 38 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 35 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:358)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 35 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:358)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 39 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 36 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:360)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 36 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:360)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 40 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 37 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:362)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 37 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:362)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 41 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 38 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:364)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 38 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:364)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 42 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 39 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:366)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 39 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:366)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 43 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 40 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:368)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 40 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:368)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 44 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 41 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:370)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 41 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:370)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 45 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 42 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:372)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 42 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:372)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 46 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 43 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:374)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 43 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:374)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 47 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 44 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:376)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 44 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:376)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 48 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 45 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:378)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 45 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:378)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 49 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 46 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:380)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 46 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:380)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 50 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 47 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:382)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 47 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:382)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 51 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 48 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:384)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 48 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:384)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 52 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 49 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:386)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 49 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:386)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 53 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 50 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:388)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 50 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:388)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 54 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 51 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:390)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 51 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:390)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 55 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 52 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:392)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 52 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:392)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 56 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 53 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:394)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 53 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:394)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 57 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 54 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:396)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 54 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:396)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 58 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 55 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:398)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 55 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:398)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 59 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 56 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:400)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 56 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:400)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 60 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 57 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:402)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 57 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:402)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 61 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 58 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:404)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 58 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:404)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 62 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 59 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:406)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 59 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:406)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 63 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 60 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:408)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 60 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:408)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 64 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 61 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:410)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 61 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:410)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 65 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 62 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:412)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 62 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:412)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 66 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 63 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:414)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 63 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:414)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 67 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 64 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:416)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 64 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:416)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 68 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 65 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:418)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 65 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:418)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 69 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 66 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:420)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 66 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:420)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 70 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 67 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:422)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 67 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:422)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 71 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 68 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:424)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 68 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:424)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 72 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 69 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:426)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 69 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:426)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 73 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 70 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:428)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 70 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:428)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 74 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 71 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:430)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 71 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:430)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 75 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 72 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:432)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 72 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:432)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 76 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 73 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:434)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 73 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:434)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 77 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 74 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:436)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 74 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:436)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 78 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 75 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:438)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 75 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:438)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 79 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 76 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:440)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 76 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:440)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 80 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 77 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:442)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 77 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:442)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 81 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 78 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:444)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 78 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:444)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 82 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 79 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:446)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 79 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:446)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 83 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 80 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:448)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 80 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:448)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 84 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 81 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:450)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 81 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:450)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 85 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 82 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:452)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 82 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:452)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 86 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 83 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:454)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 83 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:454)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 87 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 84 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:456)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 84 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:456)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 88 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 85 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:458)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 85 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:458)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 89 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 86 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:460)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 86 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:460)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 90 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 87 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:462)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 87 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:462)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 91 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 88 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:464)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 88 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:464)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 92 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 89 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:466)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 89 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:466)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 93 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 90 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:468)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 90 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:468)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 94 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 91 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:470)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 91 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:470)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 95 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+
+ERROR SUMMARY: 477 errors from 477 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc19_shadowmem.stderr.exp-64bit b/drd/tests/tc19_shadowmem.stderr.exp-64bit
new file mode 100644
index 0000000..4fbbfaa
--- /dev/null
+++ b/drd/tests/tc19_shadowmem.stderr.exp-64bit
@@ -0,0 +1,3488 @@
+
+
+===========================================================
+=== 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 ===
+===========================================================
+
+---------- char gran, 0 .. 99, skip 0 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:288)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 0 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 1 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:290)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 1 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 2 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:292)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 2 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 3 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:294)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 3 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 4 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:296)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 4 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 5 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:298)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 5 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 6 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:300)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 6 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 7 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:302)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 7 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 8 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:304)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 8 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 9 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:306)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 9 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 10 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:308)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 10 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 11 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:310)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 11 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 12 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:312)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 12 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 13 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:314)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 13 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 14 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:316)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 14 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 15 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:318)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 15 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 16 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:320)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 16 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 17 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:322)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 17 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 18 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:324)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 18 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 19 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:326)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 19 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 20 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:328)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 20 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 21 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:330)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 21 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 22 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:332)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 22 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 23 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:334)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 23 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 24 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:336)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 24 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 25 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:338)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 25 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 26 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:340)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 26 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 27 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:342)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 27 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 28 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:344)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 28 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 29 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:346)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 29 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 30 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:348)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 30 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 31 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:350)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 31 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 32 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:352)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 32 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 33 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:354)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 33 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 34 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:356)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 34 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 35 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:358)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 35 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 36 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:360)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 36 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 37 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:362)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 37 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 38 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:364)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 38 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 39 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:366)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 39 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 40 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:368)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 40 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 41 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:370)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 41 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 42 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:372)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 42 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 43 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:374)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 43 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 44 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:376)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 44 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 45 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:378)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 45 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 46 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:380)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 46 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 47 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:382)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 47 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 48 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:384)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 48 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 49 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:386)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 49 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 50 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:388)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 50 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 51 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:390)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 51 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 52 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:392)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 52 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 53 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:394)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 53 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 54 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:396)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 54 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 55 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:398)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 55 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 56 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:400)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 56 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 57 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:402)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 57 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 58 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:404)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 58 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 59 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:406)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 59 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 60 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:408)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 60 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 61 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:410)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 61 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 62 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:412)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 62 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 63 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:414)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 63 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 64 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:416)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 64 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 65 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:418)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 65 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 66 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:420)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 66 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 67 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:422)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 67 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 68 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:424)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 68 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 69 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:426)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 69 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 70 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:428)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 70 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 71 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:430)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 71 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 72 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:432)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 72 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 73 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:434)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 73 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 74 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:436)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 74 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 75 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:438)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 75 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 76 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:440)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 76 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 77 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:442)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 77 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 78 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:444)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 78 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 79 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:446)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 79 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 80 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:448)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 80 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 81 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:450)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 81 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 82 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:452)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 82 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 83 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:454)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 83 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 84 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:456)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 84 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 85 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:458)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 85 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 86 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:460)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 86 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 87 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:462)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 87 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 88 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:464)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 88 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 89 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:466)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 89 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 90 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:468)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 90 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 91 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:470)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 91 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 92 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:472)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 92 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 93 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:474)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 93 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 94 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:476)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 94 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 95 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:478)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 95 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 96 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:480)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 96 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 97 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:482)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 97 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- char gran, 0 .. 99, skip 98 ----------
+Conflicting store by thread x at 0x........ size 1
+   at 0x........: child8 (tc19_shadowmem.c:33)
+   by 0x........: steer (tc19_shadowmem.c:484)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 98 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+
+==========================================================
+=== 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 ===
+==========================================================
+
+---------- short gran, 0 .. 98, skip 0 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:288)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 0 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 1 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:290)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 1 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 2 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:292)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 2 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 3 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:294)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 3 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 4 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:296)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 4 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 5 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:298)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 5 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 6 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:300)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 6 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 7 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:302)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 7 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 8 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:304)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 8 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 9 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:306)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 9 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 10 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:308)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 10 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 11 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:310)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 11 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 12 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:312)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 12 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 13 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:314)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 13 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 14 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:316)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 14 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 15 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:318)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 15 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 16 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:320)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 16 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 17 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:322)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 17 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 18 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:324)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 18 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 19 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:326)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 19 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 20 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:328)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 20 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 21 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:330)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 21 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 22 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:332)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 22 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 23 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:334)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 23 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 24 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:336)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 24 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 25 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:338)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 25 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 26 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:340)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 26 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 27 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:342)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 27 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 28 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:344)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 28 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 29 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:346)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 29 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 30 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:348)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 30 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 31 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:350)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 31 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 32 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:352)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 32 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 33 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:354)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 33 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 34 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:356)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 34 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 35 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:358)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 35 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 36 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:360)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 36 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 37 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:362)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 37 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 38 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:364)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 38 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 39 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:366)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 39 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 40 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:368)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 40 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 41 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:370)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 41 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 42 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:372)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 42 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 43 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:374)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 43 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 44 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:376)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 44 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 45 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:378)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 45 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 46 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:380)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 46 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 47 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:382)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 47 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 48 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:384)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 48 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 49 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:386)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 49 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 50 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:388)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 50 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 51 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:390)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 51 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 52 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:392)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 52 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 53 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:394)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 53 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 54 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:396)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 54 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 55 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:398)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 55 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 56 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:400)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 56 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 57 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:402)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 57 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 58 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:404)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 58 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 59 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:406)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 59 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 60 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:408)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 60 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 61 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:410)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 61 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 62 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:412)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 62 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 63 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:414)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 63 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 64 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:416)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 64 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 65 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:418)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 65 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 66 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:420)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 66 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 67 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:422)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 67 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 68 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:424)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 68 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 69 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:426)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 69 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 70 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:428)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 70 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 71 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:430)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 71 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 72 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:432)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 72 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 73 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:434)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 73 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 74 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:436)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 74 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 75 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:438)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 75 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 76 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:440)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 76 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 77 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:442)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 77 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 78 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:444)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 78 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 79 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:446)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 79 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 80 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:448)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 80 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 81 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:450)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 81 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 82 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:452)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 82 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 83 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:454)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 83 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 84 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:456)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 84 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 85 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:458)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 85 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 86 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:460)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 86 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 87 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:462)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 87 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 88 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:464)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 88 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 89 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:466)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 89 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 90 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:468)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 90 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 91 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:470)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 91 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 92 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:472)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 92 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 93 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:474)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 93 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 94 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:476)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 94 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 95 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:478)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 95 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 0 .. 98, skip 96 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:480)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 96 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- short gran, 1 .. 98, skip 97 ----------
+Conflicting store by thread x at 0x........ size 2
+   at 0x........: child16 (tc19_shadowmem.c:57)
+   by 0x........: steer (tc19_shadowmem.c:482)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 97 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+
+==========================================================
+=== 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 ===
+==========================================================
+
+---------- int gran, 0 .. 96, skip 0 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:288)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 0 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 1 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:290)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 1 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 2 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:292)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 2 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 3 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:294)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 3 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 4 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:296)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 4 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 5 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:298)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 5 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 6 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:300)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 6 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 7 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:302)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 7 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 8 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:304)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 8 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 9 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:306)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 9 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 10 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:308)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 10 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 11 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:310)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 11 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 12 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:312)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 12 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 13 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:314)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 13 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 14 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:316)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 14 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 15 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:318)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 15 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 16 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:320)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 16 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 17 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:322)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 17 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 18 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:324)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 18 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 19 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:326)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 19 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 20 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:328)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 20 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 21 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:330)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 21 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 22 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:332)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 22 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 23 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:334)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 23 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 24 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:336)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 24 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 25 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:338)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 25 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 26 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:340)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 26 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 27 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:342)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 27 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 28 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:344)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 28 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 29 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:346)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 29 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 30 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:348)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 30 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 31 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:350)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 31 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 32 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:352)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 32 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 33 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:354)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 33 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 34 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:356)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 34 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 35 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:358)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 35 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 36 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:360)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 36 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 37 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:362)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 37 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 38 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:364)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 38 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 39 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:366)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 39 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 40 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:368)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 40 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 41 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:370)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 41 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 42 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:372)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 42 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 43 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:374)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 43 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 44 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:376)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 44 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 45 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:378)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 45 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 46 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:380)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 46 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 47 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:382)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 47 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 48 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:384)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 48 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 49 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:386)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 49 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 50 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:388)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 50 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 51 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:390)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 51 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 52 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:392)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 52 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 53 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:394)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 53 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 54 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:396)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 54 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 55 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:398)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 55 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 56 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:400)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 56 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 57 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:402)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 57 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 58 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:404)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 58 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 59 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:406)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 59 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 60 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:408)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 60 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 61 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:410)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 61 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 62 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:412)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 62 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 63 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:414)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 63 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 64 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:416)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 64 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 65 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:418)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 65 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 66 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:420)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 66 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 67 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:422)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 67 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 68 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:424)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 68 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 69 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:426)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 69 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 70 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:428)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 70 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 71 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:430)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 71 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 72 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:432)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 72 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 73 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:434)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 73 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 74 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:436)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 74 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 75 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:438)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 75 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 76 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:440)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 76 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 77 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:442)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 77 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 78 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:444)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 78 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 79 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:446)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 79 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 80 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:448)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 80 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 81 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:450)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 81 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 82 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:452)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 82 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 83 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:454)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 83 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 84 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:456)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 84 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 85 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:458)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 85 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 86 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:460)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 86 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 87 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:462)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 87 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 88 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:464)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 88 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 89 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:466)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 89 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 90 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:468)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 90 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 91 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:470)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 91 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 0 .. 96, skip 92 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:472)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 92 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 1 .. 96, skip 93 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:474)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 93 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 2 .. 96, skip 94 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:476)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 94 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- int gran, 3 .. 96, skip 95 ----------
+Conflicting store by thread x at 0x........ size 4
+   at 0x........: child32 (tc19_shadowmem.c:81)
+   by 0x........: steer (tc19_shadowmem.c:478)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 95 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+
+==========================================================
+=== 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 ===
+==========================================================
+
+---------- double gran, 0 .. 92, skip 0 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:288)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 0 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 1 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:290)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 1 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 2 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:292)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 2 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 3 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:294)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 3 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 4 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:296)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 4 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 5 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:298)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 5 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 6 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:300)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 6 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 7 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:302)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 7 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 8 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:304)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 8 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 9 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:306)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 9 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 10 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:308)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 10 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 11 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:310)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 11 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 12 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:312)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 12 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 13 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:314)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 13 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 14 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:316)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 14 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 15 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:318)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 15 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 16 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:320)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 16 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 17 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:322)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 17 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 18 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:324)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 18 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 19 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:326)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 19 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 20 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:328)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 20 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 21 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:330)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 21 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 22 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:332)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 22 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 23 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:334)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 23 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 24 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:336)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 24 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 25 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:338)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 25 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 26 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:340)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 26 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 27 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:342)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 27 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 28 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:344)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 28 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 29 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:346)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 29 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 30 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:348)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 30 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 31 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:350)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 31 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 32 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:352)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 32 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 33 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:354)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 33 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 34 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:356)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 34 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 35 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:358)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 35 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 36 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:360)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 36 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 37 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:362)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 37 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 38 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:364)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 38 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 39 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:366)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 39 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 40 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:368)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 40 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 41 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:370)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 41 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 42 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:372)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 42 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 43 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:374)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 43 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 44 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:376)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 44 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 45 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:378)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 45 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 46 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:380)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 46 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 47 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:382)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 47 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 48 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:384)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 48 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 49 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:386)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 49 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 50 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:388)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 50 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 51 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:390)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 51 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 52 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:392)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 52 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 53 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:394)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 53 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 54 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:396)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 54 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 55 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:398)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 55 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 56 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:400)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 56 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 57 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:402)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 57 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 58 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:404)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 58 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 59 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:406)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 59 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 60 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:408)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 60 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 61 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:410)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 61 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 62 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:412)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 62 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 63 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:414)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 63 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 64 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:416)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 64 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 65 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:418)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 65 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 66 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:420)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 66 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 67 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:422)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 67 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 68 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:424)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 68 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 69 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:426)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 69 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 70 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:428)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 70 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 71 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:430)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 71 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 72 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:432)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 72 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 73 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:434)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 73 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 74 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:436)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 74 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 75 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:438)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 75 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 76 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:440)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 76 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 77 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:442)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 77 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 78 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:444)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 78 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 79 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:446)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 79 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 80 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:448)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 80 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 81 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:450)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 81 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 82 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:452)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 82 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 83 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:454)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 83 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 4 .. 92, skip 84 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:456)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 84 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 5 .. 92, skip 85 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:458)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 85 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 6 .. 92, skip 86 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:460)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 86 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 7 .. 92, skip 87 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:462)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 87 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 0 .. 92, skip 88 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:464)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 88 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 1 .. 92, skip 89 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:466)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 89 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 2 .. 92, skip 90 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:468)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 90 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+---------- double gran, 3 .. 92, skip 91 ----------
+Conflicting store by thread x at 0x........ size 8
+   at 0x........: child64 (tc19_shadowmem.c:105)
+   by 0x........: steer (tc19_shadowmem.c:470)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+Address 0x........ is at offset 91 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (tc19_shadowmem.c:144)
+
+
+ERROR SUMMARY: 385 errors from 385 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc19_shadowmem.vgtest b/drd/tests/tc19_shadowmem.vgtest
new file mode 100644
index 0000000..cf2542d
--- /dev/null
+++ b/drd/tests/tc19_shadowmem.vgtest
@@ -0,0 +1,4 @@
+prereq: ./supported_libpthread
+prog: ../../helgrind/tests/tc19_shadowmem
+vgopts: --error-limit=no --read-var-info=yes --show-confl-seg=no --num-callers=3
+stderr_filter: filter_stderr_and_thread_no
diff --git a/drd/tests/tc21_pthonce.stderr.exp b/drd/tests/tc21_pthonce.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/tc21_pthonce.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc21_pthonce.stdout.exp b/drd/tests/tc21_pthonce.stdout.exp
new file mode 100644
index 0000000..e6c2dc2
--- /dev/null
+++ b/drd/tests/tc21_pthonce.stdout.exp
@@ -0,0 +1,4 @@
+welcome: Welcome
+child: Hi, I'm thread 0
+child: Hi, I'm thread 1
+main: Goodbye
diff --git a/drd/tests/tc21_pthonce.vgtest b/drd/tests/tc21_pthonce.vgtest
new file mode 100644
index 0000000..b9fa8f7
--- /dev/null
+++ b/drd/tests/tc21_pthonce.vgtest
@@ -0,0 +1,2 @@
+prereq: ./supported_libpthread
+prog: ../../helgrind/tests/tc21_pthonce
diff --git a/drd/tests/tc22_exit_w_lock.stderr.exp-32bit b/drd/tests/tc22_exit_w_lock.stderr.exp-32bit
new file mode 100644
index 0000000..b4e5b2c
--- /dev/null
+++ b/drd/tests/tc22_exit_w_lock.stderr.exp-32bit
@@ -0,0 +1,139 @@
+
+Conflicting load by thread 1 at 0x........ size 4
+   at 0x........: __deallocate_stack (in libpthread-?.?.so)
+   by 0x........: __free_tcb (in libpthread-?.?.so)
+   by 0x........: pthread_join (in libpthread-?.?.so)
+   by 0x........: pthread_join (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc22_exit_w_lock.c:43)
+Allocation context: stack_cache_lock (offset 0, size 4) in libpthread-?.?.so, libpthread.so.0:BSS
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+Conflicting store by thread 1 at 0x........ size 4
+   at 0x........: __deallocate_stack (in libpthread-?.?.so)
+   by 0x........: __free_tcb (in libpthread-?.?.so)
+   by 0x........: pthread_join (in libpthread-?.?.so)
+   by 0x........: pthread_join (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc22_exit_w_lock.c:43)
+Allocation context: stack_cache_lock (offset 0, size 4) in libpthread-?.?.so, libpthread.so.0:BSS
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+Conflicting store by thread 1 at 0x........ size 4
+   at 0x........: __deallocate_stack (in libpthread-?.?.so)
+   by 0x........: __free_tcb (in libpthread-?.?.so)
+   by 0x........: pthread_join (in libpthread-?.?.so)
+   by 0x........: pthread_join (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc22_exit_w_lock.c:43)
+Allocation context: stack_used (offset 4, size 8) in libpthread-?.?.so, libpthread.so.0:Data
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+Conflicting store by thread 1 at 0x........ size 4
+   at 0x........: __deallocate_stack (in libpthread-?.?.so)
+   by 0x........: __free_tcb (in libpthread-?.?.so)
+   by 0x........: pthread_join (in libpthread-?.?.so)
+   by 0x........: pthread_join (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc22_exit_w_lock.c:43)
+Allocation context: stack_used (offset 0, size 8) in libpthread-?.?.so, libpthread.so.0:Data
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+Conflicting load by thread 1 at 0x........ size 4
+   at 0x........: __deallocate_stack (in libpthread-?.?.so)
+   by 0x........: __free_tcb (in libpthread-?.?.so)
+   by 0x........: pthread_join (in libpthread-?.?.so)
+   by 0x........: pthread_join (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc22_exit_w_lock.c:43)
+Allocation context: stack_cache (offset 0, size 8) in libpthread-?.?.so, libpthread.so.0:Data
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+Conflicting store by thread 1 at 0x........ size 4
+   at 0x........: __deallocate_stack (in libpthread-?.?.so)
+   by 0x........: __free_tcb (in libpthread-?.?.so)
+   by 0x........: pthread_join (in libpthread-?.?.so)
+   by 0x........: pthread_join (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc22_exit_w_lock.c:43)
+Allocation context: stack_cache (offset 4, size 8) in libpthread-?.?.so, libpthread.so.0:Data
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+Conflicting load by thread 1 at 0x........ size 4
+   at 0x........: __deallocate_stack (in libpthread-?.?.so)
+   by 0x........: __free_tcb (in libpthread-?.?.so)
+   by 0x........: pthread_join (in libpthread-?.?.so)
+   by 0x........: pthread_join (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc22_exit_w_lock.c:43)
+Allocation context: stack_cache_actsize (offset 0, size 4) in libpthread-?.?.so, libpthread.so.0:BSS
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+Conflicting store by thread 1 at 0x........ size 4
+   at 0x........: __deallocate_stack (in libpthread-?.?.so)
+   by 0x........: __free_tcb (in libpthread-?.?.so)
+   by 0x........: pthread_join (in libpthread-?.?.so)
+   by 0x........: pthread_join (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc22_exit_w_lock.c:43)
+Allocation context: stack_cache (offset 0, size 8) in libpthread-?.?.so, libpthread.so.0:Data
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+Conflicting store by thread 1 at 0x........ size 4
+   at 0x........: __deallocate_stack (in libpthread-?.?.so)
+   by 0x........: __free_tcb (in libpthread-?.?.so)
+   by 0x........: pthread_join (in libpthread-?.?.so)
+   by 0x........: pthread_join (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc22_exit_w_lock.c:43)
+Allocation context: stack_cache_actsize (offset 0, size 4) in libpthread-?.?.so, libpthread.so.0:BSS
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+Conflicting load by thread 1 at 0x........ size 4
+   at 0x........: __deallocate_stack (in libpthread-?.?.so)
+   by 0x........: __free_tcb (in libpthread-?.?.so)
+   by 0x........: pthread_join (in libpthread-?.?.so)
+   by 0x........: pthread_join (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc22_exit_w_lock.c:43)
+Allocation context: stack_cache_lock (offset 0, size 4) in libpthread-?.?.so, libpthread.so.0:BSS
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+Conflicting store by thread 1 at 0x........ size 4
+   at 0x........: __deallocate_stack (in libpthread-?.?.so)
+   by 0x........: __free_tcb (in libpthread-?.?.so)
+   by 0x........: pthread_join (in libpthread-?.?.so)
+   by 0x........: pthread_join (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc22_exit_w_lock.c:43)
+Allocation context: stack_cache_lock (offset 0, size 4) in libpthread-?.?.so, libpthread.so.0:BSS
+Other segment start (thread 2)
+   (thread finished, call stack no longer available)
+Other segment end (thread 2)
+   (thread finished, call stack no longer available)
+
+Mutex still locked at thread exit: address 0x........, recursion count 1, owner 3.
+   at 0x........: pthread_join (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc22_exit_w_lock.c:43)
+
+
+ERROR SUMMARY: 12 errors from 12 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc22_exit_w_lock.stderr.exp-64bit b/drd/tests/tc22_exit_w_lock.stderr.exp-64bit
new file mode 100644
index 0000000..cf7e0d2
--- /dev/null
+++ b/drd/tests/tc22_exit_w_lock.stderr.exp-64bit
@@ -0,0 +1,11 @@
+
+Mutex still locked at thread exit: mutex 0x........, recursion count 1, owner 3.
+   at 0x........: pthread_join (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc22_exit_w_lock.c:43)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_lock (drd_pthread_intercepts.c:?)
+   by 0x........: child_fn1 (tc22_exit_w_lock.c:18)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc22_exit_w_lock.vgtest b/drd/tests/tc22_exit_w_lock.vgtest
new file mode 100644
index 0000000..673380c
--- /dev/null
+++ b/drd/tests/tc22_exit_w_lock.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread && [ -e ../../helgrind/tests/tc22_exit_w_lock ]
+vgopts: --num-callers=3
+prog: ../../helgrind/tests/tc22_exit_w_lock
diff --git a/drd/tests/tc23_bogus_condwait.stderr.exp-darwin b/drd/tests/tc23_bogus_condwait.stderr.exp-darwin
new file mode 100644
index 0000000..7832a6f
--- /dev/null
+++ b/drd/tests/tc23_bogus_condwait.stderr.exp-darwin
@@ -0,0 +1,63 @@
+
+The object at address 0x........ is not a mutex.
+   at 0x........: pthread_cond_wait (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:69)
+
+Mutex not locked: mutex 0x........, recursion count 0, owner 0.
+   at 0x........: pthread_cond_wait (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:72)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:51)
+
+Thread 3:
+Probably a race condition: condition variable 0x........ has been signaled but the associated mutex 0x........ is not locked by the signalling thread.
+   at 0x........: pthread_cond_signal (drd_pthread_intercepts.c:?)
+   by 0x........: rescue_me (tc23_bogus_condwait.c:20)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+cond 0x........ was first observed at:
+   at 0x........: pthread_cond_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:56)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:51)
+
+Thread 1:
+The object at address 0x........ is not a mutex.
+   at 0x........: pthread_cond_wait (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:75)
+rwlock 0x........ was first observed at:
+   at 0x........: pthread_rwlock_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:57)
+
+Mutex not locked by calling thread: mutex 0x........, recursion count 1, owner 2.
+   at 0x........: pthread_cond_wait (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:78)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:53)
+
+Thread 3:
+Probably a race condition: condition variable 0x........ has been signaled but the associated mutex 0x........ is not locked by the signalling thread.
+   at 0x........: pthread_cond_signal (drd_pthread_intercepts.c:?)
+   by 0x........: rescue_me (tc23_bogus_condwait.c:24)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+cond 0x........ was first observed at:
+   at 0x........: pthread_cond_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:56)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:53)
+
+The impossible happened: mutex 0x........ is locked simultaneously by two threads (recursion count 1, owners 2 and 1) !
+Thread 2:
+Mutex not locked by calling thread: mutex 0x........, recursion count 2, owner 1.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: grab_the_lock (tc23_bogus_condwait.c:42)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:53)
+
+
+ERROR SUMMARY: 9 errors from 7 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc23_bogus_condwait.stderr.exp-linux-ppc b/drd/tests/tc23_bogus_condwait.stderr.exp-linux-ppc
new file mode 100644
index 0000000..3854362
--- /dev/null
+++ b/drd/tests/tc23_bogus_condwait.stderr.exp-linux-ppc
@@ -0,0 +1,13 @@
+
+The object at address 0x........ is not a mutex.
+   at 0x........: pthread_cond_wait (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:69)
+
+
+Process terminating with default action of signal 7 (SIGBUS)
+ Invalid address alignment at address 0x........
+   at 0x........: (within libpthread-?.?.so)
+   by 0x........: pthread_cond_wait@@GLIBC_2.3.2(within libpthread-?.?.so)
+   by 0x........: pthread_cond_wait (drd_pthread_intercepts.c:?)
+
+ERROR SUMMARY: 2 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc23_bogus_condwait.stderr.exp-linux-x86 b/drd/tests/tc23_bogus_condwait.stderr.exp-linux-x86
new file mode 100644
index 0000000..5e16bd2
--- /dev/null
+++ b/drd/tests/tc23_bogus_condwait.stderr.exp-linux-x86
@@ -0,0 +1,86 @@
+
+The object at address 0x........ is not a mutex.
+   at 0x........: pthread_cond_wait (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:69)
+
+Thread 3:
+Probably a race condition: condition variable 0x........ has been signaled but the associated mutex 0x........ is not locked by the signalling thread.
+   at 0x........: pthread_cond_signal (drd_pthread_intercepts.c:?)
+   by 0x........: rescue_me (tc23_bogus_condwait.c:20)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+cond 0x........ was first observed at:
+   at 0x........: pthread_cond_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:56)
+
+Thread 1:
+Mutex not locked: mutex 0x........, recursion count 0, owner 0.
+   at 0x........: pthread_cond_wait (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:72)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:51)
+
+Thread 3:
+Probably a race condition: condition variable 0x........ has been signaled but the associated mutex 0x........ is not locked by the signalling thread.
+   at 0x........: pthread_cond_signal (drd_pthread_intercepts.c:?)
+   by 0x........: rescue_me (tc23_bogus_condwait.c:24)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+cond 0x........ was first observed at:
+   at 0x........: pthread_cond_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:56)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:51)
+
+Thread 1:
+The object at address 0x........ is not a mutex.
+   at 0x........: pthread_cond_wait (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:75)
+rwlock 0x........ was first observed at:
+   at 0x........: pthread_rwlock_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:57)
+
+Thread 3:
+Probably a race condition: condition variable 0x........ has been signaled but the associated mutex 0x........ is not locked by the signalling thread.
+   at 0x........: pthread_cond_signal (drd_pthread_intercepts.c:?)
+   by 0x........: rescue_me (tc23_bogus_condwait.c:28)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+cond 0x........ was first observed at:
+   at 0x........: pthread_cond_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:56)
+rwlock 0x........ was first observed at:
+   at 0x........: pthread_rwlock_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:57)
+
+Thread 1:
+Mutex not locked by calling thread: mutex 0x........, recursion count 1, owner 2.
+   at 0x........: pthread_cond_wait (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:78)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:53)
+
+Thread 3:
+Probably a race condition: condition variable 0x........ has been signaled but the associated mutex 0x........ is not locked by the signalling thread.
+   at 0x........: pthread_cond_signal (drd_pthread_intercepts.c:?)
+   by 0x........: rescue_me (tc23_bogus_condwait.c:32)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+cond 0x........ was first observed at:
+   at 0x........: pthread_cond_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:56)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:53)
+
+The impossible happened: mutex 0x........ is locked simultaneously by two threads (recursion count 1, owners 2 and 1) !
+Thread 2:
+Mutex not locked by calling thread: mutex 0x........, recursion count 2, owner 1.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: grab_the_lock (tc23_bogus_condwait.c:42)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+mutex 0x........ was first observed at:
+   at 0x........: pthread_mutex_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (tc23_bogus_condwait.c:53)
+
+
+ERROR SUMMARY: 11 errors from 9 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc23_bogus_condwait.vgtest b/drd/tests/tc23_bogus_condwait.vgtest
new file mode 100644
index 0000000..edbbef7
--- /dev/null
+++ b/drd/tests/tc23_bogus_condwait.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread
+vgopts: --num-callers=3
+prog: ../../helgrind/tests/tc23_bogus_condwait
diff --git a/drd/tests/tc24_nonzero_sem.stderr.exp b/drd/tests/tc24_nonzero_sem.stderr.exp
new file mode 100644
index 0000000..d18786f
--- /dev/null
+++ b/drd/tests/tc24_nonzero_sem.stderr.exp
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/tc24_nonzero_sem.vgtest b/drd/tests/tc24_nonzero_sem.vgtest
new file mode 100644
index 0000000..22bf7a1
--- /dev/null
+++ b/drd/tests/tc24_nonzero_sem.vgtest
@@ -0,0 +1,3 @@
+prereq: ./supported_libpthread && ./supported_sem_init
+prog: ../../helgrind/tests/tc24_nonzero_sem
+vgopts: --read-var-info=yes
diff --git a/drd/tests/thread_name.c b/drd/tests/thread_name.c
new file mode 100644
index 0000000..2236eae
--- /dev/null
+++ b/drd/tests/thread_name.c
@@ -0,0 +1,61 @@
+/* Test whether assigning names to threads works properly. */
+
+
+#include <pthread.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include "../../drd/drd.h"
+
+
+#define NUM_THREADS 10
+
+
+static pthread_mutex_t s_mutex;
+static pthread_cond_t  s_cond;
+static int s_counter;
+
+static void* thread_func(void* argp)
+{
+  const int thread_num = (ptrdiff_t)(argp);
+  pthread_mutex_t invalid_mutex;
+  char thread_name[32];
+
+  snprintf(thread_name, sizeof(thread_name),
+           "thread_func instance %d", thread_num + 1);
+  ANNOTATE_THREAD_NAME(thread_name);
+
+  memset(&invalid_mutex, 0xff, sizeof(invalid_mutex));
+
+  pthread_mutex_lock(&s_mutex);
+  while (s_counter != thread_num)
+    pthread_cond_wait(&s_cond, &s_mutex);
+  fprintf(stderr, "\n%s\n\n", thread_name);
+  pthread_mutex_unlock(&invalid_mutex);
+  s_counter++;
+  pthread_cond_broadcast(&s_cond);
+  pthread_mutex_unlock(&s_mutex);
+
+  return 0;
+}
+
+
+int main(int arg, char** argv)
+{
+  int i;
+  pthread_t tid[NUM_THREADS];
+
+  pthread_mutex_init(&s_mutex, 0);
+  pthread_cond_init(&s_cond, 0);
+
+  for (i = 0; i < NUM_THREADS; i++)
+    pthread_create(&tid[i], 0, thread_func, (void*)(ptrdiff_t)i);
+
+  for (i = 0; i < NUM_THREADS; i++)
+    pthread_join(tid[i], 0);
+
+  pthread_cond_destroy(&s_cond);
+  pthread_mutex_destroy(&s_mutex);
+
+  return 0;
+}
diff --git a/drd/tests/thread_name.stderr.exp b/drd/tests/thread_name.stderr.exp
new file mode 100644
index 0000000..82ad952
--- /dev/null
+++ b/drd/tests/thread_name.stderr.exp
@@ -0,0 +1,93 @@
+
+
+thread_func instance 1
+
+Thread 2 (thread_func instance 1):
+The object at address 0x........ is not a mutex.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: thread_func (thread_name.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+
+
+thread_func instance 2
+
+Thread 3 (thread_func instance 2):
+The object at address 0x........ is not a mutex.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: thread_func (thread_name.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+
+
+thread_func instance 3
+
+Thread 4 (thread_func instance 3):
+The object at address 0x........ is not a mutex.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: thread_func (thread_name.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+
+
+thread_func instance 4
+
+Thread 5 (thread_func instance 4):
+The object at address 0x........ is not a mutex.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: thread_func (thread_name.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+
+
+thread_func instance 5
+
+Thread 6 (thread_func instance 5):
+The object at address 0x........ is not a mutex.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: thread_func (thread_name.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+
+
+thread_func instance 6
+
+Thread 7 (thread_func instance 6):
+The object at address 0x........ is not a mutex.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: thread_func (thread_name.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+
+
+thread_func instance 7
+
+Thread 8 (thread_func instance 7):
+The object at address 0x........ is not a mutex.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: thread_func (thread_name.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+
+
+thread_func instance 8
+
+Thread 9 (thread_func instance 8):
+The object at address 0x........ is not a mutex.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: thread_func (thread_name.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+
+
+thread_func instance 9
+
+Thread 10 (thread_func instance 9):
+The object at address 0x........ is not a mutex.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: thread_func (thread_name.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+
+
+thread_func instance 10
+
+Thread 11 (thread_func instance 10):
+The object at address 0x........ is not a mutex.
+   at 0x........: pthread_mutex_unlock (drd_pthread_intercepts.c:?)
+   by 0x........: thread_func (thread_name.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+
+
+ERROR SUMMARY: 10 errors from 10 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/thread_name.vgtest b/drd/tests/thread_name.vgtest
new file mode 100644
index 0000000..868f5f3
--- /dev/null
+++ b/drd/tests/thread_name.vgtest
@@ -0,0 +1,3 @@
+prereq: test -e thread_name && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --num-callers=3
+prog: thread_name
diff --git a/drd/tests/trylock.c b/drd/tests/trylock.c
new file mode 100644
index 0000000..17f2fb6
--- /dev/null
+++ b/drd/tests/trylock.c
@@ -0,0 +1,78 @@
+/** Test interception of the various pthread_timed*lock() and pthread_try*lock()
+ *  functions. If any of these are not intercepted, an error message will be
+ *  printed at unlock time.
+ */
+
+
+/* Needed for older glibc's (2.3 and older, at least) who don't
+   otherwise "know" about pthread_rwlock_anything or about
+   PTHREAD_MUTEX_RECURSIVE (amongst things). */
+
+#define _GNU_SOURCE 1
+
+#include "../../config.h"
+#include <stdio.h>
+#include <assert.h>
+#include <pthread.h>
+
+
+int main(int argc, char** argv)
+{
+  int r;
+  pthread_mutex_t mutex;
+  pthread_rwlock_t rwlock;
+  struct timespec abs_timeout;
+
+  time(&abs_timeout.tv_sec);
+  abs_timeout.tv_nsec = 0;
+  abs_timeout.tv_sec += 10;
+
+  r = pthread_rwlock_init(&rwlock, NULL); assert(r == 0);
+  fprintf(stderr, "Locking rwlock via pthread_rwlock_wrlock().\n");
+  r = pthread_rwlock_wrlock(&rwlock); assert(r == 0);
+  r = pthread_rwlock_unlock(&rwlock); assert(r == 0);
+  fprintf(stderr, "Locking rwlock via pthread_rwlock_trywrlock().\n");
+  r = pthread_rwlock_trywrlock(&rwlock); assert(r == 0);
+  r = pthread_rwlock_unlock(&rwlock); assert(r == 0);
+  fprintf(stderr, "Locking rwlock via pthread_rwlock_timedwrlock().\n");
+#ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
+  r = pthread_rwlock_timedwrlock(&rwlock, &abs_timeout); assert(r == 0);
+  r = pthread_rwlock_unlock(&rwlock); assert(r == 0);
+#endif
+  fprintf(stderr, "Locking rwlock via pthread_rwlock_rdlock().\n");
+  r = pthread_rwlock_rdlock(&rwlock); assert(r == 0);
+  r = pthread_rwlock_rdlock(&rwlock); assert(r == 0);
+  r = pthread_rwlock_rdlock(&rwlock); assert(r == 0);
+  r = pthread_rwlock_unlock(&rwlock); assert(r == 0);
+  r = pthread_rwlock_unlock(&rwlock); assert(r == 0);
+  r = pthread_rwlock_unlock(&rwlock); assert(r == 0);
+  fprintf(stderr, "Locking rwlock via pthread_rwlock_tryrdlock().\n");
+  r = pthread_rwlock_tryrdlock(&rwlock); assert(r == 0);
+  r = pthread_rwlock_unlock(&rwlock); assert(r == 0);
+  fprintf(stderr, "Locking rwlock via pthread_rwlock_timedrdlock().\n");
+#ifdef HAVE_PTHREAD_RWLOCK_TIMEDRDLOCK
+  r = pthread_rwlock_timedrdlock(&rwlock, &abs_timeout); assert(r == 0);
+  r = pthread_rwlock_unlock(&rwlock); assert(r == 0);
+#endif
+  fprintf(stderr, "Attempt to lock for writing recursively (not allowed).\n");
+  r = pthread_rwlock_wrlock(&rwlock); assert(r == 0);
+  r = pthread_rwlock_wrlock(&rwlock); assert(r != 0);
+  r = pthread_rwlock_unlock(&rwlock); assert(r == 0);
+  r = pthread_rwlock_destroy(&rwlock); assert(r == 0);
+
+  r = pthread_mutex_init(&mutex, NULL); assert(r == 0);
+  fprintf(stderr, "Locking mutex via pthread_mutex_trylock().\n");
+  r = pthread_mutex_trylock(&mutex); assert(r == 0);
+  r = pthread_mutex_unlock(&mutex); assert(r == 0);
+  fprintf(stderr, "Locking mutex via pthread_mutex_lock().\n");
+  r = pthread_mutex_lock(&mutex); assert(r == 0);
+  r = pthread_mutex_unlock(&mutex); assert(r == 0);
+  fprintf(stderr, "Locking mutex via pthread_mutex_timedlock().\n");
+#ifdef HAVE_PTHREAD_MUTEX_TIMEDLOCK
+  r = pthread_mutex_timedlock(&mutex, &abs_timeout); assert(r == 0);
+  r = pthread_mutex_unlock(&mutex); assert(r == 0);
+#endif
+  r = pthread_mutex_destroy(&mutex); assert(r == 0);
+
+  return 0;
+}
diff --git a/drd/tests/trylock.stderr.exp b/drd/tests/trylock.stderr.exp
new file mode 100644
index 0000000..2c5d765
--- /dev/null
+++ b/drd/tests/trylock.stderr.exp
@@ -0,0 +1,20 @@
+
+Locking rwlock via pthread_rwlock_wrlock().
+Locking rwlock via pthread_rwlock_trywrlock().
+Locking rwlock via pthread_rwlock_timedwrlock().
+Locking rwlock via pthread_rwlock_rdlock().
+Locking rwlock via pthread_rwlock_tryrdlock().
+Locking rwlock via pthread_rwlock_timedrdlock().
+Attempt to lock for writing recursively (not allowed).
+Recursive writer locking not allowed: rwlock 0x.........
+   at 0x........: pthread_rwlock_wrlock (drd_pthread_intercepts.c:?)
+   by 0x........: main (trylock.c:?)
+rwlock 0x........ was first observed at:
+   at 0x........: pthread_rwlock_init (drd_pthread_intercepts.c:?)
+   by 0x........: main (trylock.c:?)
+
+Locking mutex via pthread_mutex_trylock().
+Locking mutex via pthread_mutex_lock().
+Locking mutex via pthread_mutex_timedlock().
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/trylock.vgtest b/drd/tests/trylock.vgtest
new file mode 100644
index 0000000..2cdcd24
--- /dev/null
+++ b/drd/tests/trylock.vgtest
@@ -0,0 +1,2 @@
+prereq: ./supported_libpthread
+prog: trylock
diff --git a/drd/tests/tsan_thread_wrappers_pthread.h b/drd/tests/tsan_thread_wrappers_pthread.h
new file mode 100644
index 0000000..cfb9b3c
--- /dev/null
+++ b/drd/tests/tsan_thread_wrappers_pthread.h
@@ -0,0 +1,614 @@
+/*
+  This file is part of Valgrind, a dynamic binary instrumentation
+  framework.
+
+  Copyright (C) 2008-2008 Google Inc
+     opensource@google.com
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+// Author: Konstantin Serebryany <opensource@google.com>
+//
+// Here we define few simple classes that wrap pthread primitives.
+//
+// We need this to create unit tests for helgrind (or similar tool)
+// that will work with different threading frameworks.
+//
+// If one needs to test helgrind's support for another threading library,
+// he/she can create a copy of this file and replace pthread_ calls
+// with appropriate calls to his/her library.
+//
+// Note, that some of the methods defined here are annotated with
+// ANNOTATE_* macros defined in dynamic_annotations.h.
+//
+// DISCLAIMER: the classes defined in this header file
+// are NOT intended for general use -- only for unit tests.
+//
+
+#ifndef THREAD_WRAPPERS_PTHREAD_H
+#define THREAD_WRAPPERS_PTHREAD_H
+
+#include <pthread.h>
+#include <semaphore.h>
+#include <unistd.h>
+#include <queue>
+#include <stdio.h>
+#include <limits.h>   // INT_MAX
+
+#ifdef __APPLE__
+#include <libkern/OSAtomic.h>
+#define NO_BARRIER
+#define NO_TLS
+#endif
+
+#include <string>
+using namespace std;
+
+#include <sys/time.h>
+#include <time.h>
+
+#include "../../drd/drd.h"
+#define ANNOTATE_NO_OP(arg) do { } while(0)
+#define ANNOTATE_EXPECT_RACE(addr, descr)                \
+    ANNOTATE_BENIGN_RACE_SIZED(addr, 4, "expected race")
+static inline bool RunningOnValgrind() { return RUNNING_ON_VALGRIND; }
+
+#include <assert.h>
+#ifdef NDEBUG
+# error "Pleeease, do not define NDEBUG"
+#endif
+#define CHECK assert
+
+/// Set this to true if malloc() uses mutex on your platform as this may
+/// introduce a happens-before arc for a pure happens-before race detector.
+const bool kMallocUsesMutex = false;
+
+/// Current time in milliseconds.
+static inline int64_t GetCurrentTimeMillis() {
+  struct timeval now;
+  gettimeofday(&now, NULL);
+  return now.tv_sec * 1000 + now.tv_usec / 1000;
+}
+
+/// Copy tv to ts adding offset in milliseconds.
+static inline void timeval2timespec(timeval *const tv,
+                                     timespec *ts,
+                                     int64_t offset_milli) {
+  const int64_t ten_9 = 1000000000LL;
+  const int64_t ten_6 = 1000000LL;
+  const int64_t ten_3 = 1000LL;
+  int64_t now_nsec = (int64_t)tv->tv_sec * ten_9;
+  now_nsec += (int64_t)tv->tv_usec * ten_3;
+  int64_t then_nsec = now_nsec + offset_milli * ten_6;
+  ts->tv_sec  = then_nsec / ten_9;
+  ts->tv_nsec = then_nsec % ten_9;
+}
+
+
+class CondVar;
+
+#ifndef NO_SPINLOCK
+/// helgrind does not (yet) support spin locks, so we annotate them.
+
+#ifndef __APPLE__
+class SpinLock {
+ public:
+  SpinLock() {
+    CHECK(0 == pthread_spin_init(&mu_, 0));
+    ANNOTATE_RWLOCK_CREATE((void*)&mu_);
+  }
+  ~SpinLock() {
+    ANNOTATE_RWLOCK_DESTROY((void*)&mu_);
+    CHECK(0 == pthread_spin_destroy(&mu_));
+  }
+  void Lock() {
+    CHECK(0 == pthread_spin_lock(&mu_));
+    ANNOTATE_RWLOCK_ACQUIRED((void*)&mu_, 1);
+  }
+  void Unlock() {
+    ANNOTATE_RWLOCK_RELEASED((void*)&mu_, 1);
+    CHECK(0 == pthread_spin_unlock(&mu_));
+  }
+ private:
+  pthread_spinlock_t mu_;
+};
+
+#else
+
+class SpinLock {
+ public:
+  // Mac OS X version.
+  SpinLock() : mu_(OS_SPINLOCK_INIT) {
+    ANNOTATE_RWLOCK_CREATE((void*)&mu_);
+  }
+  ~SpinLock() {
+    ANNOTATE_RWLOCK_DESTROY((void*)&mu_);
+  }
+  void Lock() {
+    OSSpinLockLock(&mu_);
+    ANNOTATE_RWLOCK_ACQUIRED((void*)&mu_, 1);
+  }
+  void Unlock() {
+    ANNOTATE_RWLOCK_RELEASED((void*)&mu_, 1);
+    OSSpinLockUnlock(&mu_);
+  }
+ private:
+  OSSpinLock mu_;
+};
+#endif // __APPLE__
+
+#endif // NO_SPINLOCK
+
+/// Just a boolean condition. Used by Mutex::LockWhen and similar.
+class Condition {
+ public:
+  typedef bool (*func_t)(void*);
+
+  template <typename T>
+  Condition(bool (*func)(T*), T* arg)
+  : func_(reinterpret_cast<func_t>(func)), arg_(arg) {}
+
+  Condition(bool (*func)())
+  : func_(reinterpret_cast<func_t>(func)), arg_(NULL) {}
+
+  bool Eval() { return func_(arg_); }
+ private:
+  func_t func_;
+  void *arg_;
+
+};
+
+
+/// Wrapper for pthread_mutex_t.
+///
+/// pthread_mutex_t is *not* a reader-writer lock,
+/// so the methods like ReaderLock() aren't really reader locks.
+/// We can not use pthread_rwlock_t because it
+/// does not work with pthread_cond_t.
+///
+/// TODO: We still need to test reader locks with this class.
+/// Implement a mode where pthread_rwlock_t will be used
+/// instead of pthread_mutex_t (only when not used with CondVar or LockWhen).
+///
+class Mutex {
+  friend class CondVar;
+ public:
+  Mutex() {
+    CHECK(0 == pthread_mutex_init(&mu_, NULL));
+    CHECK(0 == pthread_cond_init(&cv_, NULL));
+    signal_at_unlock_ = true;  // Always signal at Unlock to make
+                               // Mutex more friendly to hybrid detectors.
+  }
+  ~Mutex() {
+    CHECK(0 == pthread_cond_destroy(&cv_));
+    CHECK(0 == pthread_mutex_destroy(&mu_));
+  }
+  void Lock()          { CHECK(0 == pthread_mutex_lock(&mu_));}
+  bool TryLock()       { return (0 == pthread_mutex_trylock(&mu_));}
+  void Unlock() {
+    if (signal_at_unlock_) {
+      CHECK(0 == pthread_cond_signal(&cv_));
+    }
+    CHECK(0 == pthread_mutex_unlock(&mu_));
+  }
+  void ReaderLock()    { Lock(); }
+  bool ReaderTryLock() { return TryLock();}
+  void ReaderUnlock()  { Unlock(); }
+
+  void LockWhen(Condition cond)            { Lock(); WaitLoop(cond); }
+  void ReaderLockWhen(Condition cond)      { Lock(); WaitLoop(cond); }
+  void Await(Condition cond)               { WaitLoop(cond); }
+
+  bool ReaderLockWhenWithTimeout(Condition cond, int millis)
+    { Lock(); return WaitLoopWithTimeout(cond, millis); }
+  bool LockWhenWithTimeout(Condition cond, int millis)
+    { Lock(); return WaitLoopWithTimeout(cond, millis); }
+  bool AwaitWithTimeout(Condition cond, int millis)
+    { return WaitLoopWithTimeout(cond, millis); }
+
+ private:
+
+  void WaitLoop(Condition cond) {
+    signal_at_unlock_ = true;
+    while(cond.Eval() == false) {
+      pthread_cond_wait(&cv_, &mu_);
+    }
+    ANNOTATE_CONDVAR_LOCK_WAIT(&cv_, &mu_);
+  }
+
+  bool WaitLoopWithTimeout(Condition cond, int millis) {
+    struct timeval now;
+    struct timespec timeout;
+    int retcode = 0;
+    gettimeofday(&now, NULL);
+    timeval2timespec(&now, &timeout, millis);
+
+    signal_at_unlock_ = true;
+    while (cond.Eval() == false && retcode == 0) {
+      retcode = pthread_cond_timedwait(&cv_, &mu_, &timeout);
+    }
+    if(retcode == 0) {
+      ANNOTATE_CONDVAR_LOCK_WAIT(&cv_, &mu_);
+    }
+    return cond.Eval();
+  }
+
+  // A hack. cv_ should be the first data member so that
+  // ANNOTATE_CONDVAR_WAIT(&MU, &MU) and ANNOTATE_CONDVAR_SIGNAL(&MU) works.
+  // (See also racecheck_unittest.cc)
+  pthread_cond_t  cv_;
+  pthread_mutex_t mu_;
+  bool            signal_at_unlock_;  // Set to true if Wait was called.
+};
+
+
+class MutexLock {  // Scoped Mutex Locker/Unlocker
+ public:
+  MutexLock(Mutex *mu)
+    : mu_(mu) {
+    mu_->Lock();
+  }
+  ~MutexLock() {
+    mu_->Unlock();
+  }
+ private:
+  Mutex *mu_;
+};
+
+
+/// Wrapper for pthread_cond_t.
+class CondVar {
+ public:
+  CondVar()   { CHECK(0 == pthread_cond_init(&cv_, NULL)); }
+  ~CondVar()  { CHECK(0 == pthread_cond_destroy(&cv_)); }
+  void Wait(Mutex *mu) { CHECK(0 == pthread_cond_wait(&cv_, &mu->mu_)); }
+  bool WaitWithTimeout(Mutex *mu, int millis) {
+    struct timeval now;
+    struct timespec timeout;
+    gettimeofday(&now, NULL);
+    timeval2timespec(&now, &timeout, millis);
+    return 0 != pthread_cond_timedwait(&cv_, &mu->mu_, &timeout);
+  }
+  void Signal() { CHECK(0 == pthread_cond_signal(&cv_)); }
+  void SignalAll() { CHECK(0 == pthread_cond_broadcast(&cv_)); }
+ private:
+  pthread_cond_t cv_;
+};
+
+
+// pthreads do not allow to use condvar with rwlock so we can't make
+// ReaderLock method of Mutex to be the real rw-lock.
+// So, we need a special lock class to test reader locks.
+#define NEEDS_SEPERATE_RW_LOCK
+class RWLock {
+ public:
+  RWLock() { CHECK(0 == pthread_rwlock_init(&mu_, NULL)); }
+  ~RWLock() { CHECK(0 == pthread_rwlock_destroy(&mu_)); }
+  void Lock() { CHECK(0 == pthread_rwlock_wrlock(&mu_)); }
+  void ReaderLock() { CHECK(0 == pthread_rwlock_rdlock(&mu_)); }
+  void Unlock() { CHECK(0 == pthread_rwlock_unlock(&mu_)); }
+  void ReaderUnlock() { CHECK(0 == pthread_rwlock_unlock(&mu_)); }
+ private:
+  pthread_cond_t dummy; // Damn, this requires some redesign...
+  pthread_rwlock_t mu_;
+};
+
+class ReaderLockScoped {  // Scoped RWLock Locker/Unlocker
+ public:
+  ReaderLockScoped(RWLock *mu)
+    : mu_(mu) {
+    mu_->ReaderLock();
+  }
+  ~ReaderLockScoped() {
+    mu_->ReaderUnlock();
+  }
+ private:
+  RWLock *mu_;
+};
+
+class WriterLockScoped {  // Scoped RWLock Locker/Unlocker
+ public:
+  WriterLockScoped(RWLock *mu)
+    : mu_(mu) {
+    mu_->Lock();
+  }
+  ~WriterLockScoped() {
+    mu_->Unlock();
+  }
+ private:
+  RWLock *mu_;
+};
+
+
+
+
+/// Wrapper for pthread_create()/pthread_join().
+class MyThread {
+ public:
+  typedef void *(*worker_t)(void*);
+
+  MyThread(worker_t worker, void *arg = NULL, const char *name = NULL)
+      :w_(worker), arg_(arg), name_(name) {}
+  MyThread(void (*worker)(void), void *arg = NULL, const char *name = NULL)
+      :w_(reinterpret_cast<worker_t>(worker)), arg_(arg), name_(name) {}
+  MyThread(void (*worker)(void *), void *arg = NULL, const char *name = NULL)
+      :w_(reinterpret_cast<worker_t>(worker)), arg_(arg), name_(name) {}
+
+  ~MyThread(){ w_ = NULL; arg_ = NULL;}
+  void Start() { CHECK(0 == pthread_create(&t_, NULL, (worker_t)ThreadBody, this));}
+  void Join()  { CHECK(0 == pthread_join(t_, NULL));}
+  pthread_t tid() const { return t_; }
+ private:
+  static void ThreadBody(MyThread *my_thread) {
+    if (my_thread->name_) {
+      ANNOTATE_THREAD_NAME(my_thread->name_);
+    }
+    my_thread->w_(my_thread->arg_);
+  }
+  pthread_t t_;
+  worker_t  w_;
+  void     *arg_;
+  const char *name_;
+};
+
+
+/// Just a message queue.
+class ProducerConsumerQueue {
+ public:
+  ProducerConsumerQueue(int unused) {
+    //ANNOTATE_PCQ_CREATE(this);
+  }
+  ~ProducerConsumerQueue() {
+    CHECK(q_.empty());
+    //ANNOTATE_PCQ_DESTROY(this);
+  }
+
+  // Put.
+  void Put(void *item) {
+    mu_.Lock();
+      q_.push(item);
+      ANNOTATE_CONDVAR_SIGNAL(&mu_); // LockWhen in Get()
+      //ANNOTATE_PCQ_PUT(this);
+    mu_.Unlock();
+  }
+
+  // Get.
+  // Blocks if the queue is empty.
+  void *Get() {
+    mu_.LockWhen(Condition(IsQueueNotEmpty, &q_));
+      void * item = NULL;
+      bool ok = TryGetInternal(&item);
+      CHECK(ok);
+    mu_.Unlock();
+    return item;
+  }
+
+  // If queue is not empty,
+  // remove an element from queue, put it into *res and return true.
+  // Otherwise return false.
+  bool TryGet(void **res) {
+    mu_.Lock();
+      bool ok = TryGetInternal(res);
+    mu_.Unlock();
+    return ok;
+  }
+
+ private:
+  Mutex mu_;
+  std::queue<void*> q_; // protected by mu_
+
+  // Requires mu_
+  bool TryGetInternal(void ** item_ptr) {
+    if (q_.empty())
+      return false;
+    *item_ptr = q_.front();
+    q_.pop();
+    //ANNOTATE_PCQ_GET(this);
+    return true;
+  }
+
+  static bool IsQueueNotEmpty(std::queue<void*> * queue) {
+     return !queue->empty();
+  }
+};
+
+
+
+/// Function pointer with zero, one or two parameters.
+struct Closure {
+  typedef void (*F0)();
+  typedef void (*F1)(void *arg1);
+  typedef void (*F2)(void *arg1, void *arg2);
+  int  n_params;
+  void *f;
+  void *param1;
+  void *param2;
+
+  void Execute() {
+    if (n_params == 0) {
+      (F0(f))();
+    } else if (n_params == 1) {
+      (F1(f))(param1);
+    } else {
+      CHECK(n_params == 2);
+      (F2(f))(param1, param2);
+    }
+    delete this;
+  }
+};
+
+Closure *NewCallback(void (*f)()) {
+  Closure *res = new Closure;
+  res->n_params = 0;
+  res->f = (void*)(f);
+  res->param1 = NULL;
+  res->param2 = NULL;
+  return res;
+}
+
+template <class P1>
+Closure *NewCallback(void (*f)(P1), P1 p1) {
+  CHECK(sizeof(P1) <= sizeof(void*));
+  Closure *res = new Closure;
+  res->n_params = 1;
+  res->f = (void*)(f);
+  res->param1 = (void*)p1;
+  res->param2 = NULL;
+  return res;
+}
+
+template <class T, class P1, class P2>
+Closure *NewCallback(void (*f)(P1, P2), P1 p1, P2 p2) {
+  CHECK(sizeof(P1) <= sizeof(void*));
+  Closure *res = new Closure;
+  res->n_params = 2;
+  res->f = (void*)(f);
+  res->param1 = (void*)p1;
+  res->param2 = (void*)p2;
+  return res;
+}
+
+/*! A thread pool that uses ProducerConsumerQueue.
+  Usage:
+  {
+    ThreadPool pool(n_workers);
+    pool.StartWorkers();
+    pool.Add(NewCallback(func_with_no_args));
+    pool.Add(NewCallback(func_with_one_arg, arg));
+    pool.Add(NewCallback(func_with_two_args, arg1, arg2));
+    ... // more calls to pool.Add()
+
+    // the ~ThreadPool() is called: we wait workers to finish
+    // and then join all threads in the pool.
+  }
+*/
+class ThreadPool {
+ public:
+  //! Create n_threads threads, but do not start.
+  explicit ThreadPool(int n_threads)
+    : queue_(INT_MAX) {
+    for (int i = 0; i < n_threads; i++) {
+      MyThread *thread = new MyThread(&ThreadPool::Worker, this);
+      workers_.push_back(thread);
+    }
+  }
+
+  //! Start all threads.
+  void StartWorkers() {
+    for (size_t i = 0; i < workers_.size(); i++) {
+      workers_[i]->Start();
+    }
+  }
+
+  //! Add a closure.
+  void Add(Closure *closure) {
+    queue_.Put(closure);
+  }
+
+  int num_threads() { return workers_.size();}
+
+  //! Wait workers to finish, then join all threads.
+  ~ThreadPool() {
+    for (size_t i = 0; i < workers_.size(); i++) {
+      Add(NULL);
+    }
+    for (size_t i = 0; i < workers_.size(); i++) {
+      workers_[i]->Join();
+      delete workers_[i];
+    }
+  }
+ private:
+  std::vector<MyThread*>   workers_;
+  ProducerConsumerQueue  queue_;
+
+  static void *Worker(void *p) {
+    ThreadPool *pool = reinterpret_cast<ThreadPool*>(p);
+    while (true) {
+      Closure *closure = reinterpret_cast<Closure*>(pool->queue_.Get());
+      if(closure == NULL) {
+        return NULL;
+      }
+      closure->Execute();
+    }
+  }
+};
+
+#ifndef NO_BARRIER
+/// Wrapper for pthread_barrier_t.
+class Barrier{
+ public:
+  explicit Barrier(int n_threads) {CHECK(0 == pthread_barrier_init(&b_, 0, n_threads));}
+  ~Barrier()                      {CHECK(0 == pthread_barrier_destroy(&b_));}
+  void Block() {
+    // helgrind 3.3.0 does not have an interceptor for barrier.
+    // but our current local version does.
+    // ANNOTATE_CONDVAR_SIGNAL(this);
+    pthread_barrier_wait(&b_);
+    // ANNOTATE_CONDVAR_WAIT(this, this);
+  }
+ private:
+  pthread_barrier_t b_;
+};
+
+#endif // NO_BARRIER
+
+class BlockingCounter {
+ public:
+  explicit BlockingCounter(int initial_count) :
+    count_(initial_count) {}
+  bool DecrementCount() {
+    MutexLock lock(&mu_);
+    count_--;
+    return count_ == 0;
+  }
+  void Wait() {
+    mu_.LockWhen(Condition(&IsZero, &count_));
+    mu_.Unlock();
+  }
+ private:
+  static bool IsZero(int *arg) { return *arg == 0; }
+  Mutex mu_;
+  int count_;
+};
+
+int AtomicIncrement(volatile int *value, int increment);
+
+#ifndef __APPLE__
+inline int AtomicIncrement(volatile int *value, int increment) {
+  return __sync_add_and_fetch(value, increment);
+}
+
+#else
+// Mac OS X version.
+inline int AtomicIncrement(volatile int *value, int increment) {
+  return OSAtomicAdd32(increment, value);
+}
+
+// TODO(timurrrr) this is a hack
+#define memalign(A,B) malloc(B)
+
+// TODO(timurrrr) this is a hack
+int posix_memalign(void **out, size_t al, size_t size) {
+  *out = memalign(al, size);
+  return (*out == 0);
+}
+#endif // __APPLE__
+
+#endif // THREAD_WRAPPERS_PTHREAD_H
+// vim:shiftwidth=2:softtabstop=2:expandtab:foldmethod=marker
diff --git a/drd/tests/tsan_unittest.cpp b/drd/tests/tsan_unittest.cpp
new file mode 100644
index 0000000..6ba123d
--- /dev/null
+++ b/drd/tests/tsan_unittest.cpp
@@ -0,0 +1,7806 @@
+/*
+  This file is part of Valgrind, a dynamic binary instrumentation
+  framework.
+
+  Copyright (C) 2008-2008 Google Inc
+     opensource@google.com 
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+// Author: Konstantin Serebryany <opensource@google.com> 
+//
+// This file contains a set of unit tests for a data race detection tool. 
+//
+//
+//
+// This test can be compiled with pthreads (default) or
+// with any other library that supports threads, locks, cond vars, etc. 
+// 
+// To compile with pthreads: 
+//   g++  racecheck_unittest.cc dynamic_annotations.cc 
+//        -lpthread -g -DDYNAMIC_ANNOTATIONS=1
+// 
+// To compile with different library: 
+//   1. cp thread_wrappers_pthread.h thread_wrappers_yourlib.h
+//   2. edit thread_wrappers_yourlib.h
+//   3. add '-DTHREAD_WRAPPERS="thread_wrappers_yourlib.h"' to your compilation.
+//
+//
+
+// This test must not include any other file specific to threading library,
+// everything should be inside THREAD_WRAPPERS. 
+#ifndef THREAD_WRAPPERS 
+# define THREAD_WRAPPERS "thread_wrappers_pthread.h"
+#endif 
+#include THREAD_WRAPPERS
+
+#ifndef NEEDS_SEPERATE_RW_LOCK
+#define RWLock Mutex // Mutex does work as an rw-lock.
+#define WriterLockScoped MutexLock
+#define ReaderLockScoped ReaderMutexLock
+#endif // !NEEDS_SEPERATE_RW_LOCK
+
+
+// Helgrind memory usage testing stuff
+// If not present in dynamic_annotations.h/.cc - ignore
+#ifndef ANNOTATE_RESET_STATS
+#define ANNOTATE_RESET_STATS() do { } while(0)
+#endif
+#ifndef ANNOTATE_PRINT_STATS
+#define ANNOTATE_PRINT_STATS() do { } while(0)
+#endif
+#ifndef ANNOTATE_PRINT_MEMORY_USAGE
+#define ANNOTATE_PRINT_MEMORY_USAGE(a) do { } while(0)
+#endif
+//
+
+// A function that allows to suppress gcc's warnings about
+// unused return values in a portable way.
+template <typename T>
+static inline void IGNORE_RETURN_VALUE(T v)
+{ }
+
+#include <vector>
+#include <string>
+#include <map>
+#include <queue>
+#include <algorithm>
+#include <cstring>      // strlen(), index(), rindex()
+#include <ctime>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>  // mmap
+#include <errno.h>
+#include <stdint.h>    // uintptr_t
+#include <stdlib.h>
+#include <dirent.h>
+
+#ifndef __APPLE__
+#include <malloc.h>
+#endif
+
+// The tests are
+// - Stability tests (marked STAB)
+// - Performance tests (marked PERF)
+// - Feature tests
+//   - TN (true negative) : no race exists and the tool is silent. 
+//   - TP (true positive) : a race exists and reported. 
+//   - FN (false negative): a race exists but not reported. 
+//   - FP (false positive): no race exists but the tool reports it. 
+//
+// The feature tests are marked according to the behavior of helgrind 3.3.0.
+//
+// TP and FP tests are annotated with ANNOTATE_EXPECT_RACE, 
+// so, no error reports should be seen when running under helgrind. 
+//
+// When some of the FP cases are fixed in helgrind we'll need 
+// to update this test.
+//
+// Each test resides in its own namespace. 
+// Namespaces are named test01, test02, ... 
+// Please, *DO NOT* change the logic of existing tests nor rename them. 
+// Create a new test instead. 
+//
+// Some tests use sleep()/usleep(). 
+// This is not a synchronization, but a simple way to trigger 
+// some specific behaviour of the race detector's scheduler.
+
+// Globals and utilities used by several tests. {{{1
+CondVar CV; 
+int     COND = 0;
+
+
+typedef void (*void_func_void_t)(void);
+enum TEST_FLAG {
+  FEATURE           = 1 << 0, 
+  STABILITY         = 1 << 1, 
+  PERFORMANCE       = 1 << 2,
+  EXCLUDE_FROM_ALL  = 1 << 3,
+  NEEDS_ANNOTATIONS = 1 << 4,
+  RACE_DEMO         = 1 << 5,
+  MEMORY_USAGE      = 1 << 6,
+  PRINT_STATS       = 1 << 7
+};
+
+// Put everything into stderr.
+Mutex printf_mu;
+#define printf(args...) \
+    do{ \
+      printf_mu.Lock();\
+      fprintf(stderr, args);\
+      printf_mu.Unlock(); \
+    }while(0)
+
+long GetTimeInMs() {
+   struct timeval tv;
+   gettimeofday(&tv, NULL);
+   return (tv.tv_sec * 1000L) + (tv.tv_usec / 1000L);
+}
+
+struct Test{
+  void_func_void_t f_;
+  int flags_;
+  Test(void_func_void_t f, int flags) 
+    : f_(f)
+    , flags_(flags)
+  {}
+  Test() : f_(0), flags_(0) {}
+  void Run() {
+     ANNOTATE_RESET_STATS();
+     if (flags_ & PERFORMANCE) {
+        long start = GetTimeInMs();
+        f_();
+        long end = GetTimeInMs();
+        printf ("Time: %4ldms\n", end-start);
+     } else
+        f_();
+     if (flags_ & PRINT_STATS)
+        ANNOTATE_PRINT_STATS();
+     if (flags_ & MEMORY_USAGE)
+        ANNOTATE_PRINT_MEMORY_USAGE(0);
+  }
+};
+std::map<int, Test> TheMapOfTests;
+
+#define NOINLINE __attribute__ ((noinline))
+extern "C" void NOINLINE AnnotateSetVerbosity(const char *, int, int) {};
+
+
+struct TestAdder {
+  TestAdder(void_func_void_t f, int id, int flags = FEATURE) {
+    // AnnotateSetVerbosity(__FILE__, __LINE__, 0);
+    CHECK(TheMapOfTests.count(id) == 0);
+    TheMapOfTests[id] = Test(f, flags);
+  }
+};
+
+#define REGISTER_TEST(f, id)         TestAdder add_test_##id (f, id);
+#define REGISTER_TEST2(f, id, flags) TestAdder add_test_##id (f, id, flags);
+
+static bool ArgIsOne(int *arg) { return *arg == 1; };
+static bool ArgIsZero(int *arg) { return *arg == 0; };
+static bool ArgIsTrue(bool *arg) { return *arg == true; };
+
+// Call ANNOTATE_EXPECT_RACE only if 'machine' env variable is defined. 
+// Useful to test against several different machines. 
+// Supported machines so far:
+//   MSM_HYBRID1             -- aka MSMProp1
+//   MSM_HYBRID1_INIT_STATE  -- aka MSMProp1 with --initialization-state=yes
+//   MSM_THREAD_SANITIZER    -- ThreadSanitizer's state machine
+#define ANNOTATE_EXPECT_RACE_FOR_MACHINE(mem, descr, machine) \
+    while(getenv(machine)) {\
+      ANNOTATE_EXPECT_RACE(mem, descr); \
+      break;\
+    }\
+
+#define ANNOTATE_EXPECT_RACE_FOR_TSAN(mem, descr) \
+    ANNOTATE_EXPECT_RACE_FOR_MACHINE(mem, descr, "MSM_THREAD_SANITIZER")
+
+inline bool Tsan_PureHappensBefore() {
+  return true;
+}
+
+inline bool Tsan_FastMode()           {
+  return getenv("TSAN_FAST_MODE") != NULL;
+}
+
+// Initialize *(mem) to 0 if Tsan_FastMode.
+#define FAST_MODE_INIT(mem) do { if (Tsan_FastMode()) { *(mem) = 0; } } while(0)
+
+#ifndef MAIN_INIT_ACTION
+#define MAIN_INIT_ACTION
+#endif 
+
+
+
+int main(int argc, char** argv) { // {{{1
+  MAIN_INIT_ACTION;
+  printf("FLAGS [phb=%i, fm=%i]\n", Tsan_PureHappensBefore(), Tsan_FastMode());
+  if (argc == 2 && !strcmp(argv[1], "benchmark")) {
+     for (std::map<int,Test>::iterator it = TheMapOfTests.begin(); 
+         it != TheMapOfTests.end(); ++it) {
+       if(!(it->second.flags_ & PERFORMANCE)) continue;
+       it->second.Run();
+     }    
+  } else if (argc == 2 && !strcmp(argv[1], "demo")) {
+     for (std::map<int,Test>::iterator it = TheMapOfTests.begin(); 
+         it != TheMapOfTests.end();  ++it) {
+       if(!(it->second.flags_ & RACE_DEMO)) continue;
+       it->second.Run();
+     }      
+  } else if (argc > 1) {     
+    // the tests are listed in command line flags 
+    for (int i = 1; i < argc; i++) {
+      int f_num = atoi(argv[i]);
+      CHECK(TheMapOfTests.count(f_num));
+      TheMapOfTests[f_num].Run();
+    }
+  } else {
+    bool run_tests_with_annotations = false;
+    if (getenv("DRT_ALLOW_ANNOTATIONS")) {
+      run_tests_with_annotations = true;
+    }
+    for (std::map<int,Test>::iterator it = TheMapOfTests.begin(); 
+        it != TheMapOfTests.end();
+        ++it) {
+      if(it->second.flags_ & EXCLUDE_FROM_ALL) continue;
+      if(it->second.flags_ & RACE_DEMO) continue;
+      if((it->second.flags_ & NEEDS_ANNOTATIONS)
+         && run_tests_with_annotations == false) continue;
+      it->second.Run();
+    } 
+  }
+}
+
+#ifdef THREAD_WRAPPERS_PTHREAD_H
+#endif
+
+
+// An array of threads. Create/start/join all elements at once. {{{1
+class MyThreadArray {
+ public:
+  static const int kSize = 5;
+  typedef void (*F) (void);
+  MyThreadArray(F f1, F f2 = NULL, F f3 = NULL, F f4 = NULL, F f5 = NULL) {
+    ar_[0] = new MyThread(f1);
+    ar_[1] = f2 ? new MyThread(f2) : NULL;
+    ar_[2] = f3 ? new MyThread(f3) : NULL;
+    ar_[3] = f4 ? new MyThread(f4) : NULL;
+    ar_[4] = f5 ? new MyThread(f5) : NULL;
+  }
+  void Start() {
+    for(int i = 0; i < kSize; i++) {
+      if(ar_[i]) {
+        ar_[i]->Start();
+        usleep(10);
+      }
+    }
+  }
+
+  void Join() {
+    for(int i = 0; i < kSize; i++) {
+      if(ar_[i]) {
+        ar_[i]->Join();
+      }
+    }
+  }
+
+  ~MyThreadArray() {
+    for(int i = 0; i < kSize; i++) {
+      delete ar_[i];
+    }
+  }
+ private:
+  MyThread *ar_[kSize];
+};
+
+
+
+// test00: {{{1
+namespace test00 {
+int     GLOB = 0;
+void Run() {
+  printf("test00: negative\n");
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 00)
+}  // namespace test00
+
+
+// test01: TP. Simple race (write vs write). {{{1
+namespace test01 {
+int     GLOB = 0;
+void Worker() {
+  GLOB = 1; 
+}
+
+void Parent() {
+  MyThread t(Worker);
+  t.Start();
+  GLOB = 2;
+  t.Join();
+}
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test01. TP.");
+  ANNOTATE_TRACE_MEMORY(&GLOB);
+  printf("test01: positive\n");
+  Parent();
+  const int tmp = GLOB;
+  printf("\tGLOB=%d\n", tmp);
+}
+REGISTER_TEST(Run, 1);
+}  // namespace test01
+
+
+// test02: TN. Synchronization via CondVar. {{{1
+namespace test02 {
+int     GLOB = 0;
+// Two write accesses to GLOB are synchronized because 
+// the pair of CV.Signal() and CV.Wait() establish happens-before relation. 
+//
+// Waiter:                      Waker: 
+// 1. COND = 0
+// 2. Start(Waker)              
+// 3. MU.Lock()                 a. write(GLOB)
+//                              b. MU.Lock()
+//                              c. COND = 1
+//                         /--- d. CV.Signal()
+//  4. while(COND)        /     e. MU.Unlock()
+//       CV.Wait(MU) <---/
+//  5. MU.Unlock()
+//  6. write(GLOB)
+Mutex   MU; 
+
+void Waker() {
+  usleep(100000);  // Make sure the waiter blocks.
+  GLOB = 1; 
+
+  MU.Lock();
+  COND = 1;
+  CV.Signal(); 
+  MU.Unlock();
+}
+
+void Waiter() {
+  ThreadPool pool(1);
+  pool.StartWorkers();
+  COND = 0;
+  pool.Add(NewCallback(Waker));
+  MU.Lock();
+  while(COND != 1)
+    CV.Wait(&MU);
+  MU.Unlock();
+  GLOB = 2;
+}
+void Run() {
+  printf("test02: negative\n");
+  Waiter();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 2);
+}  // namespace test02
+
+
+// test03: TN. Synchronization via LockWhen, signaller gets there first. {{{1
+namespace test03 {  
+int     GLOB = 0;
+// Two write accesses to GLOB are synchronized via conditional critical section. 
+// Note that LockWhen() happens first (we use sleep(1) to make sure)! 
+//
+// Waiter:                           Waker: 
+// 1. COND = 0
+// 2. Start(Waker)              
+//                                   a. write(GLOB)
+//                                   b. MU.Lock()
+//                                   c. COND = 1
+//                              /--- d. MU.Unlock()
+// 3. MU.LockWhen(COND==1) <---/     
+// 4. MU.Unlock()
+// 5. write(GLOB)
+Mutex   MU; 
+
+void Waker() {
+  usleep(100000);  // Make sure the waiter blocks.
+  GLOB = 1; 
+
+  MU.Lock();
+  COND = 1; // We are done! Tell the Waiter. 
+  MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
+}
+void Waiter() {
+  ThreadPool pool(1);
+  pool.StartWorkers();
+  COND = 0;
+  pool.Add(NewCallback(Waker));
+  MU.LockWhen(Condition(&ArgIsOne, &COND));  // calls ANNOTATE_CONDVAR_WAIT
+  MU.Unlock();  // Waker is done! 
+
+  GLOB = 2;
+}
+void Run() {
+  printf("test03: negative\n");
+  Waiter();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 3, FEATURE|NEEDS_ANNOTATIONS);
+}  // namespace test03
+
+// test04: TN. Synchronization via PCQ. {{{1
+namespace test04 {
+int     GLOB = 0;
+ProducerConsumerQueue Q(INT_MAX); 
+// Two write accesses to GLOB are separated by PCQ Put/Get. 
+//
+// Putter:                        Getter:
+// 1. write(GLOB)                
+// 2. Q.Put() ---------\          .
+//                      \-------> a. Q.Get()
+//                                b. write(GLOB)
+
+
+void Putter() {
+  GLOB = 1; 
+  Q.Put(NULL);
+}
+
+void Getter() {
+  Q.Get();
+  GLOB = 2;
+}
+
+void Run() {
+  printf("test04: negative\n");
+  MyThreadArray t(Putter, Getter);
+  t.Start(); 
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 4);
+}  // namespace test04
+
+
+// test05: FP. Synchronization via CondVar, but waiter does not block. {{{1
+// Since CondVar::Wait() is not called, we get a false positive. 
+namespace test05 {
+int     GLOB = 0;
+// Two write accesses to GLOB are synchronized via CondVar. 
+// But race detector can not see it. 
+// See this for details: 
+// http://www.valgrind.org/docs/manual/hg-manual.html#hg-manual.effective-use. 
+//
+// Waiter:                                  Waker: 
+// 1. COND = 0                         
+// 2. Start(Waker)                          
+// 3. MU.Lock()                             a. write(GLOB)
+//                                          b. MU.Lock()
+//                                          c. COND = 1
+//                                          d. CV.Signal()
+//  4. while(COND)                          e. MU.Unlock()
+//       CV.Wait(MU) <<< not called   
+//  5. MU.Unlock()      
+//  6. write(GLOB)      
+Mutex   MU; 
+
+void Waker() {
+  GLOB = 1; 
+  MU.Lock();
+  COND = 1;
+  CV.Signal(); 
+  MU.Unlock();
+}
+
+void Waiter() {
+  ThreadPool pool(1);
+  pool.StartWorkers();
+  COND = 0;
+  pool.Add(NewCallback(Waker));
+  usleep(100000);  // Make sure the signaller gets first.
+  MU.Lock();
+  while(COND != 1)
+    CV.Wait(&MU);
+  MU.Unlock();
+  GLOB = 2;
+}
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  if (!Tsan_PureHappensBefore())
+    ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test05. FP. Unavoidable in hybrid scheme.");
+  printf("test05: unavoidable false positive\n");
+  Waiter();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 5);
+}  // namespace test05
+
+
+// test06: TN. Synchronization via CondVar, but Waker gets there first.  {{{1
+namespace test06 {
+int     GLOB = 0;
+// Same as test05 but we annotated the Wait() loop. 
+//
+// Waiter:                                            Waker: 
+// 1. COND = 0                                   
+// 2. Start(Waker)                                    
+// 3. MU.Lock()                                       a. write(GLOB)
+//                                                    b. MU.Lock()
+//                                                    c. COND = 1
+//                                           /------- d. CV.Signal()
+//  4. while(COND)                          /         e. MU.Unlock()
+//       CV.Wait(MU) <<< not called        /
+//  6. ANNOTATE_CONDVAR_WAIT(CV, MU) <----/
+//  5. MU.Unlock()      
+//  6. write(GLOB)      
+
+Mutex   MU; 
+
+void Waker() {
+  GLOB = 1; 
+  MU.Lock();
+  COND = 1;
+  CV.Signal(); 
+  MU.Unlock();
+}
+
+void Waiter() {
+  ThreadPool pool(1);
+  pool.StartWorkers();
+  COND = 0;
+  pool.Add(NewCallback(Waker));
+  usleep(100000);  // Make sure the signaller gets first.
+  MU.Lock();
+  while(COND != 1)
+    CV.Wait(&MU);
+  ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
+
+  MU.Unlock();
+  GLOB = 2;
+}
+void Run() {
+  printf("test06: negative\n");
+  Waiter();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 6, FEATURE|NEEDS_ANNOTATIONS);
+}  // namespace test06
+
+
+// test07: TN. Synchronization via LockWhen(), Signaller is observed first. {{{1
+namespace test07 {  
+int     GLOB = 0;
+bool    COND = 0;
+// Two write accesses to GLOB are synchronized via conditional critical section.
+// LockWhen() is observed after COND has been set (due to sleep). 
+// Unlock() calls ANNOTATE_CONDVAR_SIGNAL().
+//
+// Waiter:                           Signaller: 
+// 1. COND = 0
+// 2. Start(Signaller)              
+//                                   a. write(GLOB)
+//                                   b. MU.Lock()
+//                                   c. COND = 1
+//                              /--- d. MU.Unlock calls ANNOTATE_CONDVAR_SIGNAL
+// 3. MU.LockWhen(COND==1) <---/
+// 4. MU.Unlock()
+// 5. write(GLOB)
+
+Mutex   MU; 
+void Signaller() {
+  GLOB = 1; 
+  MU.Lock();
+  COND = true; // We are done! Tell the Waiter. 
+  MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
+}
+void Waiter() {
+  COND = false;
+  MyThread t(Signaller);
+  t.Start();
+  usleep(100000);  // Make sure the signaller gets there first.
+  
+  MU.LockWhen(Condition(&ArgIsTrue, &COND));  // calls ANNOTATE_CONDVAR_WAIT
+  MU.Unlock();  // Signaller is done! 
+  
+  GLOB = 2; // If LockWhen didn't catch the signal, a race may be reported here.
+  t.Join();
+}
+void Run() {
+  printf("test07: negative\n");
+  Waiter();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 7, FEATURE|NEEDS_ANNOTATIONS);
+}  // namespace test07
+
+// test08: TN. Synchronization via thread start/join. {{{1
+namespace test08 {
+int     GLOB = 0;
+// Three accesses to GLOB are separated by thread start/join. 
+//
+// Parent:                        Worker:
+// 1. write(GLOB)
+// 2. Start(Worker) ------------>
+//                                a. write(GLOB)
+// 3. Join(Worker) <------------
+// 4. write(GLOB)
+void Worker() {
+  GLOB = 2; 
+}
+
+void Parent() {
+  MyThread t(Worker);
+  GLOB = 1;
+  t.Start();
+  t.Join();
+  GLOB = 3;
+}
+void Run() {
+  printf("test08: negative\n");
+  Parent();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 8);
+}  // namespace test08
+
+
+// test09: TP. Simple race (read vs write). {{{1
+namespace test09 {
+int     GLOB = 0;
+// A simple data race between writer and reader. 
+// Write happens after read (enforced by sleep). 
+// Usually, easily detectable by a race detector. 
+void Writer() {
+  usleep(100000);
+  GLOB = 3; 
+}
+void Reader() {
+  CHECK(GLOB != -777);
+}
+
+void Run() {
+  ANNOTATE_TRACE_MEMORY(&GLOB);
+  FAST_MODE_INIT(&GLOB);
+  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test09. TP.");
+  printf("test09: positive\n");
+  MyThreadArray t(Writer, Reader);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 9);
+}  // namespace test09
+
+
+// test10: FN. Simple race (write vs read). {{{1
+namespace test10 {
+int     GLOB = 0;
+// A simple data race between writer and reader. 
+// Write happens before Read (enforced by sleep), 
+// otherwise this test is the same as test09. 
+// 
+// Writer:                    Reader:
+// 1. write(GLOB)             a. sleep(long enough so that GLOB 
+//                                is most likely initialized by Writer)
+//                            b. read(GLOB)
+// 
+//
+// Eraser algorithm does not detect the race here, 
+// see Section 2.2 of http://citeseer.ist.psu.edu/savage97eraser.html. 
+//
+void Writer() {
+  GLOB = 3; 
+}
+void Reader() {
+  usleep(100000);
+  CHECK(GLOB != -777);
+}
+
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test10. TP. FN in MSMHelgrind.");
+  printf("test10: positive\n");
+  MyThreadArray t(Writer, Reader);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 10);
+}  // namespace test10
+
+
+// test11: FP. Synchronization via CondVar, 2 workers. {{{1
+// This test is properly synchronized, but currently (Dec 2007) 
+// helgrind reports a false positive. 
+//
+// Parent:                              Worker1, Worker2: 
+// 1. Start(workers)                    a. read(GLOB)
+// 2. MU.Lock()                         b. MU.Lock()
+// 3. while(COND != 2)        /-------- c. CV.Signal()
+//      CV.Wait(&MU) <-------/          d. MU.Unlock()
+// 4. MU.Unlock()
+// 5. write(GLOB) 
+//
+namespace test11 {
+int     GLOB = 0;
+Mutex   MU; 
+void Worker() {
+  usleep(200000);
+  CHECK(GLOB != 777); 
+
+  MU.Lock();
+  COND++;
+  CV.Signal();
+  MU.Unlock();
+}
+
+void Parent() {
+  COND = 0;
+
+  MyThreadArray t(Worker, Worker);
+  t.Start();
+
+  MU.Lock();
+  while(COND != 2) {
+    CV.Wait(&MU);
+  }
+  MU.Unlock();
+
+  GLOB = 2;
+
+  t.Join();
+}
+
+void Run() {
+//  ANNOTATE_EXPECT_RACE(&GLOB, "test11. FP. Fixed by MSMProp1.");
+  printf("test11: negative\n");
+  Parent();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 11);
+}  // namespace test11
+
+
+// test12: FP. Synchronization via Mutex, then via PCQ. {{{1
+namespace test12 {
+int     GLOB = 0;
+// This test is properly synchronized, but currently (Dec 2007) 
+// helgrind reports a false positive. 
+//
+// First, we write to GLOB under MU, then we synchronize via PCQ, 
+// which is essentially a semaphore. 
+//
+// Putter:                       Getter:
+// 1. MU.Lock()                  a. MU.Lock()
+// 2. write(GLOB) <---- MU ----> b. write(GLOB)
+// 3. MU.Unlock()                c. MU.Unlock()
+// 4. Q.Put()   ---------------> d. Q.Get()
+//                               e. write(GLOB)
+                               
+ProducerConsumerQueue Q(INT_MAX);
+Mutex   MU; 
+
+void Putter() {
+  MU.Lock();
+  GLOB++; 
+  MU.Unlock();
+
+  Q.Put(NULL);
+}
+
+void Getter() {
+  MU.Lock();
+  GLOB++; 
+  MU.Unlock();
+
+  Q.Get();
+  GLOB++;
+}
+
+void Run() {
+//  ANNOTATE_EXPECT_RACE(&GLOB, "test12. FP. Fixed by MSMProp1.");
+  printf("test12: negative\n");
+  MyThreadArray t(Putter, Getter);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 12);
+}  // namespace test12
+
+
+// test13: FP. Synchronization via Mutex, then via LockWhen. {{{1
+namespace test13 { 
+int     GLOB = 0;
+// This test is essentially the same as test12, but uses LockWhen 
+// instead of PCQ.
+//
+// Waker:                                     Waiter:
+// 1. MU.Lock()                               a. MU.Lock()
+// 2. write(GLOB) <---------- MU ---------->  b. write(GLOB)
+// 3. MU.Unlock()                             c. MU.Unlock()
+// 4. MU.Lock()                               .
+// 5. COND = 1                                .
+// 6. ANNOTATE_CONDVAR_SIGNAL -------\        .        
+// 7. MU.Unlock()                     \       .
+//                                     \----> d. MU.LockWhen(COND == 1)
+//                                            e. MU.Unlock()
+//                                            f. write(GLOB)
+Mutex   MU; 
+
+void Waker() {
+  MU.Lock();
+  GLOB++; 
+  MU.Unlock();
+
+  MU.Lock();
+  COND = 1;
+  ANNOTATE_CONDVAR_SIGNAL(&MU);
+  MU.Unlock();
+}
+
+void Waiter() {
+  MU.Lock();
+  GLOB++; 
+  MU.Unlock();
+
+  MU.LockWhen(Condition(&ArgIsOne, &COND));
+  MU.Unlock();
+  GLOB++;
+}
+
+void Run() {
+//  ANNOTATE_EXPECT_RACE(&GLOB, "test13. FP. Fixed by MSMProp1.");
+  printf("test13: negative\n");
+  COND = 0;
+
+  MyThreadArray t(Waker, Waiter);
+  t.Start();
+  t.Join();
+
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 13, FEATURE|NEEDS_ANNOTATIONS);
+}  // namespace test13
+
+
+// test14: FP. Synchronization via PCQ, reads, 2 workers. {{{1
+namespace test14 {
+int     GLOB = 0;
+// This test is properly synchronized, but currently (Dec 2007) 
+// helgrind reports a false positive. 
+//
+// This test is similar to test11, but uses PCQ (semaphore). 
+//
+// Putter2:                  Putter1:                     Getter: 
+// 1. read(GLOB)             a. read(GLOB)
+// 2. Q2.Put() ----\         b. Q1.Put() -----\           .
+//                  \                          \--------> A. Q1.Get()
+//                   \----------------------------------> B. Q2.Get()
+//                                                        C. write(GLOB)
+ProducerConsumerQueue Q1(INT_MAX), Q2(INT_MAX);
+
+void Putter1() {
+  CHECK(GLOB != 777);
+  Q1.Put(NULL);
+}
+void Putter2() {
+  CHECK(GLOB != 777);
+  Q2.Put(NULL);
+}
+void Getter() {
+  Q1.Get();
+  Q2.Get(); 
+  GLOB++;
+}
+void Run() {
+//  ANNOTATE_EXPECT_RACE(&GLOB, "test14. FP. Fixed by MSMProp1.");
+  printf("test14: negative\n");
+  MyThreadArray t(Getter, Putter1, Putter2);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 14);
+}  // namespace test14
+
+
+// test15: TN. Synchronization via LockWhen. One waker and 2 waiters. {{{1
+namespace test15 {
+// Waker:                                   Waiter1, Waiter2:
+// 1. write(GLOB)
+// 2. MU.Lock()
+// 3. COND = 1
+// 4. ANNOTATE_CONDVAR_SIGNAL ------------> a. MU.LockWhen(COND == 1)
+// 5. MU.Unlock()                           b. MU.Unlock()
+//                                          c. read(GLOB)
+
+int     GLOB = 0;
+Mutex   MU; 
+
+void Waker() {
+  GLOB = 2;
+
+  MU.Lock();
+  COND = 1;
+  ANNOTATE_CONDVAR_SIGNAL(&MU);
+  MU.Unlock();
+};
+
+void Waiter() {
+  MU.LockWhen(Condition(&ArgIsOne, &COND));
+  MU.Unlock();
+  CHECK(GLOB != 777);
+}
+
+
+void Run() {
+  COND = 0;
+  printf("test15: negative\n");
+  MyThreadArray t(Waker, Waiter, Waiter);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 15);
+}  // namespace test15
+
+
+// test16: FP. Barrier (emulated by CV), 2 threads. {{{1
+namespace test16 {
+// Worker1:                                     Worker2:
+// 1. MU.Lock()                                 a. MU.Lock()
+// 2. write(GLOB) <------------ MU ---------->  b. write(GLOB)
+// 3. MU.Unlock()                               c. MU.Unlock()
+// 4. MU2.Lock()                                d. MU2.Lock()
+// 5. COND--                                    e. COND--
+// 6. ANNOTATE_CONDVAR_SIGNAL(MU2) ---->V       .
+// 7. MU2.Await(COND == 0) <------------+------ f. ANNOTATE_CONDVAR_SIGNAL(MU2)
+// 8. MU2.Unlock()                      V-----> g. MU2.Await(COND == 0)
+// 9. read(GLOB)                                h. MU2.Unlock()
+//                                              i. read(GLOB)
+//
+//
+// TODO: This way we may create too many edges in happens-before graph. 
+// Arndt Mühlenfeld in his PhD (TODO: link) suggests creating special nodes in 
+// happens-before graph to reduce the total number of edges. 
+// See figure 3.14. 
+//
+//
+int     GLOB = 0;
+Mutex   MU; 
+Mutex MU2; 
+
+void Worker() {
+  MU.Lock();
+  GLOB++; 
+  MU.Unlock();
+
+  MU2.Lock(); 
+  COND--;
+  ANNOTATE_CONDVAR_SIGNAL(&MU2);
+  MU2.Await(Condition(&ArgIsZero, &COND));
+  MU2.Unlock();
+
+  CHECK(GLOB == 2);
+}
+
+void Run() {
+//  ANNOTATE_EXPECT_RACE(&GLOB, "test16. FP. Fixed by MSMProp1 + Barrier support.");
+  COND = 2;
+  printf("test16: negative\n");
+  MyThreadArray t(Worker, Worker);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 16, FEATURE|NEEDS_ANNOTATIONS);
+}  // namespace test16
+
+
+// test17: FP. Barrier (emulated by CV), 3 threads. {{{1
+namespace test17 {
+// Same as test16, but with 3 threads.
+int     GLOB = 0;
+Mutex   MU; 
+Mutex MU2; 
+
+void Worker() {
+  MU.Lock();
+  GLOB++; 
+  MU.Unlock();
+
+  MU2.Lock(); 
+  COND--;
+  ANNOTATE_CONDVAR_SIGNAL(&MU2);
+  MU2.Await(Condition(&ArgIsZero, &COND));
+  MU2.Unlock();
+
+  CHECK(GLOB == 3);
+}
+
+void Run() {
+//  ANNOTATE_EXPECT_RACE(&GLOB, "test17. FP. Fixed by MSMProp1 + Barrier support.");
+  COND = 3;
+  printf("test17: negative\n");
+  MyThreadArray t(Worker, Worker, Worker);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 17, FEATURE|NEEDS_ANNOTATIONS);
+}  // namespace test17
+
+
+// test18: TN. Synchronization via Await(), signaller gets there first. {{{1
+namespace test18 {  
+int     GLOB = 0;
+Mutex   MU; 
+// Same as test03, but uses Mutex::Await() instead of Mutex::LockWhen(). 
+
+void Waker() {
+  usleep(100000);  // Make sure the waiter blocks.
+  GLOB = 1; 
+
+  MU.Lock();
+  COND = 1; // We are done! Tell the Waiter. 
+  MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
+}
+void Waiter() {
+  ThreadPool pool(1);
+  pool.StartWorkers();
+  COND = 0;
+  pool.Add(NewCallback(Waker));
+
+  MU.Lock();
+  MU.Await(Condition(&ArgIsOne, &COND));  // calls ANNOTATE_CONDVAR_WAIT
+  MU.Unlock();  // Waker is done! 
+
+  GLOB = 2;
+}
+void Run() {
+  printf("test18: negative\n");
+  Waiter();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 18, FEATURE|NEEDS_ANNOTATIONS);
+}  // namespace test18
+
+// test19: TN. Synchronization via AwaitWithTimeout(). {{{1
+namespace test19 {  
+int     GLOB = 0;
+// Same as test18, but with AwaitWithTimeout. Do not timeout. 
+Mutex   MU; 
+void Waker() {
+  usleep(100000);  // Make sure the waiter blocks.
+  GLOB = 1; 
+
+  MU.Lock();
+  COND = 1; // We are done! Tell the Waiter. 
+  MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
+}
+void Waiter() {
+  ThreadPool pool(1);
+  pool.StartWorkers();
+  COND = 0;
+  pool.Add(NewCallback(Waker));
+
+  MU.Lock();
+  CHECK(MU.AwaitWithTimeout(Condition(&ArgIsOne, &COND), INT_MAX));
+  MU.Unlock();
+
+  GLOB = 2;
+}
+void Run() {
+  printf("test19: negative\n");
+  Waiter();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 19, FEATURE|NEEDS_ANNOTATIONS);
+}  // namespace test19
+
+// test20: TP. Incorrect synchronization via AwaitWhen(), timeout. {{{1
+namespace test20 {  
+int     GLOB = 0;
+Mutex   MU; 
+// True race. We timeout in AwaitWhen.
+void Waker() {
+  GLOB = 1; 
+  usleep(100 * 1000);
+}
+void Waiter() {
+  ThreadPool pool(1);
+  pool.StartWorkers();
+  COND = 0;
+  pool.Add(NewCallback(Waker));
+
+  MU.Lock();
+  CHECK(!MU.AwaitWithTimeout(Condition(&ArgIsOne, &COND), 100));
+  MU.Unlock();
+
+  GLOB = 2;
+}
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test20. TP.");
+  printf("test20: positive\n");
+  Waiter();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 20, FEATURE|NEEDS_ANNOTATIONS);
+}  // namespace test20
+
+// test21: TP. Incorrect synchronization via LockWhenWithTimeout(). {{{1
+namespace test21 {  
+int     GLOB = 0;
+// True race. We timeout in LockWhenWithTimeout().
+Mutex   MU; 
+void Waker() {
+  GLOB = 1; 
+  usleep(100 * 1000);
+}
+void Waiter() {
+  ThreadPool pool(1);
+  pool.StartWorkers();
+  COND = 0;
+  pool.Add(NewCallback(Waker));
+
+  CHECK(!MU.LockWhenWithTimeout(Condition(&ArgIsOne, &COND), 100));
+  MU.Unlock();
+
+  GLOB = 2;
+}
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test21. TP.");
+  printf("test21: positive\n");
+  Waiter();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 21, FEATURE|NEEDS_ANNOTATIONS);
+}  // namespace test21
+
+// test22: TP. Incorrect synchronization via CondVar::WaitWithTimeout(). {{{1
+namespace test22 {  
+int     GLOB = 0;
+Mutex   MU; 
+// True race. We timeout in CondVar::WaitWithTimeout().
+void Waker() {
+  GLOB = 1; 
+  usleep(100 * 1000);
+}
+void Waiter() {
+  ThreadPool pool(1);
+  pool.StartWorkers();
+  COND = 0;
+  pool.Add(NewCallback(Waker));
+
+  int64_t ms_left_to_wait = 100; 
+  int64_t deadline_ms = GetCurrentTimeMillis() + ms_left_to_wait;
+  MU.Lock();
+  while(COND != 1 && ms_left_to_wait > 0) {
+    CV.WaitWithTimeout(&MU, ms_left_to_wait);
+    ms_left_to_wait = deadline_ms - GetCurrentTimeMillis();
+  }
+  MU.Unlock();
+
+  GLOB = 2;
+}
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test22. TP.");
+  printf("test22: positive\n");
+  Waiter();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 22);
+}  // namespace test22
+
+// test23: TN. TryLock, ReaderLock, ReaderTryLock. {{{1
+namespace test23 {  
+// Correct synchronization with TryLock, Lock, ReaderTryLock, ReaderLock. 
+int     GLOB = 0;
+Mutex   MU; 
+void Worker_TryLock() {
+  for (int i = 0; i < 20; i++) {
+    while (true) {
+      if (MU.TryLock()) {
+        GLOB++; 
+        MU.Unlock();
+        break;
+      }
+      usleep(1000);
+    }
+  }
+}
+
+void Worker_ReaderTryLock() {
+  for (int i = 0; i < 20; i++) {
+    while (true) {
+      if (MU.ReaderTryLock()) {
+        CHECK(GLOB != 777); 
+        MU.ReaderUnlock();
+        break;
+      }
+      usleep(1000);
+    }
+  }
+}
+
+void Worker_ReaderLock() {
+  for (int i = 0; i < 20; i++) {
+    MU.ReaderLock();
+    CHECK(GLOB != 777); 
+    MU.ReaderUnlock();
+    usleep(1000);
+  }
+}
+
+void Worker_Lock() {
+  for (int i = 0; i < 20; i++) {
+    MU.Lock();
+    GLOB++;
+    MU.Unlock();
+    usleep(1000);
+  }
+}
+
+void Run() {
+  printf("test23: negative\n");
+  MyThreadArray t(Worker_TryLock, 
+                  Worker_ReaderTryLock, 
+                  Worker_ReaderLock,
+                  Worker_Lock
+                  );
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 23);
+}  // namespace test23
+
+// test24: TN. Synchronization via ReaderLockWhen(). {{{1
+namespace test24 {  
+int     GLOB = 0;
+Mutex   MU; 
+// Same as test03, but uses ReaderLockWhen(). 
+
+void Waker() {
+  usleep(100000);  // Make sure the waiter blocks.
+  GLOB = 1; 
+
+  MU.Lock();
+  COND = 1; // We are done! Tell the Waiter. 
+  MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
+}
+void Waiter() {
+  ThreadPool pool(1);
+  pool.StartWorkers();
+  COND = 0;
+  pool.Add(NewCallback(Waker));
+  MU.ReaderLockWhen(Condition(&ArgIsOne, &COND));
+  MU.ReaderUnlock();
+
+  GLOB = 2;
+}
+void Run() {
+  printf("test24: negative\n");
+  Waiter();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 24, FEATURE|NEEDS_ANNOTATIONS);
+}  // namespace test24
+
+// test25: TN. Synchronization via ReaderLockWhenWithTimeout(). {{{1
+namespace test25 {  
+int     GLOB = 0;
+Mutex   MU; 
+// Same as test24, but uses ReaderLockWhenWithTimeout(). 
+// We do not timeout. 
+
+void Waker() {
+  usleep(100000);  // Make sure the waiter blocks.
+  GLOB = 1; 
+
+  MU.Lock();
+  COND = 1; // We are done! Tell the Waiter. 
+  MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
+}
+void Waiter() {
+  ThreadPool pool(1);
+  pool.StartWorkers();
+  COND = 0;
+  pool.Add(NewCallback(Waker));
+  CHECK(MU.ReaderLockWhenWithTimeout(Condition(&ArgIsOne, &COND), INT_MAX));
+  MU.ReaderUnlock();
+
+  GLOB = 2;
+}
+void Run() {
+  printf("test25: negative\n");
+  Waiter();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 25, FEATURE|NEEDS_ANNOTATIONS);
+}  // namespace test25
+
+// test26: TP. Incorrect synchronization via ReaderLockWhenWithTimeout(). {{{1
+namespace test26 {  
+int     GLOB = 0;
+Mutex   MU; 
+// Same as test25, but we timeout and incorrectly assume happens-before. 
+
+void Waker() {
+  GLOB = 1; 
+  usleep(10000);
+}
+void Waiter() {
+  ThreadPool pool(1);
+  pool.StartWorkers();
+  COND = 0;
+  pool.Add(NewCallback(Waker));
+  CHECK(!MU.ReaderLockWhenWithTimeout(Condition(&ArgIsOne, &COND), 100));
+  MU.ReaderUnlock();
+
+  GLOB = 2;
+}
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test26. TP");
+  printf("test26: positive\n");
+  Waiter();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 26, FEATURE|NEEDS_ANNOTATIONS);
+}  // namespace test26
+
+
+// test27: TN. Simple synchronization via SpinLock. {{{1
+namespace test27 {
+#ifndef NO_SPINLOCK
+int     GLOB = 0;
+SpinLock MU;
+void Worker() {
+  MU.Lock();
+  GLOB++; 
+  MU.Unlock();
+  usleep(10000);
+}
+
+void Run() {
+  printf("test27: negative\n");
+  MyThreadArray t(Worker, Worker, Worker, Worker);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 27, FEATURE|NEEDS_ANNOTATIONS);
+#endif // NO_SPINLOCK
+}  // namespace test27
+
+
+// test28: TN. Synchronization via Mutex, then PCQ. 3 threads {{{1
+namespace test28 {
+// Putter1:                       Getter:                         Putter2:        
+// 1. MU.Lock()                                                   A. MU.Lock()
+// 2. write(GLOB)                                                 B. write(GLOB)
+// 3. MU.Unlock()                                                 C. MU.Unlock()
+// 4. Q.Put() ---------\                                 /------- D. Q.Put()
+// 5. MU.Lock()         \-------> a. Q.Get()            /         E. MU.Lock()
+// 6. read(GLOB)                  b. Q.Get() <---------/          F. read(GLOB)
+// 7. MU.Unlock()                   (sleep)                       G. MU.Unlock()
+//                                c. read(GLOB)
+ProducerConsumerQueue Q(INT_MAX);
+int     GLOB = 0;
+Mutex   MU; 
+
+void Putter() {
+  MU.Lock();
+  GLOB++;
+  MU.Unlock();
+
+  Q.Put(NULL);
+
+  MU.Lock();
+  CHECK(GLOB != 777);
+  MU.Unlock();
+}
+
+void Getter() {
+  Q.Get();
+  Q.Get();
+  usleep(100000);
+  CHECK(GLOB == 2);
+}
+
+void Run() {
+  printf("test28: negative\n");
+  MyThreadArray t(Getter, Putter, Putter);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 28);
+}  // namespace test28
+
+
+// test29: TN. Synchronization via Mutex, then PCQ. 4 threads. {{{1
+namespace test29 {
+// Similar to test28, but has two Getters and two PCQs. 
+ProducerConsumerQueue *Q1, *Q2;
+Mutex   MU; 
+int     GLOB = 0;
+
+void Putter(ProducerConsumerQueue *q) {
+  MU.Lock();
+  GLOB++;
+  MU.Unlock();
+
+  q->Put(NULL);
+  q->Put(NULL);
+
+  MU.Lock();
+  CHECK(GLOB != 777);
+  MU.Unlock();
+
+}
+
+void Putter1() { Putter(Q1); }
+void Putter2() { Putter(Q2); }
+
+void Getter() {
+  Q1->Get();
+  Q2->Get();
+  usleep(100000);
+  CHECK(GLOB == 2);
+  usleep(48000); //  TODO: remove this when FP in test32 is fixed. 
+}
+
+void Run() {
+  printf("test29: negative\n");
+  Q1 = new ProducerConsumerQueue(INT_MAX);
+  Q2 = new ProducerConsumerQueue(INT_MAX);
+  MyThreadArray t(Getter, Getter, Putter1, Putter2);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+  delete Q1;
+  delete Q2;
+}
+REGISTER_TEST(Run, 29);
+}  // namespace test29
+
+
+// test30: TN. Synchronization via 'safe' race. Writer vs multiple Readers. {{{1
+namespace test30 {
+// This test shows a very risky kind of synchronization which is very easy 
+// to get wrong. Actually, I am not sure I've got it right. 
+//
+// Writer:                                 Reader1, Reader2, ..., ReaderN: 
+// 1. write(GLOB[i]: i >= BOUNDARY)        a. n = BOUNDARY
+// 2. HAPPENS_BEFORE(BOUNDARY+1)  -------> b. HAPPENS_AFTER(n)
+// 3. BOUNDARY++;                          c. read(GLOB[i]: i < n)
+//
+// Here we have a 'safe' race on accesses to BOUNDARY and 
+// no actual races on accesses to GLOB[]: 
+// Writer writes to GLOB[i] where i>=BOUNDARY and then increments BOUNDARY. 
+// Readers read BOUNDARY and read GLOB[i] where i<BOUNDARY. 
+//
+// I am not completely sure that this scheme guaranties no race between 
+// accesses to GLOB since compilers and CPUs 
+// are free to rearrange memory operations. 
+// I am actually sure that this scheme is wrong unless we use 
+// some smart memory fencing... 
+
+
+const int N = 48;
+static int GLOB[N];
+volatile int BOUNDARY = 0;
+
+void Writer() {
+  for (int i = 0; i < N; i++) {
+    CHECK(BOUNDARY == i);
+    for (int j = i; j < N; j++) {
+      GLOB[j] = j;
+    }
+    ANNOTATE_HAPPENS_BEFORE(reinterpret_cast<void*>(BOUNDARY+1));
+    BOUNDARY++;
+    usleep(1000);
+  }
+}
+
+void Reader() {
+  int n;
+  do {
+    n = BOUNDARY;
+    if (n == 0) continue; 
+    ANNOTATE_HAPPENS_AFTER(reinterpret_cast<void*>(n));
+    for (int i = 0; i < n; i++) {
+      CHECK(GLOB[i] == i);
+    }
+    usleep(100);
+  } while(n < N);
+}
+
+void Run() {
+  FAST_MODE_INIT(&BOUNDARY);
+  ANNOTATE_EXPECT_RACE((void*)(&BOUNDARY), "test30. Sync via 'safe' race.");
+  printf("test30: negative\n");
+  MyThreadArray t(Writer, Reader, Reader, Reader);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB[N-1]);
+}
+REGISTER_TEST2(Run, 30, FEATURE|NEEDS_ANNOTATIONS);
+}  // namespace test30
+
+
+// test31: TN. Synchronization via 'safe' race. Writer vs Writer. {{{1
+namespace test31 {
+// This test is similar to test30, but 
+// it has one Writer instead of mulitple Readers. 
+//
+// Writer1:                                Writer2 
+// 1. write(GLOB[i]: i >= BOUNDARY)        a. n = BOUNDARY
+// 2. HAPPENS_BEFORE(BOUNDARY+1)  -------> b. HAPPENS_AFTER(n)
+// 3. BOUNDARY++;                          c. write(GLOB[i]: i < n)
+//
+
+const int N = 48;
+static int GLOB[N];
+volatile int BOUNDARY = 0;
+
+void Writer1() {
+  for (int i = 0; i < N; i++) {
+    CHECK(BOUNDARY == i);
+    for (int j = i; j < N; j++) {
+      GLOB[j] = j;
+    }
+    ANNOTATE_HAPPENS_BEFORE(reinterpret_cast<void*>(BOUNDARY+1));
+    BOUNDARY++;
+    usleep(1000);
+  }
+}
+
+void Writer2() {
+  int n;
+  do {
+    n = BOUNDARY;
+    if (n == 0) continue; 
+    ANNOTATE_HAPPENS_AFTER(reinterpret_cast<void*>(n));
+    for (int i = 0; i < n; i++) {
+      if(GLOB[i] == i) {
+        GLOB[i]++;
+      }
+    }
+    usleep(100);
+  } while(n < N);
+}
+
+void Run() {
+  FAST_MODE_INIT(&BOUNDARY);
+  ANNOTATE_EXPECT_RACE((void*)(&BOUNDARY), "test31. Sync via 'safe' race.");
+  printf("test31: negative\n");
+  MyThreadArray t(Writer1, Writer2);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB[N-1]);
+}
+REGISTER_TEST2(Run, 31, FEATURE|NEEDS_ANNOTATIONS);
+}  // namespace test31
+
+
+// test32: FP. Synchronization via thread create/join. W/R. {{{1
+namespace test32 {
+// This test is well synchronized but helgrind 3.3.0 reports a race. 
+//
+// Parent:                   Writer:               Reader:  
+// 1. Start(Reader) -----------------------\       .
+//                                          \      .
+// 2. Start(Writer) ---\                     \     .
+//                      \---> a. MU.Lock()    \--> A. sleep(long enough)
+//                            b. write(GLOB)     
+//                      /---- c. MU.Unlock()
+// 3. Join(Writer) <---/                           
+//                                                 B. MU.Lock()
+//                                                 C. read(GLOB)
+//                                   /------------ D. MU.Unlock()
+// 4. Join(Reader) <----------------/
+// 5. write(GLOB)
+//
+//
+// The call to sleep() in Reader is not part of synchronization, 
+// it is required to trigger the false positive in helgrind 3.3.0. 
+//
+int     GLOB = 0;
+Mutex   MU; 
+
+void Writer() {
+  MU.Lock();
+  GLOB = 1;
+  MU.Unlock();
+}
+
+void Reader() {
+  usleep(480000);
+  MU.Lock();
+  CHECK(GLOB != 777);
+  MU.Unlock();
+}
+
+void Parent() {
+  MyThread r(Reader);
+  MyThread w(Writer);
+  r.Start(); 
+  w.Start();
+
+  w.Join();  // 'w' joins first. 
+  r.Join(); 
+
+  GLOB = 2;
+}
+
+void Run() {
+//  ANNOTATE_EXPECT_RACE(&GLOB, "test32. FP. Fixed by MSMProp1.");
+  printf("test32: negative\n");
+  Parent();
+  printf("\tGLOB=%d\n", GLOB);
+}
+
+REGISTER_TEST(Run, 32);
+}  // namespace test32
+
+
+// test33: STAB. Stress test for the number of thread sets (TSETs). {{{1
+namespace test33 {
+int     GLOB = 0;
+// Here we access N memory locations from within log(N) threads. 
+// We do it in such a way that helgrind creates nearly all possible TSETs. 
+// Then we join all threads and start again (N_iter times). 
+const int N_iter = 48;
+const int Nlog  = 15;
+const int N     = 1 << Nlog;
+static int ARR[N];
+Mutex   MU; 
+
+void Worker() {
+  MU.Lock();
+  int n = ++GLOB;
+  MU.Unlock();
+
+  n %= Nlog;
+  for (int i = 0; i < N; i++) {
+    // ARR[i] is accessed by threads from i-th subset 
+    if (i & (1 << n)) {
+        CHECK(ARR[i] == 0);
+    }
+  }
+}
+
+void Run() {
+  printf("test33:\n");
+
+  std::vector<MyThread*> vec(Nlog);
+
+  for (int j = 0; j < N_iter; j++) {
+    // Create and start Nlog threads
+    for (int i = 0; i < Nlog; i++) {
+      vec[i] = new MyThread(Worker);
+    }
+    for (int i = 0; i < Nlog; i++) {
+      vec[i]->Start();
+    }
+    // Join all threads. 
+    for (int i = 0; i < Nlog; i++) {
+      vec[i]->Join();
+      delete vec[i];
+    }
+    printf("------------------\n");
+  }
+
+  printf("\tGLOB=%d; ARR[1]=%d; ARR[7]=%d; ARR[N-1]=%d\n", 
+         GLOB, ARR[1], ARR[7], ARR[N-1]);
+}
+REGISTER_TEST2(Run, 33, STABILITY|EXCLUDE_FROM_ALL);
+}  // namespace test33
+
+
+// test34: STAB. Stress test for the number of locks sets (LSETs). {{{1
+namespace test34 {
+// Similar to test33, but for lock sets. 
+int     GLOB = 0;
+const int N_iter = 48;
+const int Nlog = 10;
+const int N    = 1 << Nlog;
+static int ARR[N];
+static Mutex *MUs[Nlog];
+
+void Worker() {
+    for (int i = 0; i < N; i++) {
+      // ARR[i] is protected by MUs from i-th subset of all MUs
+      for (int j = 0; j < Nlog; j++)  if (i & (1 << j)) MUs[j]->Lock();
+      CHECK(ARR[i] == 0);
+      for (int j = 0; j < Nlog; j++)  if (i & (1 << j)) MUs[j]->Unlock();
+    }
+}
+
+void Run() {
+  printf("test34:\n");
+  for (int iter = 0; iter < N_iter; iter++) {
+    for (int i = 0; i < Nlog; i++) {
+      MUs[i] = new Mutex;
+    }
+    MyThreadArray t(Worker, Worker);
+    t.Start();
+    t.Join();
+    for (int i = 0; i < Nlog; i++) {
+      delete MUs[i];
+    }
+    printf("------------------\n");
+  }
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 34, STABILITY|EXCLUDE_FROM_ALL);
+}  // namespace test34
+
+
+// test35: PERF. Lots of mutexes and lots of call to free().  {{{1
+namespace test35 {
+// Helgrind 3.3.0 has very slow in shadow_mem_make_NoAccess(). Fixed locally.
+// With the fix helgrind runs this test about a minute.  
+// Without the fix -- about 5 minutes. (on c2d 2.4GHz). 
+//
+// TODO: need to figure out the best way for performance testing. 
+int **ARR; 
+const int N_mu   = 25000;
+const int N_free = 48000;
+
+void Worker() {
+  for (int i = 0; i < N_free; i++) 
+    CHECK(777 == *ARR[i]);
+}
+
+void Run() {
+  printf("test35:\n");
+  std::vector<Mutex*> mus;
+
+  ARR = new int *[N_free];
+  for (int i = 0; i < N_free; i++) {
+    const int c = N_free / N_mu;
+    if ((i % c) == 0) {
+      mus.push_back(new Mutex);
+      mus.back()->Lock();
+      mus.back()->Unlock();
+    }
+    ARR[i] = new int(777);
+  }
+
+  // Need to put all ARR[i] into shared state in order 
+  // to trigger the performance bug. 
+  MyThreadArray t(Worker, Worker);
+  t.Start();
+  t.Join();
+  
+  for (int i = 0; i < N_free; i++) delete ARR[i];
+  delete [] ARR;
+  
+  for (size_t i = 0; i < mus.size(); i++) {
+    delete mus[i];
+  }
+}
+REGISTER_TEST2(Run, 35, PERFORMANCE|EXCLUDE_FROM_ALL);
+}  // namespace test35
+
+
+// test36: TN. Synchronization via Mutex, then PCQ. 3 threads. W/W {{{1
+namespace test36 {
+// variation of test28 (W/W instead of W/R) 
+
+// Putter1:                       Getter:                         Putter2:        
+// 1. MU.Lock();                                                  A. MU.Lock()
+// 2. write(GLOB)                                                 B. write(GLOB)
+// 3. MU.Unlock()                                                 C. MU.Unlock()
+// 4. Q.Put() ---------\                                 /------- D. Q.Put()
+// 5. MU1.Lock()        \-------> a. Q.Get()            /         E. MU1.Lock()  
+// 6. MU.Lock()                   b. Q.Get() <---------/          F. MU.Lock()   
+// 7. write(GLOB)                                                 G. write(GLOB) 
+// 8. MU.Unlock()                                                 H. MU.Unlock() 
+// 9. MU1.Unlock()                  (sleep)                       I. MU1.Unlock()
+//                                c. MU1.Lock()   
+//                                d. write(GLOB)  
+//                                e. MU1.Unlock() 
+ProducerConsumerQueue Q(INT_MAX);
+int     GLOB = 0;
+Mutex   MU, MU1; 
+
+void Putter() {
+  MU.Lock();
+  GLOB++;
+  MU.Unlock();
+
+  Q.Put(NULL);
+
+  MU1.Lock();
+  MU.Lock();
+  GLOB++;
+  MU.Unlock();
+  MU1.Unlock();
+}
+
+void Getter() {
+  Q.Get();
+  Q.Get();
+  usleep(100000);
+  MU1.Lock();
+  GLOB++;
+  MU1.Unlock();
+}
+
+void Run() {
+  printf("test36: negative \n");
+  MyThreadArray t(Getter, Putter, Putter);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 36);
+}  // namespace test36
+
+
+// test37: TN. Simple synchronization (write vs read). {{{1
+namespace test37 {
+int     GLOB = 0;
+Mutex   MU; 
+// Similar to test10, but properly locked. 
+// Writer:             Reader: 
+// 1. MU.Lock()      
+// 2. write
+// 3. MU.Unlock()                   
+//                    a. MU.Lock()
+//                    b. read
+//                    c. MU.Unlock();              
+
+void Writer() {
+  MU.Lock();
+  GLOB = 3; 
+  MU.Unlock();
+}
+void Reader() {
+  usleep(100000);
+  MU.Lock();
+  CHECK(GLOB != -777);
+  MU.Unlock();
+}
+
+void Run() {
+  printf("test37: negative\n");
+  MyThreadArray t(Writer, Reader);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 37);
+}  // namespace test37
+
+
+// test38: TN. Synchronization via Mutexes and PCQ. 4 threads. W/W {{{1
+namespace test38 {
+// Fusion of test29 and test36. 
+
+// Putter1:            Putter2:           Getter1:       Getter2:
+//    MU1.Lock()          MU1.Lock()                                    
+//    write(GLOB)         write(GLOB)                                   
+//    MU1.Unlock()        MU1.Unlock()                                  
+//    Q1.Put()            Q2.Put()                                      
+//    Q1.Put()            Q2.Put()                                      
+//    MU1.Lock()          MU1.Lock()        
+//    MU2.Lock()          MU2.Lock()        
+//    write(GLOB)         write(GLOB)       
+//    MU2.Unlock()        MU2.Unlock()      
+//    MU1.Unlock()        MU1.Unlock()     sleep          sleep
+//                                         Q1.Get()       Q1.Get()
+//                                         Q2.Get()       Q2.Get()
+//                                         MU2.Lock()     MU2.Lock()
+//                                         write(GLOB)    write(GLOB)
+//                                         MU2.Unlock()   MU2.Unlock()
+//
+
+
+ProducerConsumerQueue *Q1, *Q2;
+int     GLOB = 0;
+Mutex   MU, MU1, MU2; 
+
+void Putter(ProducerConsumerQueue *q) {
+  MU1.Lock();
+  GLOB++;
+  MU1.Unlock();
+
+  q->Put(NULL);
+  q->Put(NULL);
+
+  MU1.Lock();
+  MU2.Lock();
+  GLOB++;
+  MU2.Unlock();
+  MU1.Unlock();
+
+}
+
+void Putter1() { Putter(Q1); }
+void Putter2() { Putter(Q2); }
+
+void Getter() {
+  usleep(100000);
+  Q1->Get();
+  Q2->Get();
+
+  MU2.Lock();
+  GLOB++;
+  MU2.Unlock();
+
+  usleep(48000); //  TODO: remove this when FP in test32 is fixed. 
+}
+
+void Run() {
+  printf("test38: negative\n");
+  Q1 = new ProducerConsumerQueue(INT_MAX);
+  Q2 = new ProducerConsumerQueue(INT_MAX);
+  MyThreadArray t(Getter, Getter, Putter1, Putter2);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+  delete Q1;
+  delete Q2;
+}
+REGISTER_TEST(Run, 38);
+}  // namespace test38
+
+// test39: FP. Barrier. {{{1
+namespace test39 {
+#ifndef NO_BARRIER
+// Same as test17 but uses Barrier class (pthread_barrier_t). 
+int     GLOB = 0;
+const int N_threads = 3;
+Barrier barrier(N_threads);
+Mutex   MU; 
+
+void Worker() {
+  MU.Lock();
+  GLOB++;
+  MU.Unlock();
+  barrier.Block();
+  CHECK(GLOB == N_threads);
+}
+void Run() {
+  ANNOTATE_TRACE_MEMORY(&GLOB);
+//  ANNOTATE_EXPECT_RACE(&GLOB, "test39. FP. Fixed by MSMProp1. Barrier.");
+  printf("test39: negative\n");
+  {
+    ThreadPool pool(N_threads);
+    pool.StartWorkers();
+    for (int i = 0; i < N_threads; i++) {
+      pool.Add(NewCallback(Worker));
+    }
+  } // all folks are joined here. 
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 39);
+#endif // NO_BARRIER
+}  // namespace test39
+
+
+// test40: FP. Synchronization via Mutexes and PCQ. 4 threads. W/W {{{1
+namespace test40 {
+// Similar to test38 but with different order of events (due to sleep). 
+
+// Putter1:            Putter2:           Getter1:       Getter2:
+//    MU1.Lock()          MU1.Lock()                                    
+//    write(GLOB)         write(GLOB)                                   
+//    MU1.Unlock()        MU1.Unlock()                                  
+//    Q1.Put()            Q2.Put()                                      
+//    Q1.Put()            Q2.Put()                                      
+//                                        Q1.Get()       Q1.Get()     
+//                                        Q2.Get()       Q2.Get()     
+//                                        MU2.Lock()     MU2.Lock()   
+//                                        write(GLOB)    write(GLOB)  
+//                                        MU2.Unlock()   MU2.Unlock()
+//                                         
+//    MU1.Lock()          MU1.Lock()                                       
+//    MU2.Lock()          MU2.Lock()                                       
+//    write(GLOB)         write(GLOB)                                      
+//    MU2.Unlock()        MU2.Unlock()                                     
+//    MU1.Unlock()        MU1.Unlock() 
+
+
+ProducerConsumerQueue *Q1, *Q2;
+int     GLOB = 0;
+Mutex   MU, MU1, MU2; 
+
+void Putter(ProducerConsumerQueue *q) {
+  MU1.Lock();
+  GLOB++;
+  MU1.Unlock();
+
+  q->Put(NULL);
+  q->Put(NULL);
+  usleep(100000);
+
+  MU1.Lock();
+  MU2.Lock();
+  GLOB++;
+  MU2.Unlock();
+  MU1.Unlock();
+
+}
+
+void Putter1() { Putter(Q1); }
+void Putter2() { Putter(Q2); }
+
+void Getter() {
+  Q1->Get();
+  Q2->Get();
+
+  MU2.Lock();
+  GLOB++;
+  MU2.Unlock();
+
+  usleep(48000); //  TODO: remove this when FP in test32 is fixed. 
+}
+
+void Run() {
+//  ANNOTATE_EXPECT_RACE(&GLOB, "test40. FP. Fixed by MSMProp1. Complex Stuff.");
+  printf("test40: negative\n");
+  Q1 = new ProducerConsumerQueue(INT_MAX);
+  Q2 = new ProducerConsumerQueue(INT_MAX);
+  MyThreadArray t(Getter, Getter, Putter1, Putter2);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+  delete Q1;
+  delete Q2;
+}
+REGISTER_TEST(Run, 40);
+}  // namespace test40
+
+// test41: TN. Test for race that appears when loading a dynamic symbol. {{{1
+namespace test41 {
+void Worker() {
+  ANNOTATE_NO_OP(NULL); // An empty function, loaded from dll. 
+}
+void Run() {
+  printf("test41: negative\n");
+  MyThreadArray t(Worker, Worker, Worker);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST2(Run, 41, FEATURE|NEEDS_ANNOTATIONS);
+}  // namespace test41
+
+
+// test42: TN. Using the same cond var several times. {{{1
+namespace test42 {
+int GLOB = 0;
+int COND = 0;
+int N_threads = 3;
+Mutex   MU; 
+
+void Worker1() {
+  GLOB=1;
+
+  MU.Lock(); 
+  COND = 1;
+  CV.Signal();
+  MU.Unlock();
+
+  MU.Lock(); 
+  while (COND != 0) 
+    CV.Wait(&MU);
+  ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
+  MU.Unlock();
+
+  GLOB=3;
+
+}
+
+void Worker2() {
+
+  MU.Lock(); 
+  while (COND != 1) 
+    CV.Wait(&MU);
+  ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
+  MU.Unlock();
+
+  GLOB=2;
+
+  MU.Lock(); 
+  COND = 0;
+  CV.Signal();
+  MU.Unlock();
+
+}
+
+void Run() {
+//  ANNOTATE_EXPECT_RACE(&GLOB, "test42. TN. debugging.");
+  printf("test42: negative\n");
+  MyThreadArray t(Worker1, Worker2);
+  t.Start(); 
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 42, FEATURE|NEEDS_ANNOTATIONS);
+}  // namespace test42
+
+
+
+// test43: TN. {{{1
+namespace test43 {
+// 
+// Putter:            Getter: 
+// 1. write          
+// 2. Q.Put() --\     .
+// 3. read       \--> a. Q.Get()    
+//                    b. read
+int     GLOB = 0;
+ProducerConsumerQueue Q(INT_MAX);
+void Putter() {
+  GLOB = 1;
+  Q.Put(NULL);
+  CHECK(GLOB == 1);
+}
+void Getter() {
+  Q.Get();
+  usleep(100000);
+  CHECK(GLOB == 1);
+}
+void Run() {
+  printf("test43: negative\n");
+  MyThreadArray t(Putter, Getter);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 43)
+}  // namespace test43
+
+
+// test44: FP. {{{1
+namespace test44 {
+// 
+// Putter:            Getter: 
+// 1. read          
+// 2. Q.Put() --\     .
+// 3. MU.Lock()  \--> a. Q.Get()    
+// 4. write
+// 5. MU.Unlock()                   
+//                    b. MU.Lock()
+//                    c. write
+//                    d. MU.Unlock();              
+int     GLOB = 0;
+Mutex   MU; 
+ProducerConsumerQueue Q(INT_MAX);
+void Putter() {
+  CHECK(GLOB == 0);
+  Q.Put(NULL);
+  MU.Lock();
+  GLOB = 1;
+  MU.Unlock();
+}
+void Getter() {
+  Q.Get();
+  usleep(100000);
+  MU.Lock();
+  GLOB = 1;
+  MU.Unlock();
+}
+void Run() {
+//  ANNOTATE_EXPECT_RACE(&GLOB, "test44. FP. Fixed by MSMProp1.");
+  printf("test44: negative\n");
+  MyThreadArray t(Putter, Getter);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 44)
+}  // namespace test44
+
+
+// test45: TN. {{{1
+namespace test45 {
+// 
+// Putter:            Getter: 
+// 1. read          
+// 2. Q.Put() --\     .
+// 3. MU.Lock()  \--> a. Q.Get()    
+// 4. write
+// 5. MU.Unlock()                   
+//                    b. MU.Lock()
+//                    c. read
+//                    d. MU.Unlock();              
+int     GLOB = 0;
+Mutex   MU; 
+ProducerConsumerQueue Q(INT_MAX);
+void Putter() {
+  CHECK(GLOB == 0);
+  Q.Put(NULL);
+  MU.Lock();
+  GLOB++;
+  MU.Unlock();
+}
+void Getter() {
+  Q.Get();
+  usleep(100000);
+  MU.Lock();
+  CHECK(GLOB <= 1);
+  MU.Unlock();
+}
+void Run() {
+  printf("test45: negative\n");
+  MyThreadArray t(Putter, Getter);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 45)
+}  // namespace test45
+
+
+// test46: FN. {{{1
+namespace test46 {
+// 
+// First:                             Second: 
+// 1. write                          
+// 2. MU.Lock()                      
+// 3. write                       
+// 4. MU.Unlock()                      (sleep)              
+//                                    a. MU.Lock()
+//                                    b. write
+//                                    c. MU.Unlock();              
+int     GLOB = 0;
+Mutex   MU; 
+void First() {
+  GLOB++;
+  MU.Lock();
+  GLOB++;
+  MU.Unlock();
+}
+void Second() {
+  usleep(480000);
+  MU.Lock();
+  GLOB++;
+  MU.Unlock();
+
+  // just a print. 
+  // If we move it to Run()  we will get report in MSMHelgrind 
+  // due to its false positive (test32). 
+  MU.Lock();
+  printf("\tGLOB=%d\n", GLOB);
+  MU.Unlock();
+}
+void Run() {
+  ANNOTATE_TRACE_MEMORY(&GLOB);
+  MyThreadArray t(First, Second);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST(Run, 46)
+}  // namespace test46
+
+
+// test47: TP. Not detected by pure happens-before detectors. {{{1
+namespace test47 {
+// A true race that can not be detected by a pure happens-before 
+// race detector. 
+//
+// First:                             Second: 
+// 1. write                          
+// 2. MU.Lock()                      
+// 3. MU.Unlock()                      (sleep)              
+//                                    a. MU.Lock()
+//                                    b. MU.Unlock();              
+//                                    c. write
+int     GLOB = 0;
+Mutex   MU; 
+void First() {
+  GLOB=1;
+  MU.Lock();
+  MU.Unlock();
+}
+void Second() {
+  usleep(480000);
+  MU.Lock();
+  MU.Unlock();
+  GLOB++;
+}
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  if (!Tsan_PureHappensBefore())
+    ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test47. TP. Not detected by pure HB.");
+  printf("test47: positive\n");
+  MyThreadArray t(First, Second);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 47)
+}  // namespace test47
+
+
+// test48: FN. Simple race (single write vs multiple reads). {{{1
+namespace test48 {
+int     GLOB = 0;
+// same as test10 but with single writer and  multiple readers
+// A simple data race between single writer and  multiple readers. 
+// Write happens before Reads (enforced by sleep(1)), 
+
+// 
+// Writer:                    Readers:
+// 1. write(GLOB)             a. sleep(long enough so that GLOB 
+//                                is most likely initialized by Writer)
+//                            b. read(GLOB)
+// 
+//
+// Eraser algorithm does not detect the race here, 
+// see Section 2.2 of http://citeseer.ist.psu.edu/savage97eraser.html. 
+//
+void Writer() {
+  GLOB = 3; 
+}
+void Reader() {
+  usleep(100000);
+  CHECK(GLOB != -777);
+}
+
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test48. TP. FN in MSMHelgrind.");
+  printf("test48: positive\n");
+  MyThreadArray t(Writer, Reader,Reader,Reader);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 48)
+}  // namespace test48
+
+
+// test49: FN. Simple race (single write vs multiple reads). {{{1
+namespace test49 {
+int     GLOB = 0;
+// same as test10 but with multiple read operations done by a single reader
+// A simple data race between writer and readers. 
+// Write happens before Read (enforced by sleep(1)), 
+// 
+// Writer:                    Reader:
+// 1. write(GLOB)             a. sleep(long enough so that GLOB 
+//                                is most likely initialized by Writer)
+//                            b. read(GLOB)
+//                            c. read(GLOB)
+//                            d. read(GLOB)
+//                            e. read(GLOB)
+// 
+//
+// Eraser algorithm does not detect the race here, 
+// see Section 2.2 of http://citeseer.ist.psu.edu/savage97eraser.html. 
+//
+void Writer() {
+  GLOB = 3; 
+}
+void Reader() {
+  usleep(100000);
+  CHECK(GLOB != -777);
+  CHECK(GLOB != -777);
+  CHECK(GLOB != -777);
+  CHECK(GLOB != -777);
+}
+
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test49. TP. FN in MSMHelgrind.");
+  printf("test49: positive\n");
+  MyThreadArray t(Writer, Reader);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 49);
+}  // namespace test49
+
+
+// test50: TP. Synchronization via CondVar. {{{1
+namespace test50 {
+int     GLOB = 0;
+Mutex   MU; 
+// Two last write accesses to GLOB are not synchronized 
+//
+// Waiter:                      Waker: 
+// 1. COND = 0
+// 2. Start(Waker)              
+// 3. MU.Lock()                 a. write(GLOB)
+//                              b. MU.Lock()
+//                              c. COND = 1
+//                         /--- d. CV.Signal()
+//  4. while(COND != 1)   /     e. MU.Unlock()
+//       CV.Wait(MU) <---/
+//  5. MU.Unlock()
+//  6. write(GLOB)              f. MU.Lock()
+//                              g. write(GLOB)
+//                              h. MU.Unlock()
+
+
+void Waker() {
+  usleep(100000);  // Make sure the waiter blocks.
+
+  GLOB = 1;
+
+  MU.Lock();
+  COND = 1;
+  CV.Signal(); 
+  MU.Unlock();
+
+  usleep(100000);
+  MU.Lock();
+  GLOB = 3; 
+  MU.Unlock();
+}
+
+void Waiter() {
+  ThreadPool pool(1);
+  pool.StartWorkers();
+  COND = 0;
+  pool.Add(NewCallback(Waker));
+ 
+  MU.Lock();
+  while(COND != 1)
+    CV.Wait(&MU);
+  ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
+  MU.Unlock();
+
+  GLOB = 2;
+}
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test50. TP.");
+  printf("test50: positive\n");
+  Waiter();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 50, FEATURE|NEEDS_ANNOTATIONS);
+}  // namespace test50
+
+
+// test51: TP. Synchronization via CondVar: problem with several signals. {{{1
+namespace test51 {
+int     GLOB = 0;
+int     COND = 0;
+Mutex   MU; 
+
+
+// scheduler dependent results because of several signals
+// second signal will be lost
+//
+// Waiter:                      Waker: 
+// 1. Start(Waker)              
+// 2. MU.Lock()          
+// 3. while(COND)               
+//       CV.Wait(MU)<-\         .
+// 4. MU.Unlock()      \        .
+// 5. write(GLOB)       \       a. write(GLOB)
+//                       \      b. MU.Lock()
+//                        \     c. COND = 1
+//                         \--- d. CV.Signal()
+//                              e. MU.Unlock()
+//                              
+//                              f. write(GLOB)
+//                              
+//                              g. MU.Lock()
+//                              h. COND = 1
+//                    LOST<---- i. CV.Signal()
+//                              j. MU.Unlock()
+
+void Waker() {
+
+  usleep(10000);  // Make sure the waiter blocks.
+
+  GLOB = 1;
+  
+  MU.Lock();
+  COND = 1;
+  CV.Signal(); 
+  MU.Unlock();
+
+  usleep(10000);  // Make sure the waiter is signalled.
+
+  GLOB = 2;
+
+  MU.Lock();
+  COND = 1;
+  CV.Signal();   //Lost Signal
+  MU.Unlock();
+}
+
+void Waiter() {
+
+  ThreadPool pool(1);
+  pool.StartWorkers();
+  pool.Add(NewCallback(Waker));
+ 
+  MU.Lock();
+  while(COND != 1)
+    CV.Wait(&MU);
+  MU.Unlock();
+
+
+  GLOB = 3;
+}
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  ANNOTATE_EXPECT_RACE(&GLOB, "test51. TP.");
+  printf("test51: positive\n");
+  Waiter();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 51);
+}  // namespace test51
+
+
+// test52: TP. Synchronization via CondVar: problem with several signals. {{{1
+namespace test52 {
+int     GLOB = 0;
+int     COND = 0;
+Mutex   MU; 
+
+// same as test51 but the first signal will be lost
+// scheduler dependent results because of several signals
+//
+// Waiter:                      Waker: 
+// 1. Start(Waker)              
+//                              a. write(GLOB)
+//                              b. MU.Lock()
+//                              c. COND = 1
+//                    LOST<---- d. CV.Signal()
+//                              e. MU.Unlock()
+//                              
+// 2. MU.Lock()       
+// 3. while(COND)               
+//       CV.Wait(MU)<-\         .
+// 4. MU.Unlock()      \        f. write(GLOB)
+// 5. write(GLOB)       \       .
+//                       \      g. MU.Lock()
+//                        \     h. COND = 1
+//                         \--- i. CV.Signal()
+//                              j. MU.Unlock()
+
+void Waker() {
+
+  GLOB = 1;
+  
+  MU.Lock();
+  COND = 1;
+  CV.Signal();    //lost signal
+  MU.Unlock();
+
+  usleep(20000);  // Make sure the waiter blocks
+
+  GLOB = 2;
+
+  MU.Lock();
+  COND = 1;
+  CV.Signal(); 
+  MU.Unlock();  
+}
+
+void Waiter() {
+  ThreadPool pool(1);
+  pool.StartWorkers();
+  pool.Add(NewCallback(Waker));
+ 
+  usleep(10000);  // Make sure the first signal will be lost
+
+  MU.Lock();
+  while(COND != 1)
+    CV.Wait(&MU);
+  MU.Unlock();
+  
+  GLOB = 3;
+}
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  ANNOTATE_EXPECT_RACE(&GLOB, "test52. TP.");
+  printf("test52: positive\n");
+  Waiter();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 52);
+}  // namespace test52
+
+
+// test53: FP. Synchronization via implicit semaphore. {{{1
+namespace test53 {
+// Correctly synchronized test, but the common lockset is empty.
+// The variable FLAG works as an implicit semaphore. 
+// MSMHelgrind still does not complain since it does not maintain the lockset
+// at the exclusive state. But MSMProp1 does complain. 
+// See also test54. 
+// 
+//
+// Initializer:                  Users
+// 1. MU1.Lock() 
+// 2. write(GLOB) 
+// 3. FLAG = true
+// 4. MU1.Unlock()
+//                               a. MU1.Lock()
+//                               b. f = FLAG;
+//                               c. MU1.Unlock()
+//                               d. if (!f) goto a.
+//                               e. MU2.Lock()
+//                               f. write(GLOB)
+//                               g. MU2.Unlock()
+//
+
+int     GLOB = 0;
+bool    FLAG = false;
+Mutex   MU1, MU2; 
+
+void Initializer() {
+  MU1.Lock();
+  GLOB = 1000;
+  FLAG = true;
+  MU1.Unlock();
+  usleep(100000); // just in case
+}
+
+void User() {
+  bool f = false;
+  while(!f) {
+    MU1.Lock();
+    f = FLAG;
+    MU1.Unlock();
+    usleep(10000);
+  }
+  // at this point Initializer will not access GLOB again
+  MU2.Lock();
+  CHECK(GLOB >= 1000);
+  GLOB++;
+  MU2.Unlock();
+}
+
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  if (!Tsan_PureHappensBefore())
+    ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test53. FP. Implicit semaphore");
+  printf("test53: FP. false positive, Implicit semaphore\n");
+  MyThreadArray t(Initializer, User, User);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 53)
+}  // namespace test53
+
+
+// test54: TN. Synchronization via implicit semaphore. Annotated {{{1
+namespace test54 {
+// Same as test53, but annotated. 
+int     GLOB = 0;
+bool    FLAG = false;
+Mutex   MU1, MU2; 
+
+void Initializer() {
+  MU1.Lock();
+  GLOB = 1000;
+  FLAG = true;
+  ANNOTATE_CONDVAR_SIGNAL(&GLOB);
+  MU1.Unlock();
+  usleep(100000); // just in case
+}
+
+void User() {
+  bool f = false;
+  while(!f) {
+    MU1.Lock();
+    f = FLAG;
+    MU1.Unlock();
+    usleep(10000);
+  }
+  // at this point Initializer will not access GLOB again
+  ANNOTATE_CONDVAR_WAIT(&GLOB);
+  MU2.Lock();
+  CHECK(GLOB >= 1000);
+  GLOB++;
+  MU2.Unlock();
+}
+
+void Run() {
+  printf("test54: negative\n");
+  MyThreadArray t(Initializer, User, User);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 54, FEATURE|NEEDS_ANNOTATIONS)
+}  // namespace test54
+
+
+// test55: FP. Synchronization with TryLock. Not easy for race detectors {{{1
+namespace test55 {  
+// "Correct" synchronization with TryLock and Lock. 
+//
+// This scheme is actually very risky. 
+// It is covered in detail in this video: 
+// http://youtube.com/watch?v=mrvAqvtWYb4 (slide 36, near 50-th minute). 
+int     GLOB = 0;
+Mutex   MU; 
+
+void Worker_Lock() {
+  GLOB = 1;
+  MU.Lock();
+}
+
+void Worker_TryLock() {
+  while (true) {
+    if (!MU.TryLock()) {
+      MU.Unlock();
+      break;
+    }
+    else 
+      MU.Unlock();
+    usleep(100); 
+  }
+  GLOB = 2; 
+}
+
+void Run() {
+  printf("test55:\n");
+  MyThreadArray t(Worker_Lock, Worker_TryLock);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 55, FEATURE|EXCLUDE_FROM_ALL);
+}  // namespace test55
+
+
+
+// test56: TP. Use of ANNOTATE_BENIGN_RACE. {{{1
+namespace test56 {
+// For whatever reason the user wants to treat 
+// a race on GLOB as a benign race. 
+int     GLOB = 0;
+int     GLOB2 = 0;
+
+void Worker() {
+  GLOB++;
+}
+
+void Run() {
+  ANNOTATE_BENIGN_RACE(&GLOB, "test56. Use of ANNOTATE_BENIGN_RACE.");
+  ANNOTATE_BENIGN_RACE(&GLOB2, "No race. The tool should be silent");
+  printf("test56: positive\n");
+  MyThreadArray t(Worker, Worker, Worker, Worker);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 56, FEATURE|NEEDS_ANNOTATIONS)
+}  // namespace test56
+
+
+// test57: TN: Correct use of atomics. {{{1
+namespace test57 {
+int     GLOB = 0;
+void Writer() {
+  for (int i = 0; i < 10; i++) {
+    AtomicIncrement(&GLOB, 1);
+    usleep(1000);
+  }
+}
+void Reader() {
+  while (GLOB < 20) usleep(1000);
+}
+void Run() {
+  printf("test57: negative\n");
+  MyThreadArray t(Writer, Writer, Reader, Reader);
+  t.Start();
+  t.Join();
+  CHECK(GLOB == 20);
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 57)
+}  // namespace test57
+
+
+// test58: TN. User defined synchronization. {{{1
+namespace test58 {
+int     GLOB1 = 1;
+int     GLOB2 = 2;
+int     FLAG1 = 0;
+int     FLAG2 = 0;
+
+// Correctly synchronized test, but the common lockset is empty.
+// The variables FLAG1 and FLAG2 used for synchronization and as 
+// temporary variables for swapping two global values.
+// Such kind of synchronization is rarely used (Excluded from all tests??).
+
+void Worker2() {
+  FLAG1=GLOB2;
+
+  while(!FLAG2)
+    ;
+  GLOB2=FLAG2;
+}
+
+void Worker1() {
+  FLAG2=GLOB1;
+
+  while(!FLAG1)
+    ;
+  GLOB1=FLAG1;
+}
+
+void Run() {
+  printf("test58:\n");
+  MyThreadArray t(Worker1, Worker2);
+  t.Start();
+  t.Join();
+  printf("\tGLOB1=%d\n", GLOB1);
+  printf("\tGLOB2=%d\n", GLOB2);
+}
+REGISTER_TEST2(Run, 58, FEATURE|EXCLUDE_FROM_ALL)
+}  // namespace test58
+
+
+
+// test59: TN. User defined synchronization. Annotated {{{1
+namespace test59 {
+int     COND1 = 0;
+int     COND2 = 0;
+int     GLOB1 = 1;
+int     GLOB2 = 2;
+int     FLAG1 = 0;
+int     FLAG2 = 0;
+// same as test 58 but annotated
+
+void Worker2() {
+  FLAG1=GLOB2;
+  ANNOTATE_CONDVAR_SIGNAL(&COND2);
+  while(!FLAG2) usleep(1);
+  ANNOTATE_CONDVAR_WAIT(&COND1);
+  GLOB2=FLAG2;
+}
+
+void Worker1() {
+  FLAG2=GLOB1;
+  ANNOTATE_CONDVAR_SIGNAL(&COND1);
+  while(!FLAG1) usleep(1);
+  ANNOTATE_CONDVAR_WAIT(&COND2);
+  GLOB1=FLAG1;
+}
+
+void Run() {
+  printf("test59: negative\n");
+  ANNOTATE_BENIGN_RACE(&FLAG1, "synchronization via 'safe' race");
+  ANNOTATE_BENIGN_RACE(&FLAG2, "synchronization via 'safe' race");
+  MyThreadArray t(Worker1, Worker2);
+  t.Start();
+  t.Join();
+  printf("\tGLOB1=%d\n", GLOB1);
+  printf("\tGLOB2=%d\n", GLOB2);
+}
+REGISTER_TEST2(Run, 59, FEATURE|NEEDS_ANNOTATIONS)
+}  // namespace test59
+
+
+// test60: TN. Correct synchronization using signal-wait {{{1
+namespace test60 {
+int     COND1 = 0;
+int     COND2 = 0;
+int     GLOB1 = 1;
+int     GLOB2 = 2;
+int     FLAG2 = 0;
+int     FLAG1 = 0;
+Mutex   MU; 
+// same as test 59 but synchronized with signal-wait.
+
+void Worker2() {
+  FLAG1=GLOB2;
+
+  MU.Lock();
+  COND1 = 1;
+  CV.Signal();    
+  MU.Unlock();
+
+  MU.Lock();
+  while(COND2 != 1)
+    CV.Wait(&MU);
+  ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
+  MU.Unlock();
+
+  GLOB2=FLAG2;
+}
+
+void Worker1() {
+  FLAG2=GLOB1;
+
+  MU.Lock();
+  COND2 = 1;
+  CV.Signal();    
+  MU.Unlock();
+
+  MU.Lock();
+  while(COND1 != 1)
+    CV.Wait(&MU);
+  ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
+  MU.Unlock();
+
+  GLOB1=FLAG1;
+}
+
+void Run() {
+  printf("test60: negative\n");
+  MyThreadArray t(Worker1, Worker2);
+  t.Start();
+  t.Join();
+  printf("\tGLOB1=%d\n", GLOB1);
+  printf("\tGLOB2=%d\n", GLOB2);
+}
+REGISTER_TEST2(Run, 60, FEATURE|NEEDS_ANNOTATIONS)
+}  // namespace test60
+
+
+// test61: TN. Synchronization via Mutex as in happens-before, annotated. {{{1
+namespace test61 {
+Mutex MU;
+int     GLOB = 0;
+int     *P1 = NULL, *P2 = NULL;
+
+// In this test Mutex lock/unlock operations introduce happens-before relation. 
+// We annotate the code so that MU is treated as in pure happens-before detector. 
+
+
+void Putter() {
+  ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&MU);
+  MU.Lock();
+  if (P1 == NULL) {
+    P1 = &GLOB;
+    *P1 = 1;
+  } 
+  MU.Unlock();
+}
+
+void Getter() {
+  bool done  = false;
+  while (!done) {
+    MU.Lock();
+    if (P1) {
+      done = true;
+      P2 = P1; 
+      P1 = NULL;
+    }
+    MU.Unlock();
+  }
+  *P2 = 2;
+}
+
+
+void Run() {
+  printf("test61: negative\n");
+  MyThreadArray t(Putter, Getter);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 61, FEATURE|NEEDS_ANNOTATIONS)
+}  // namespace test61
+
+
+// test62: STAB. Create as many segments as possible. {{{1
+namespace test62 {
+// Helgrind 3.3.0 will fail as it has a hard limit of < 2^24 segments. 
+// A better scheme is to implement garbage collection for segments. 
+ProducerConsumerQueue Q(INT_MAX);
+const int N = 1 << 22;
+
+void Putter() {
+  for (int i = 0; i < N; i++){
+    if ((i % (N / 8)) == 0) {
+      printf("i=%d\n", i);
+    }
+    Q.Put(NULL);
+  }
+}
+
+void Getter() {
+  for (int i = 0; i < N; i++)
+    Q.Get();
+}
+
+void Run() {
+  printf("test62:\n");
+  MyThreadArray t(Putter, Getter);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST2(Run, 62, STABILITY|EXCLUDE_FROM_ALL)
+}  // namespace test62
+
+
+// test63: STAB. Create as many segments as possible and do it fast. {{{1
+namespace test63 {
+// Helgrind 3.3.0 will fail as it has a hard limit of < 2^24 segments. 
+// A better scheme is to implement garbage collection for segments. 
+const int N = 1 << 24;
+int C = 0;
+
+void Putter() {
+  for (int i = 0; i < N; i++){
+    if ((i % (N / 8)) == 0) {
+      printf("i=%d\n", i);
+    }
+    ANNOTATE_CONDVAR_SIGNAL(&C);
+  }
+}
+
+void Getter() {
+}
+
+void Run() {
+  printf("test63:\n");
+  MyThreadArray t(Putter, Getter);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST2(Run, 63, STABILITY|EXCLUDE_FROM_ALL)
+}  // namespace test63
+
+
+// test64: TP. T2 happens-before T3, but T1 is independent. Reads in T1/T2. {{{1
+namespace test64 {
+// True race between T1 and T3: 
+//
+// T1:                   T2:                   T3: 
+// 1. read(GLOB)         (sleep)
+//                       a. read(GLOB)
+//                       b. Q.Put() ----->    A. Q.Get()
+//                                            B. write(GLOB) 
+//
+//
+
+int     GLOB = 0;
+ProducerConsumerQueue Q(INT_MAX);
+
+void T1() {
+  CHECK(GLOB == 0);
+}
+
+void T2() {
+  usleep(100000);
+  CHECK(GLOB == 0);
+  Q.Put(NULL);
+}
+
+void T3() {
+  Q.Get();
+  GLOB = 1;
+}
+
+
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test64: TP.");
+  printf("test64: positive\n");
+  MyThreadArray t(T1, T2, T3);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 64)
+}  // namespace test64
+
+
+// test65: TP. T2 happens-before T3, but T1 is independent. Writes in T1/T2. {{{1
+namespace test65 {
+// Similar to test64. 
+// True race between T1 and T3: 
+//
+// T1:                   T2:                   T3: 
+// 1. MU.Lock()
+// 2. write(GLOB)
+// 3. MU.Unlock()         (sleep)
+//                       a. MU.Lock()
+//                       b. write(GLOB)
+//                       c. MU.Unlock()
+//                       d. Q.Put() ----->    A. Q.Get()
+//                                            B. write(GLOB) 
+//
+//
+
+int     GLOB = 0;
+Mutex   MU; 
+ProducerConsumerQueue Q(INT_MAX);
+
+void T1() {
+  MU.Lock();
+  GLOB++;
+  MU.Unlock();
+}
+
+void T2() {
+  usleep(100000);
+  MU.Lock();
+  GLOB++;
+  MU.Unlock();
+  Q.Put(NULL);
+}
+
+void T3() {
+  Q.Get();
+  GLOB = 1;
+}
+
+
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  if (!Tsan_PureHappensBefore())
+    ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test65. TP.");
+  printf("test65: positive\n");
+  MyThreadArray t(T1, T2, T3);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 65)
+}  // namespace test65
+
+
+// test66: TN. Two separate pairs of signaller/waiter using the same CV. {{{1
+namespace test66 {
+int     GLOB1 = 0;
+int     GLOB2 = 0;
+int     C1 = 0;
+int     C2 = 0;
+Mutex   MU; 
+
+void Signaller1() {
+  GLOB1 = 1;
+  MU.Lock();
+  C1 = 1;
+  CV.Signal();
+  MU.Unlock();
+}
+
+void Signaller2() {
+  GLOB2 = 1;
+  usleep(100000);
+  MU.Lock();
+  C2 = 1;
+  CV.Signal();
+  MU.Unlock();
+}
+
+void Waiter1() {
+  MU.Lock();
+  while (C1 != 1) CV.Wait(&MU);
+  ANNOTATE_CONDVAR_WAIT(&CV);
+  MU.Unlock();
+  GLOB1 = 2;
+}
+
+void Waiter2() {
+  MU.Lock();
+  while (C2 != 1) CV.Wait(&MU);
+  ANNOTATE_CONDVAR_WAIT(&CV);
+  MU.Unlock();
+  GLOB2 = 2;
+}
+
+void Run() {
+  printf("test66: negative\n");
+  MyThreadArray t(Signaller1, Signaller2, Waiter1, Waiter2);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d/%d\n", GLOB1, GLOB2);
+}
+REGISTER_TEST2(Run, 66, FEATURE|NEEDS_ANNOTATIONS)
+}  // namespace test66
+
+
+// test67: FN. Race between Signaller1 and Waiter2 {{{1
+namespace test67 {
+// Similar to test66, but there is a real race here. 
+//
+// Here we create a happens-before arc between Signaller1 and Waiter2
+// even though there should be no such arc. 
+// However, it's probably improssible (or just very hard) to avoid it. 
+int     GLOB = 0;
+int     C1 = 0;
+int     C2 = 0;
+Mutex   MU; 
+
+void Signaller1() {
+  GLOB = 1;
+  MU.Lock();
+  C1 = 1;
+  CV.Signal();
+  MU.Unlock();
+}
+
+void Signaller2() {
+  usleep(100000);
+  MU.Lock();
+  C2 = 1;
+  CV.Signal();
+  MU.Unlock();
+}
+
+void Waiter1() {
+  MU.Lock();
+  while (C1 != 1) CV.Wait(&MU);
+  ANNOTATE_CONDVAR_WAIT(&CV);
+  MU.Unlock();
+}
+
+void Waiter2() {
+  MU.Lock();
+  while (C2 != 1) CV.Wait(&MU);
+  ANNOTATE_CONDVAR_WAIT(&CV);
+  MU.Unlock();
+  GLOB = 2;
+}
+
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  ANNOTATE_EXPECT_RACE(&GLOB, "test67. FN. Race between Signaller1 and Waiter2");
+  printf("test67: positive\n");
+  MyThreadArray t(Signaller1, Signaller2, Waiter1, Waiter2);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 67, FEATURE|NEEDS_ANNOTATIONS|EXCLUDE_FROM_ALL)
+}  // namespace test67
+
+
+// test68: TP. Writes are protected by MU, reads are not. {{{1
+namespace test68 {
+// In this test, all writes to GLOB are protected by a mutex 
+// but some reads go unprotected. 
+// This is certainly a race, but in some cases such code could occur in 
+// a correct program. For example, the unprotected reads may be used 
+// for showing statistics and are not required to be precise. 
+int     GLOB = 0;
+int     COND = 0;
+const int N_writers = 3;
+Mutex MU, MU1;
+
+void Writer() {
+  for (int i = 0; i < 100; i++) {
+    MU.Lock();
+    GLOB++;
+    MU.Unlock();
+  }
+
+  // we are done
+  MU1.Lock();
+  COND++;
+  MU1.Unlock();
+}
+
+void Reader() {
+  bool cont = true;
+  while (cont) {
+    CHECK(GLOB >= 0);
+
+    // are we done?
+    MU1.Lock();
+    if (COND == N_writers)
+      cont = false;
+    MU1.Unlock();
+    usleep(100);
+  }
+}
+
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  ANNOTATE_EXPECT_RACE(&GLOB, "TP. Writes are protected, reads are not.");
+  printf("test68: positive\n");
+  MyThreadArray t(Reader, Writer, Writer, Writer);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 68)
+}  // namespace test68
+
+
+// test69:  {{{1
+namespace test69 {
+// This is the same as test68, but annotated. 
+// We do not want to annotate GLOB as a benign race 
+// because we want to allow racy reads only in certain places. 
+//
+// TODO: 
+int     GLOB = 0;
+int     COND = 0;
+const int N_writers = 3;
+int     FAKE_MU = 0;
+Mutex MU, MU1;
+
+void Writer() {
+  for (int i = 0; i < 10; i++) {
+    MU.Lock();
+    GLOB++;
+    MU.Unlock();
+  }
+
+  // we are done
+  MU1.Lock();
+  COND++;
+  MU1.Unlock();
+}
+
+void Reader() {
+  bool cont = true;
+  while (cont) {
+    ANNOTATE_IGNORE_READS_BEGIN();
+    CHECK(GLOB >= 0);
+    ANNOTATE_IGNORE_READS_END();
+
+    // are we done?
+    MU1.Lock();
+    if (COND == N_writers)
+      cont = false;
+    MU1.Unlock();
+    usleep(100);
+  }
+}
+
+void Run() {
+  printf("test69: negative\n");
+  MyThreadArray t(Reader, Writer, Writer, Writer);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 69)
+}  // namespace test69
+
+// test70: STAB. Check that TRACE_MEMORY works. {{{1
+namespace test70 {
+int     GLOB = 0;
+void Run() {
+  printf("test70: negative\n");
+  ANNOTATE_TRACE_MEMORY(&GLOB);
+  GLOB = 1;
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 70)
+}  // namespace test70
+
+
+
+// test71: TN. strlen, index. {{{1
+namespace test71 {
+// This test is a reproducer for a benign race in strlen (as well as index, etc). 
+// Some implementations of strlen may read up to 7 bytes past the end of the string 
+// thus touching memory which may not belong to this string. 
+// Such race is benign because the data read past the end of the string is not used.
+//
+// Here, we allocate a 8-byte aligned string str and initialize first 5 bytes.
+// Then one thread calls strlen(str) (as well as index & rindex)
+// and another thread initializes str[5]..str[7]. 
+//
+// This can be fixed in Helgrind by intercepting strlen and replacing it 
+// with a simpler implementation. 
+
+char    *str;
+void WorkerX() {
+  usleep(100000);
+  CHECK(strlen(str) == 4);
+  CHECK(index(str, 'X') == str);
+  CHECK(index(str, 'x') == str+1);
+  CHECK(index(str, 'Y') == NULL);
+  CHECK(rindex(str, 'X') == str+2);
+  CHECK(rindex(str, 'x') == str+3);
+  CHECK(rindex(str, 'Y') == NULL);
+}
+void WorkerY() {
+  str[5] = 'Y';
+  str[6] = 'Y';
+  str[7] = '\0';
+}
+
+void Run() {
+  str = new char[8];
+  str[0] = 'X';
+  str[1] = 'x';
+  str[2] = 'X';
+  str[3] = 'x';
+  str[4] = '\0';
+
+  printf("test71: negative (strlen & index)\n");
+  MyThread t1(WorkerY);
+  MyThread t2(WorkerX);
+  t1.Start();
+  t2.Start();
+  t1.Join();
+  t2.Join();
+  printf("\tstrX=%s; strY=%s\n", str, str+5);
+}
+REGISTER_TEST(Run, 71)
+}  // namespace test71
+
+
+// test72: STAB. Stress test for the number of segment sets (SSETs). {{{1
+namespace test72 {
+#ifndef NO_BARRIER
+// Variation of test33. 
+// Instead of creating Nlog*N_iter threads, 
+// we create Nlog threads and do N_iter barriers. 
+int     GLOB = 0;
+const int N_iter = 30;
+const int Nlog  = 16;
+const int N     = 1 << Nlog;
+static int64_t ARR1[N];
+static int64_t ARR2[N];
+Barrier *barriers[N_iter];
+Mutex   MU; 
+
+void Worker() {
+  MU.Lock();
+  int n = ++GLOB;
+  MU.Unlock();
+
+  n %= Nlog;
+
+  long t0 = clock();
+  long t = t0;
+
+  for (int it = 0; it < N_iter; it++) {
+    if(n == 0) {
+      //printf("Iter: %d; %ld %ld\n", it, clock() - t, clock() - t0);
+      t = clock();
+    }
+    // Iterate N_iter times, block on barrier after each iteration. 
+    // This way Helgrind will create new segments after each barrier. 
+
+    for (int x = 0; x < 2; x++) { 
+      // run the inner loop twice. 
+      // When a memory location is accessed second time it is likely 
+      // that the state (SVal) will be unchanged. 
+      // The memory machine may optimize this case. 
+      for (int i = 0; i < N; i++) {
+        // ARR1[i] and ARR2[N-1-i] are accessed by threads from i-th subset 
+        if (i & (1 << n)) {
+          CHECK(ARR1[i] == 0);
+          CHECK(ARR2[N-1-i] == 0);
+        }
+      }
+    }
+    barriers[it]->Block();
+  }
+}
+
+
+void Run() {
+  printf("test72:\n");
+
+  std::vector<MyThread*> vec(Nlog);
+
+  for (int i = 0; i < N_iter; i++)
+    barriers[i] = new Barrier(Nlog);
+
+  // Create and start Nlog threads
+  for (int i = 0; i < Nlog; i++) {
+    vec[i] = new MyThread(Worker);
+    vec[i]->Start();
+  }
+  
+  // Join all threads. 
+  for (int i = 0; i < Nlog; i++) {
+    vec[i]->Join();
+    delete vec[i];
+  }
+  for (int i = 0; i < N_iter; i++)
+    delete barriers[i];
+
+  /*printf("\tGLOB=%d; ARR[1]=%d; ARR[7]=%d; ARR[N-1]=%d\n", 
+         GLOB, (int)ARR1[1], (int)ARR1[7], (int)ARR1[N-1]);*/
+}
+REGISTER_TEST2(Run, 72, STABILITY|PERFORMANCE|EXCLUDE_FROM_ALL);
+#endif // NO_BARRIER
+}  // namespace test72
+
+
+// test73: STAB. Stress test for the number of (SSETs), different access sizes. {{{1
+namespace test73 {
+#ifndef NO_BARRIER
+// Variation of test72. 
+// We perform accesses of different sizes to the same location. 
+int     GLOB = 0;
+const int N_iter = 2;
+const int Nlog  = 16;
+const int N     = 1 << Nlog;
+union uint64_union {
+  uint64_t u64[1];
+  uint32_t u32[2];
+  uint16_t u16[4];
+  uint8_t  u8 [8];
+};
+static uint64_union ARR1[N];
+union uint32_union {
+  uint32_t u32[1];
+  uint16_t u16[2];
+  uint8_t  u8 [4];
+};
+static uint32_union ARR2[N];
+Barrier *barriers[N_iter];
+Mutex   MU; 
+
+void Worker() {
+  MU.Lock();
+  int n = ++GLOB;
+  MU.Unlock();
+
+  n %= Nlog;
+
+  for (int it = 0; it < N_iter; it++) {
+    // Iterate N_iter times, block on barrier after each iteration. 
+    // This way Helgrind will create new segments after each barrier. 
+
+    for (int x = 0; x < 4; x++) { 
+      for (int i = 0; i < N; i++) {
+        // ARR1[i] are accessed by threads from i-th subset 
+        if (i & (1 << n)) {
+          for (int off = 0; off < (1 << x); off++) {
+            switch(x) {
+              case 0: CHECK(ARR1[i].u64[off] == 0); break;
+              case 1: CHECK(ARR1[i].u32[off] == 0); break;
+              case 2: CHECK(ARR1[i].u16[off] == 0); break;
+              case 3: CHECK(ARR1[i].u8 [off] == 0); break;
+            }
+            switch(x) {
+              case 1: CHECK(ARR2[i].u32[off] == 0); break;
+              case 2: CHECK(ARR2[i].u16[off] == 0); break;
+              case 3: CHECK(ARR2[i].u8 [off] == 0); break;
+            }
+          }
+        }
+      }
+    }
+    barriers[it]->Block();
+  }
+}
+
+
+
+void Run() {
+  printf("test73:\n");
+
+  std::vector<MyThread*> vec(Nlog);
+
+  for (int i = 0; i < N_iter; i++)
+    barriers[i] = new Barrier(Nlog);
+
+  // Create and start Nlog threads
+  for (int i = 0; i < Nlog; i++) {
+    vec[i] = new MyThread(Worker);
+    vec[i]->Start();
+  }
+  
+  // Join all threads. 
+  for (int i = 0; i < Nlog; i++) {
+    vec[i]->Join();
+    delete vec[i];
+  }
+  for (int i = 0; i < N_iter; i++)
+    delete barriers[i];
+
+  /*printf("\tGLOB=%d; ARR[1]=%d; ARR[7]=%d; ARR[N-1]=%d\n", 
+         GLOB, (int)ARR1[1], (int)ARR1[7], (int)ARR1[N-1]);*/
+}
+REGISTER_TEST2(Run, 73, STABILITY|PERFORMANCE|EXCLUDE_FROM_ALL);
+#endif // NO_BARRIER
+}  // namespace test73
+
+
+// test74: PERF. A lot of lock/unlock calls. {{{1
+namespace    test74 {
+const int N = 100000;
+Mutex   MU; 
+void Run() {
+  printf("test74: perf\n");
+  for (int i = 0; i < N; i++ ) {
+    MU.Lock();
+    MU.Unlock();
+  }
+}
+REGISTER_TEST(Run, 74)
+}  // namespace test74
+
+
+// test75: TN. Test for sem_post, sem_wait, sem_trywait. {{{1
+namespace test75 {
+int     GLOB = 0;
+sem_t   sem[2];
+
+void Poster() {
+  GLOB = 1;
+  sem_post(&sem[0]);
+  sem_post(&sem[1]);
+}
+
+void Waiter() {
+  sem_wait(&sem[0]);
+  CHECK(GLOB==1);
+}
+void TryWaiter() {
+  usleep(500000);
+  sem_trywait(&sem[1]);
+  CHECK(GLOB==1);
+}
+
+void Run() {
+#ifndef DRT_NO_SEM
+  sem_init(&sem[0], 0, 0);
+  sem_init(&sem[1], 0, 0);
+
+  printf("test75: negative\n");
+  {
+    MyThreadArray t(Poster, Waiter);
+    t.Start();
+    t.Join();
+  }
+  GLOB = 2;
+  {
+    MyThreadArray t(Poster, TryWaiter);
+    t.Start();
+    t.Join();
+  }
+  printf("\tGLOB=%d\n", GLOB);
+
+  sem_destroy(&sem[0]);
+  sem_destroy(&sem[1]);
+#endif
+}
+REGISTER_TEST(Run, 75)
+}  // namespace test75
+
+// RefCountedClass {{{1
+struct RefCountedClass {
+ public:
+  RefCountedClass() {
+    annotate_unref_ = false;
+    ref_ = 0;
+    data_ = 0;
+  }
+
+  ~RefCountedClass() {
+    CHECK(ref_ == 0);     // race may be reported here 
+    int data_val = data_; // and here     
+                          // if MU is not annotated
+    data_ = 0;
+    ref_ = -1;
+    printf("\tRefCountedClass::data_ = %d\n", data_val);
+  }
+
+  void AccessData() {
+    this->mu_.Lock();
+    this->data_++;
+    this->mu_.Unlock();
+  }
+
+  void Ref() {
+    MU.Lock();
+    CHECK(ref_ >= 0);
+    ref_++;
+    MU.Unlock();
+  }
+
+  void Unref() {
+    MU.Lock();
+    CHECK(ref_ > 0);
+    ref_--;
+    bool do_delete = ref_ == 0;
+    if (annotate_unref_) {
+      ANNOTATE_CONDVAR_SIGNAL(this);
+    }
+    MU.Unlock();
+    if (do_delete) {
+      if (annotate_unref_) {
+        ANNOTATE_CONDVAR_WAIT(this);
+      }
+      delete this;
+    } 
+  }
+
+  static void Annotate_MU() {
+    ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&MU);
+  }
+  void AnnotateUnref() {
+    annotate_unref_ = true;
+  }
+  void Annotate_Race() {
+    ANNOTATE_BENIGN_RACE(&this->data_, "needs annotation");
+    ANNOTATE_BENIGN_RACE(&this->ref_, "needs annotation");
+  }
+ private: 
+  bool annotate_unref_;
+
+  int data_;
+  Mutex mu_; // protects data_ 
+
+  int ref_; 
+  static Mutex MU; // protects ref_
+};
+
+Mutex RefCountedClass::MU;
+
+// test76: FP. Ref counting, no annotations. {{{1
+namespace test76 {
+#ifndef NO_BARRIER
+int     GLOB = 0;
+Barrier barrier(4);
+RefCountedClass *object = NULL; 
+void Worker() {
+  object->Ref();
+  barrier.Block();
+  object->AccessData();
+  object->Unref();
+}
+void Run() {
+  printf("test76: false positive (ref counting)\n");
+  object = new RefCountedClass; 
+  object->Annotate_Race();
+  MyThreadArray t(Worker, Worker, Worker, Worker);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST2(Run, 76, FEATURE)
+#endif // NO_BARRIER
+}  // namespace test76
+
+
+
+// test77: TN. Ref counting, MU is annotated. {{{1
+namespace test77 {
+#ifndef NO_BARRIER
+// same as test76, but RefCountedClass::MU is annotated. 
+int     GLOB = 0;
+Barrier barrier(4);
+RefCountedClass *object = NULL; 
+void Worker() {
+  object->Ref();
+  barrier.Block();
+  object->AccessData();
+  object->Unref();
+}
+void Run() {
+  printf("test77: true negative (ref counting), mutex is annotated\n");
+  RefCountedClass::Annotate_MU();
+  object = new RefCountedClass; 
+  MyThreadArray t(Worker, Worker, Worker, Worker);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST(Run, 77)
+#endif // NO_BARRIER
+}  // namespace test77
+
+
+
+// test78: TN. Ref counting, Unref is annotated. {{{1
+namespace test78 {
+#ifndef NO_BARRIER
+// same as test76, but RefCountedClass::Unref is annotated. 
+int     GLOB = 0;
+Barrier barrier(4);
+RefCountedClass *object = NULL; 
+void Worker() {
+  object->Ref();
+  barrier.Block();
+  object->AccessData();
+  object->Unref();
+}
+void Run() {
+  printf("test78: true negative (ref counting), Unref is annotated\n");
+  RefCountedClass::Annotate_MU();
+  object = new RefCountedClass; 
+  MyThreadArray t(Worker, Worker, Worker, Worker);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST(Run, 78)
+#endif // NO_BARRIER
+}  // namespace test78
+
+
+
+// test79 TN. Swap. {{{1
+namespace test79 {
+#if 0
+typedef __gnu_cxx::hash_map<int, int> map_t;
+#else
+typedef std::map<int, int> map_t;
+#endif
+map_t   MAP;
+Mutex   MU; 
+
+// Here we use swap to pass MAP between threads.
+// The synchronization is correct, but w/o ANNOTATE_MUTEX_IS_USED_AS_CONDVAR
+// Helgrind will complain.
+
+void Worker1() {
+  map_t tmp;
+  MU.Lock();
+  // We swap the new empty map 'tmp' with 'MAP'.
+  MAP.swap(tmp); 
+  MU.Unlock();
+  // tmp (which is the old version of MAP) is destroyed here.
+}
+
+void Worker2() {
+  MU.Lock();
+  MAP[1]++;  // Just update MAP under MU.
+  MU.Unlock();
+}
+
+void Worker3() { Worker1(); } 
+void Worker4() { Worker2(); } 
+
+void Run() {
+  ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&MU);
+  printf("test79: negative\n");
+  MyThreadArray t(Worker1, Worker2, Worker3, Worker4);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST(Run, 79)
+}  // namespace test79
+
+
+// AtomicRefCountedClass. {{{1
+// Same as RefCountedClass, but using atomic ops instead of mutex.
+struct AtomicRefCountedClass {
+ public:
+  AtomicRefCountedClass() {
+    annotate_unref_ = false;
+    ref_ = 0;
+    data_ = 0;
+  }
+
+  ~AtomicRefCountedClass() {
+    CHECK(ref_ == 0);     // race may be reported here 
+    int data_val = data_; // and here     
+    data_ = 0;
+    ref_ = -1;
+    printf("\tRefCountedClass::data_ = %d\n", data_val);
+  }
+
+  void AccessData() {
+    this->mu_.Lock();
+    this->data_++;
+    this->mu_.Unlock();
+  }
+
+  void Ref() {
+    AtomicIncrement(&ref_, 1);
+  }
+
+  void Unref() {
+    // DISCLAIMER: I am not sure I've implemented this correctly
+    // (might require some memory barrier, etc).
+    // But this implementation of reference counting is enough for 
+    // the purpose of Helgrind demonstration.
+    AtomicIncrement(&ref_, -1);
+    if (annotate_unref_) { ANNOTATE_CONDVAR_SIGNAL(this); }
+    if (ref_ == 0) {
+      if (annotate_unref_) { ANNOTATE_CONDVAR_WAIT(this); }
+      delete this;
+    } 
+  }
+
+  void AnnotateUnref() {
+    annotate_unref_ = true;
+  }
+  void Annotate_Race() {
+    ANNOTATE_BENIGN_RACE(&this->data_, "needs annotation");
+  }
+ private: 
+  bool annotate_unref_;
+
+  Mutex mu_; 
+  int data_; // under mu_
+
+  int ref_;  // used in atomic ops.
+};
+
+// test80: FP. Ref counting with atomics, no annotations. {{{1
+namespace test80 {
+#ifndef NO_BARRIER
+int     GLOB = 0;
+Barrier barrier(4);
+AtomicRefCountedClass *object = NULL; 
+void Worker() {
+  object->Ref();
+  barrier.Block();
+  object->AccessData();
+  object->Unref(); // All the tricky stuff is here.
+}
+void Run() {
+  printf("test80: false positive (ref counting)\n");
+  object = new AtomicRefCountedClass; 
+  object->Annotate_Race();
+  MyThreadArray t(Worker, Worker, Worker, Worker);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST2(Run, 80, FEATURE|EXCLUDE_FROM_ALL)
+#endif // NO_BARRIER
+}  // namespace test80
+
+
+// test81: TN. Ref counting with atomics, Unref is annotated. {{{1
+namespace test81 {
+#ifndef NO_BARRIER
+// same as test80, but Unref is annotated.
+int     GLOB = 0;
+Barrier barrier(4);
+AtomicRefCountedClass *object = NULL; 
+void Worker() {
+  object->Ref();
+  barrier.Block();
+  object->AccessData();
+  object->Unref(); // All the tricky stuff is here.
+}
+void Run() {
+  printf("test81: negative (annotated ref counting)\n");
+  object = new AtomicRefCountedClass; 
+  object->AnnotateUnref();
+  MyThreadArray t(Worker, Worker, Worker, Worker);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST2(Run, 81, FEATURE|EXCLUDE_FROM_ALL)
+#endif // NO_BARRIER
+}  // namespace test81
+
+
+// test82: Object published w/o synchronization. {{{1
+namespace test82 {
+
+// Writer creates a new object and makes the pointer visible to the Reader.
+// Reader waits until the object pointer is non-null and reads the object. 
+//
+// On Core 2 Duo this test will sometimes (quite rarely) fail in 
+// the CHECK below, at least if compiled with -O2.
+//
+// The sequence of events:: 
+// Thread1:                  Thread2: 
+//   a. arr_[...] = ...
+//   b. foo[i]    = ...
+//                           A. ... = foo[i]; // non NULL
+//                           B. ... = arr_[...]; 
+// 
+//  Since there is no proper synchronization, during the even (B)
+//  Thread2 may not see the result of the event (a). 
+//  On x86 and x86_64 this happens due to compiler reordering instructions.
+//  On other arcitectures it may also happen due to cashe inconsistency.
+
+class FOO {
+ public: 
+  FOO() {
+    idx_ = rand() % 1024;
+    arr_[idx_] = 77777;
+  //   __asm__ __volatile__("" : : : "memory"); // this fixes! 
+  }
+  static void check(volatile FOO *foo) {
+    CHECK(foo->arr_[foo->idx_] == 77777);
+  }
+ private:
+  int idx_;
+  int arr_[1024];
+};
+
+const int N = 100000;
+static volatile FOO *foo[N];
+Mutex   MU; 
+
+void Writer() {
+  for (int i = 0; i < N; i++) {
+    foo[i] = new FOO;
+    usleep(100);
+  }
+}
+
+void Reader() {
+  for (int i = 0; i < N; i++) {
+    while (!foo[i]) {
+      MU.Lock();   // this is NOT a synchronization, 
+      MU.Unlock(); // it just helps foo[i] to become visible in Reader.
+    }
+    if ((i % 100) == 0) {
+      printf("rd %d\n", i);
+    }
+    // At this point Reader() sees the new value of foo[i] 
+    // but in very rare cases will not see the new value of foo[i]->arr_.
+    // Thus this CHECK will sometimes fail.
+    FOO::check(foo[i]);
+  }
+}
+
+void Run() {
+  printf("test82: positive\n");
+  MyThreadArray t(Writer, Reader);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST2(Run, 82, FEATURE|EXCLUDE_FROM_ALL)
+}  // namespace test82
+
+
+// test83: Object published w/o synchronization (simple version){{{1
+namespace test83 {
+// A simplified version of test83 (example of a wrong code).
+// This test, though incorrect, will almost never fail.
+volatile static int *ptr = NULL;
+Mutex   MU; 
+
+void Writer() {
+  usleep(100);
+  ptr = new int(777);
+}
+
+void Reader() {
+  while(!ptr) {
+    MU.Lock(); // Not a synchronization!
+    MU.Unlock(); 
+  }
+  CHECK(*ptr == 777);
+}
+
+void Run() {
+//  printf("test83: positive\n");
+  MyThreadArray t(Writer, Reader);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST2(Run, 83, FEATURE|EXCLUDE_FROM_ALL)
+}  // namespace test83
+
+
+// test84: TP. True race (regression test for a bug related to atomics){{{1
+namespace test84 {
+// Helgrind should not create HB arcs for the bus lock even when 
+// --pure-happens-before=yes is used.
+// Bug found in by Bart Van Assche, the test is taken from 
+// valgrind file drd/tests/atomic_var.c.
+static int s_x = 0;
+/* s_dummy[] ensures that s_x and s_y are not in the same cache line. */
+static char s_dummy[512] = {0};
+static int s_y;
+
+void thread_func_1()
+{
+  s_y = 1;
+  AtomicIncrement(&s_x, 1);
+}
+
+void thread_func_2()
+{
+  while (AtomicIncrement(&s_x, 0) == 0)
+    ;
+  printf("y = %d\n", s_y);
+}
+
+
+void Run() {
+  CHECK(s_dummy[0] == 0);  // Avoid compiler warning about 's_dummy unused'.
+  printf("test84: positive\n");
+  FAST_MODE_INIT(&s_y);
+  ANNOTATE_EXPECT_RACE_FOR_TSAN(&s_y, "test84: TP. true race.");
+  MyThreadArray t(thread_func_1, thread_func_2);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST(Run, 84)
+}  // namespace test84
+
+
+// test85: Test for RunningOnValgrind(). {{{1
+namespace  test85 {
+int     GLOB = 0;
+void Run() {
+  printf("test85: RunningOnValgrind() = %d\n", RunningOnValgrind());
+}
+REGISTER_TEST(Run, 85)
+}  // namespace test85
+
+
+// test86: Test for race inside DTOR: racey write to vptr. Benign. {{{1
+namespace test86 {
+// This test shows a racey access to vptr (the pointer to vtbl).
+// We have class A and class B derived from A. 
+// Both classes have a virtual function f() and a virtual DTOR.
+// We create an object 'A *a = new B'
+// and pass this object from Thread1 to Thread2.
+// Thread2 calls a->f(). This call reads a->vtpr.
+// Thread1 deletes the object. B::~B waits untill the object can be destroyed 
+// (flag_stopped == true) but at the very beginning of B::~B 
+// a->vptr is written to. 
+// So, we have a race on a->vptr. 
+// On this particular test this race is benign, but test87 shows 
+// how such race could harm.
+//
+//
+// 
+// Threa1:                                            Thread2: 
+// 1. A a* = new B;                                  
+// 2. Q.Put(a); ------------\                         .            
+//                           \-------------------->   a. a = Q.Get();
+//                                                    b. a->f();
+//                                       /---------   c. flag_stopped = true;
+// 3. delete a;                         /
+//    waits untill flag_stopped <------/
+//    inside the dtor
+// 
+
+bool flag_stopped = false;
+Mutex mu;
+
+ProducerConsumerQueue Q(INT_MAX);  // Used to pass A* between threads.
+
+struct A {
+  A()  { printf("A::A()\n"); }
+  virtual ~A() { printf("A::~A()\n"); }
+  virtual void f() { }
+
+  uintptr_t padding[15];
+} __attribute__ ((aligned (64)));
+
+struct B: A {
+  B()  { printf("B::B()\n"); }
+  virtual ~B() { 
+    // The race is here.    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+    printf("B::~B()\n"); 
+    // wait until flag_stopped is true.
+    mu.LockWhen(Condition(&ArgIsTrue, &flag_stopped));
+    mu.Unlock();
+    printf("B::~B() done\n"); 
+  }
+  virtual void f() { }
+};
+
+void Waiter() {
+  A *a = new B;
+  if (!Tsan_FastMode())
+    ANNOTATE_EXPECT_RACE(a, "test86: expected race on a->vptr");
+  printf("Waiter: B created\n");
+  Q.Put(a);
+  usleep(100000); // so that Worker calls a->f() first.
+  printf("Waiter: deleting B\n");
+  delete a;
+  printf("Waiter: B deleted\n");
+  usleep(100000);
+  printf("Waiter: done\n");
+}
+
+void Worker() {
+  A *a = reinterpret_cast<A*>(Q.Get());
+  printf("Worker: got A\n");
+  a->f();
+    
+  mu.Lock();
+  flag_stopped = true;
+  mu.Unlock();
+  usleep(200000);
+  printf("Worker: done\n");
+}
+
+void Run() {
+  printf("test86: positive, race inside DTOR\n");
+  MyThreadArray t(Waiter, Worker);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST(Run, 86)
+}  // namespace test86
+
+
+// test87: Test for race inside DTOR: racey write to vptr. Harmful.{{{1
+namespace test87 {
+// A variation of test86 where the race is harmful.
+// Here we have class C derived from B. 
+// We create an object 'A *a = new C' in Thread1 and pass it to Thread2.
+// Thread2 calls a->f(). 
+// Thread1 calls 'delete a'. 
+// It first calls C::~C, then B::~B where it rewrites the vptr to point 
+// to B::vtbl. This is a problem because Thread2 might not have called a->f() 
+// and now it will call B::f instead of C::f.
+//
+bool flag_stopped = false;
+Mutex mu;
+
+ProducerConsumerQueue Q(INT_MAX);  // Used to pass A* between threads.
+
+struct A {
+  A()  { printf("A::A()\n"); }
+  virtual ~A() { printf("A::~A()\n"); }
+  virtual void f() = 0; // pure virtual.
+};
+
+struct B: A {
+  B()  { printf("B::B()\n"); }
+  virtual ~B() { 
+    // The race is here.    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+    printf("B::~B()\n"); 
+    // wait until flag_stopped is true.
+    mu.LockWhen(Condition(&ArgIsTrue, &flag_stopped));
+    mu.Unlock();
+    printf("B::~B() done\n"); 
+  }
+  virtual void f() = 0; // pure virtual.
+};
+
+struct C: B {
+  C()  { printf("C::C()\n"); }
+  virtual ~C() { printf("C::~C()\n"); }
+  virtual void f() { }
+};
+
+void Waiter() {
+  A *a = new C;
+  Q.Put(a);
+  delete a;
+}
+
+void Worker() {
+  A *a = reinterpret_cast<A*>(Q.Get());
+  a->f();
+    
+  mu.Lock();
+  flag_stopped = true;
+  ANNOTATE_CONDVAR_SIGNAL(&mu);
+  mu.Unlock();
+}
+
+void Run() {
+  printf("test87: positive, race inside DTOR\n");
+  MyThreadArray t(Waiter, Worker);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST2(Run, 87, FEATURE|EXCLUDE_FROM_ALL)
+}  // namespace test87
+
+
+// test88: Test for ANNOTATE_IGNORE_WRITES_*{{{1
+namespace test88 {
+// a recey write annotated with ANNOTATE_IGNORE_WRITES_BEGIN/END.
+int     GLOB = 0;
+void Worker() {
+  ANNOTATE_IGNORE_WRITES_BEGIN();
+  GLOB = 1;
+  ANNOTATE_IGNORE_WRITES_END();
+}
+void Run() {
+  printf("test88: negative, test for ANNOTATE_IGNORE_WRITES_*\n");
+  MyThread t(Worker);
+  t.Start();
+  GLOB = 1;
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 88)
+}  // namespace test88
+
+
+// test89: Test for debug info. {{{1
+namespace test89 {
+// Simlpe races with different objects (stack, heap globals; scalars, structs).
+// Also, if run with --trace-level=2 this test will show a sequence of 
+// CTOR and DTOR calls.
+struct STRUCT {
+  int a, b, c;
+};
+
+struct A {
+  int a;  
+  A() { 
+    ANNOTATE_TRACE_MEMORY(&a);
+    a = 1; 
+  } 
+  virtual ~A() {
+    a = 4;
+  }
+}; 
+
+struct B : A {  
+  B()  { CHECK(a == 1); } 
+  virtual ~B() { CHECK(a == 3); }
+};
+struct C : B {
+  C()  { a = 2; }
+  virtual ~C() { a = 3; } 
+};
+
+int            GLOBAL = 0;
+int           *STACK  = 0;
+STRUCT         GLOB_STRUCT;
+STRUCT        *STACK_STRUCT;
+STRUCT        *HEAP_STRUCT;
+
+void Worker() {
+  GLOBAL = 1;
+  *STACK = 1;
+  GLOB_STRUCT.b   = 1;
+  STACK_STRUCT->b = 1;
+  HEAP_STRUCT->b  = 1;
+}
+
+void Run() {
+  int stack_var = 0;
+  STACK = &stack_var;
+
+  STRUCT stack_struct;
+  STACK_STRUCT = &stack_struct;
+
+  HEAP_STRUCT = new STRUCT;
+
+  printf("test89: negative\n");
+  MyThreadArray t(Worker, Worker);
+  t.Start();
+  t.Join();
+
+  delete HEAP_STRUCT;
+
+  A *a = new C;
+  printf("Using 'a->a':  %d\n", a->a);
+  delete a;
+}
+REGISTER_TEST2(Run, 89, FEATURE|EXCLUDE_FROM_ALL)
+}  // namespace test89
+
+
+// test90: FP. Test for a safely-published pointer (read-only). {{{1
+namespace test90 {
+// The Publisher creates an object and safely publishes it under a mutex.
+// Readers access the object read-only.
+// See also test91.
+//
+// Without annotations Helgrind will issue a false positive in Reader(). 
+//
+// Choices for annotations: 
+//   -- ANNOTATE_CONDVAR_SIGNAL/ANNOTATE_CONDVAR_WAIT
+//   -- ANNOTATE_MUTEX_IS_USED_AS_CONDVAR
+//   -- ANNOTATE_PUBLISH_MEMORY_RANGE.
+
+int     *GLOB = 0;
+Mutex   MU; 
+
+void Publisher() {
+  MU.Lock();
+  GLOB = (int*)memalign(64, sizeof(int));
+  *GLOB = 777;
+  if (!Tsan_PureHappensBefore() && !Tsan_FastMode())
+    ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB, "test90. FP. This is a false positve");
+  MU.Unlock();
+  usleep(200000);
+}
+
+void Reader() {
+  usleep(10000);
+  while (true) {
+    MU.Lock();
+    int *p = GLOB;
+    MU.Unlock();
+    if (p) {
+      CHECK(*p == 777);  // Race is reported here.
+      break;
+    }
+  }
+}
+
+void Run() {
+  printf("test90: false positive (safely published pointer).\n");
+  MyThreadArray t(Publisher, Reader, Reader, Reader);
+  t.Start();
+  t.Join();
+  printf("\t*GLOB=%d\n", *GLOB);
+  free(GLOB);
+}
+REGISTER_TEST(Run, 90)
+}  // namespace test90
+
+
+// test91: FP. Test for a safely-published pointer (read-write). {{{1
+namespace test91 {
+// Similar to test90.
+// The Publisher creates an object and safely publishes it under a mutex MU1.
+// Accessors get the object under MU1 and access it (read/write) under MU2.
+//
+// Without annotations Helgrind will issue a false positive in Accessor(). 
+//
+
+int     *GLOB = 0;
+Mutex   MU, MU1, MU2; 
+
+void Publisher() {
+  MU1.Lock();
+  GLOB = (int*)memalign(64, sizeof(int));
+  *GLOB = 777;
+  if (!Tsan_PureHappensBefore() && !Tsan_FastMode())
+    ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB, "test91. FP. This is a false positve");
+  MU1.Unlock();
+}
+
+void Accessor() {
+  usleep(10000);
+  while (true) {
+    MU1.Lock();
+    int *p = GLOB;
+    MU1.Unlock();
+    if (p) {
+      MU2.Lock();
+      (*p)++;  // Race is reported here.
+      CHECK(*p >  777);  
+      MU2.Unlock();
+      break;
+    }
+  }
+}
+
+void Run() {
+  printf("test91: false positive (safely published pointer, read/write).\n");
+  MyThreadArray t(Publisher, Accessor, Accessor, Accessor);
+  t.Start();
+  t.Join();
+  printf("\t*GLOB=%d\n", *GLOB);
+  free(GLOB);
+}
+REGISTER_TEST(Run, 91)
+}  // namespace test91
+
+
+// test92: TN. Test for a safely-published pointer (read-write), annotated. {{{1
+namespace test92 {
+// Similar to test91, but annotated with ANNOTATE_PUBLISH_MEMORY_RANGE.
+//
+//
+// Publisher:                                       Accessors: 
+//
+// 1. MU1.Lock()
+// 2. Create GLOB.
+// 3. ANNOTATE_PUBLISH_...(GLOB) -------\            .
+// 4. MU1.Unlock()                       \           .
+//                                        \          a. MU1.Lock()
+//                                         \         b. Get GLOB
+//                                          \        c. MU1.Unlock()
+//                                           \-->    d. Access GLOB
+//
+//  A happens-before arc is created between ANNOTATE_PUBLISH_MEMORY_RANGE and 
+//  accesses to GLOB.
+
+struct ObjType {
+  int arr[10];
+};
+
+ObjType *GLOB = 0;
+Mutex   MU, MU1, MU2; 
+
+void Publisher() {
+  MU1.Lock();
+  GLOB = new ObjType;
+  for (int i = 0; i < 10; i++) {
+    GLOB->arr[i] = 777;
+  }
+  // This annotation should go right before the object is published.
+  ANNOTATE_PUBLISH_MEMORY_RANGE(GLOB, sizeof(*GLOB));
+  MU1.Unlock();
+}
+
+void Accessor(int index) {
+  while (true) {
+    MU1.Lock();
+    ObjType *p = GLOB;
+    MU1.Unlock();
+    if (p) {
+      MU2.Lock();
+      p->arr[index]++;  // W/o the annotations the race will be reported here.
+      CHECK(p->arr[index] ==  778);  
+      MU2.Unlock();
+      break;
+    }
+  }
+}
+
+void Accessor0() { Accessor(0); }
+void Accessor5() { Accessor(5); }
+void Accessor9() { Accessor(9); }
+
+void Run() {
+  printf("test92: safely published pointer, read/write, annotated.\n");
+  MyThreadArray t(Publisher, Accessor0, Accessor5, Accessor9);
+  t.Start();
+  t.Join();
+  printf("\t*GLOB=%d\n", GLOB->arr[0]);
+}
+REGISTER_TEST(Run, 92)
+}  // namespace test92
+
+
+// test93: TP. Test for incorrect usage of ANNOTATE_PUBLISH_MEMORY_RANGE. {{{1
+namespace test93 {
+int     GLOB = 0;
+
+void Reader() {
+  CHECK(GLOB == 0);
+}
+
+void Publisher() {
+  usleep(10000);
+  // Incorrect, used after the memory has been accessed in another thread. 
+  ANNOTATE_PUBLISH_MEMORY_RANGE(&GLOB, sizeof(GLOB)); 
+}
+
+void Run() {
+  printf("test93: positive, misuse of ANNOTATE_PUBLISH_MEMORY_RANGE\n");
+  MyThreadArray t(Reader, Publisher);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 93, FEATURE|EXCLUDE_FROM_ALL)
+}  // namespace test93
+
+
+// test94: TP. Check do_cv_signal/fake segment logic {{{1
+namespace test94 {
+int     GLOB;
+
+int COND  = 0;
+int COND2 = 0;
+Mutex MU, MU2;
+CondVar CV, CV2;
+
+void Thr1() {
+  usleep(10000);  // Make sure the waiter blocks.
+  
+  GLOB = 1; // WRITE 
+
+  MU.Lock();
+  COND = 1;
+  CV.Signal(); 
+  MU.Unlock();
+}
+void Thr2() {
+  usleep(1000*1000); // Make sure CV2.Signal() "happens after" CV.Signal()
+  usleep(10000);  // Make sure the waiter blocks.
+  
+  MU2.Lock();
+  COND2 = 1;
+  CV2.Signal(); 
+  MU2.Unlock();
+}
+void Thr3() {
+  MU.Lock();
+  while(COND != 1)
+    CV.Wait(&MU);
+  MU.Unlock();  
+}
+void Thr4() {
+  MU2.Lock();
+  while(COND2 != 1)
+    CV2.Wait(&MU2);
+  MU2.Unlock();
+  GLOB = 2; // READ: no HB-relation between CV.Signal and CV2.Wait !
+}
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test94: TP.");
+  printf("test94: TP. Check do_cv_signal/fake segment logic\n");
+  MyThreadArray mta(Thr1, Thr2, Thr3, Thr4);
+  mta.Start();
+  mta.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 94);
+}  // namespace test94
+
+// test95: TP. Check do_cv_signal/fake segment logic {{{1
+namespace test95 {
+int     GLOB = 0;
+
+int COND  = 0;
+int COND2 = 0;
+Mutex MU, MU2;
+CondVar CV, CV2;
+
+void Thr1() {
+  usleep(1000*1000); // Make sure CV2.Signal() "happens before" CV.Signal()
+  usleep(10000);  // Make sure the waiter blocks.
+  
+  GLOB = 1; // WRITE 
+
+  MU.Lock();
+  COND = 1;
+  CV.Signal(); 
+  MU.Unlock();
+}
+void Thr2() {
+  usleep(10000);  // Make sure the waiter blocks.
+  
+  MU2.Lock();
+  COND2 = 1;
+  CV2.Signal(); 
+  MU2.Unlock();
+}
+void Thr3() {
+  MU.Lock();
+  while(COND != 1)
+    CV.Wait(&MU);
+  MU.Unlock();  
+}
+void Thr4() {
+  MU2.Lock();
+  while(COND2 != 1)
+    CV2.Wait(&MU2);
+  MU2.Unlock();
+  GLOB = 2; // READ: no HB-relation between CV.Signal and CV2.Wait !
+}
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test95: TP.");
+  printf("test95: TP. Check do_cv_signal/fake segment logic\n");
+  MyThreadArray mta(Thr1, Thr2, Thr3, Thr4);
+  mta.Start();
+  mta.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 95);
+}  // namespace test95
+
+// test96: TN. tricky LockSet behaviour {{{1
+// 3 threads access the same memory with three different
+// locksets: {A, B}, {B, C}, {C, A}.
+// These locksets have empty intersection
+namespace test96 {
+int     GLOB = 0;
+
+Mutex A, B, C;
+
+void Thread1() {
+  MutexLock a(&A);
+  MutexLock b(&B);
+  GLOB++;
+}
+
+void Thread2() {
+  MutexLock b(&B);
+  MutexLock c(&C);
+  GLOB++;
+}
+
+void Thread3() {
+  MutexLock a(&A);
+  MutexLock c(&C);
+  GLOB++;
+}
+
+void Run() {
+  printf("test96: FP. tricky LockSet behaviour\n");
+  ANNOTATE_TRACE_MEMORY(&GLOB);
+  MyThreadArray mta(Thread1, Thread2, Thread3);
+  mta.Start();
+  mta.Join();
+  CHECK(GLOB == 3);
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 96);
+}  // namespace test96
+
+// test97: This test shows false negative with --fast-mode=yes {{{1
+namespace test97 {
+const int HG_CACHELINE_SIZE = 64;
+
+Mutex MU;
+
+const int ARRAY_SIZE = HG_CACHELINE_SIZE * 4 / sizeof(int);
+int array[ARRAY_SIZE];
+int * GLOB = &array[ARRAY_SIZE/2];
+/*
+  We use sizeof(array) == 4 * HG_CACHELINE_SIZE to be sure that GLOB points
+  to a memory inside a CacheLineZ which is inside array's memory range 
+ */
+
+void Reader() {
+  usleep(500000);
+  CHECK(777 == *GLOB);
+}
+
+void Run() {
+  MyThreadArray t(Reader);
+  if (!Tsan_FastMode())
+    ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB, "test97: TP. FN with --fast-mode=yes");
+  printf("test97: This test shows false negative with --fast-mode=yes\n");
+
+  t.Start();
+  *GLOB = 777;
+  t.Join();
+}
+
+REGISTER_TEST2(Run, 97, FEATURE)
+}  // namespace test97
+
+// test98: Synchronization via read/write (or send/recv). {{{1
+namespace test98 {
+// The synchronization here is done by a pair of read/write calls
+// that create a happens-before arc. Same may be done with send/recv.
+// Such synchronization is quite unusual in real programs 
+// (why would one synchronizae via a file or socket?), but 
+// quite possible in unittests where one threads runs for producer 
+// and one for consumer.
+//
+// A race detector has to create a happens-before arcs for  
+// {read,send}->{write,recv} even if the file descriptors are different.
+//
+int     GLOB = 0;
+int fd_out = -1;
+int fd_in  = -1;
+
+void Writer() {
+  usleep(1000);
+  GLOB = 1;
+  const char *str = "Hey there!\n";
+  IGNORE_RETURN_VALUE(write(fd_out, str, strlen(str) + 1));
+}
+
+void Reader() {
+  char buff[100];
+  while (read(fd_in, buff, 100) == 0)
+    sleep(1);
+  printf("read: %s\n", buff);
+  GLOB = 2;
+}
+
+void Run() {
+  printf("test98: negative, synchronization via I/O\n");
+  char in_name[100];
+  char out_name[100];
+  // we open two files, on for reading and one for writing, 
+  // but the files are actually the same (symlinked).
+  sprintf(out_name, "/tmp/racecheck_unittest_out.%d", getpid());
+  fd_out = creat(out_name, O_WRONLY | S_IRWXU);
+#ifdef __APPLE__
+  // symlink() is not supported on Darwin. Copy the output file name.
+  strcpy(in_name, out_name);
+#else
+  sprintf(in_name,  "/tmp/racecheck_unittest_in.%d", getpid());
+  IGNORE_RETURN_VALUE(symlink(out_name, in_name));
+#endif
+  fd_in  = open(in_name, 0, O_RDONLY);
+  CHECK(fd_out >= 0);
+  CHECK(fd_in  >= 0);
+  MyThreadArray t(Writer, Reader);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+  // cleanup
+  close(fd_in);
+  close(fd_out);
+  unlink(in_name);
+  unlink(out_name);
+}
+REGISTER_TEST(Run, 98)
+}  // namespace test98
+
+
+// test99: TP. Unit test for a bug in LockWhen*. {{{1
+namespace test99 {
+
+
+bool GLOB = false;
+Mutex mu;
+
+static void Thread1() {
+  for (int i = 0; i < 100; i++) {
+    mu.LockWhenWithTimeout(Condition(&ArgIsTrue, &GLOB), 5);
+    GLOB = false;
+    mu.Unlock();
+    usleep(10000);
+  }
+}
+
+static void Thread2() {
+  for (int i = 0; i < 100; i++) {
+    mu.Lock();
+    mu.Unlock();
+    usleep(10000);
+  }
+}
+
+void Run() {
+  printf("test99: regression test for LockWhen*\n");
+  MyThreadArray t(Thread1, Thread2);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST(Run, 99);
+}  // namespace test99
+
+
+// test100: Test for initialization bit. {{{1
+namespace test100 {
+int     G1 = 0;
+int     G2 = 0;
+int     G3 = 0;
+int     G4 = 0;
+
+void Creator() {
+  G1 = 1; CHECK(G1);
+  G2 = 1;
+  G3 = 1; CHECK(G3);
+  G4 = 1;
+}
+
+void Worker1() {
+  usleep(100000);
+  CHECK(G1);
+  CHECK(G2);
+  G3 = 3;
+  G4 = 3;
+}
+
+void Worker2() {
+
+}
+
+
+void Run() {
+  printf("test100: test for initialization bit. \n");
+  MyThreadArray t(Creator, Worker1, Worker2);
+  ANNOTATE_TRACE_MEMORY(&G1);
+  ANNOTATE_TRACE_MEMORY(&G2);
+  ANNOTATE_TRACE_MEMORY(&G3);
+  ANNOTATE_TRACE_MEMORY(&G4);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST2(Run, 100, FEATURE|EXCLUDE_FROM_ALL)
+}  // namespace test100
+
+
+// test101: TN. Two signals and two waits. {{{1
+namespace test101 {
+Mutex MU;
+CondVar CV;
+int     GLOB = 0;
+
+int C1 = 0, C2 = 0;
+
+void Signaller() {
+  usleep(100000);
+  MU.Lock();
+  C1 = 1;
+  CV.Signal();
+  printf("signal\n");
+  MU.Unlock();
+
+  GLOB = 1;
+
+  usleep(500000);
+  MU.Lock();
+  C2 = 1;
+  CV.Signal();
+  printf("signal\n");
+  MU.Unlock();
+}
+
+void Waiter() {
+  MU.Lock();
+  while(!C1) 
+    CV.Wait(&MU);
+  printf("wait\n");
+  MU.Unlock();
+
+  MU.Lock();
+  while(!C2) 
+    CV.Wait(&MU);
+  printf("wait\n");
+  MU.Unlock();
+
+  GLOB = 2;
+
+}
+
+void Run() {
+  printf("test101: negative\n");
+  MyThreadArray t(Waiter, Signaller);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 101)
+}  // namespace test101
+
+// test102: --fast-mode=yes vs. --initialization-bit=yes {{{1
+namespace test102 {
+const int HG_CACHELINE_SIZE = 64;
+
+Mutex MU;
+
+const int ARRAY_SIZE = HG_CACHELINE_SIZE * 4 / sizeof(int);
+int array[ARRAY_SIZE + 1];
+int * GLOB = &array[ARRAY_SIZE/2];
+/*
+  We use sizeof(array) == 4 * HG_CACHELINE_SIZE to be sure that GLOB points
+  to a memory inside a CacheLineZ which is inside array's memory range 
+*/
+
+void Reader() {
+  usleep(200000);
+  CHECK(777 == GLOB[0]);
+  usleep(400000);
+  CHECK(777 == GLOB[1]);
+}
+
+void Run() {
+  MyThreadArray t(Reader);
+  if (!Tsan_FastMode())
+    ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB+0, "test102: TP. FN with --fast-mode=yes");
+  ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB+1, "test102: TP");
+  printf("test102: --fast-mode=yes vs. --initialization-bit=yes\n");
+
+  t.Start();
+  GLOB[0] = 777;
+  usleep(400000);
+  GLOB[1] = 777;
+  t.Join();
+}
+
+REGISTER_TEST2(Run, 102, FEATURE)
+}  // namespace test102
+
+// test103: Access different memory locations with different LockSets {{{1
+namespace test103 {
+const int N_MUTEXES = 6;
+const int LOCKSET_INTERSECTION_SIZE = 3;
+
+int data[1 << LOCKSET_INTERSECTION_SIZE] = {0};
+Mutex MU[N_MUTEXES];
+
+inline int LS_to_idx (int ls) {
+  return (ls >> (N_MUTEXES - LOCKSET_INTERSECTION_SIZE))
+      & ((1 << LOCKSET_INTERSECTION_SIZE) - 1);
+}
+
+void Worker() {
+  for (int ls = 0; ls < (1 << N_MUTEXES); ls++) {
+    if (LS_to_idx(ls) == 0)
+      continue;
+    for (int m = 0; m < N_MUTEXES; m++)
+      if (ls & (1 << m))
+        MU[m].Lock();
+
+    data[LS_to_idx(ls)]++;
+
+    for (int m = N_MUTEXES - 1; m >= 0; m--)
+      if (ls & (1 << m))
+        MU[m].Unlock();
+  }
+}
+
+void Run() {
+  printf("test103: Access different memory locations with different LockSets\n");
+  MyThreadArray t(Worker, Worker, Worker, Worker);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST2(Run, 103, FEATURE)
+}  // namespace test103
+
+// test104: TP. Simple race (write vs write). Heap mem. {{{1
+namespace test104 {
+int     *GLOB = NULL;
+void Worker() {
+  *GLOB = 1; 
+}
+
+void Parent() {
+  MyThread t(Worker);
+  t.Start();
+  usleep(100000);
+  *GLOB = 2;
+  t.Join();
+}
+void Run() {
+  GLOB = (int*)memalign(64, sizeof(int));
+  *GLOB = 0;
+  ANNOTATE_EXPECT_RACE(GLOB, "test104. TP.");
+  ANNOTATE_TRACE_MEMORY(GLOB);
+  printf("test104: positive\n");
+  Parent();
+  printf("\tGLOB=%d\n", *GLOB);
+  free(GLOB);
+}
+REGISTER_TEST(Run, 104);
+}  // namespace test104
+
+
+// test105: Checks how stack grows. {{{1
+namespace test105 {
+int     GLOB = 0;
+
+void F1() {
+  int ar[32];
+//  ANNOTATE_TRACE_MEMORY(&ar[0]);
+//  ANNOTATE_TRACE_MEMORY(&ar[31]);
+  ar[0] = 1;
+  ar[31] = 1;
+}
+
+void Worker() {
+  int ar[32];
+//  ANNOTATE_TRACE_MEMORY(&ar[0]);
+//  ANNOTATE_TRACE_MEMORY(&ar[31]);
+  ar[0] = 1;
+  ar[31] = 1;
+  F1();
+}
+
+void Run() {
+  printf("test105: negative\n");
+  Worker();
+  MyThread t(Worker);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 105)
+}  // namespace test105
+
+
+// test106: TN. pthread_once. {{{1
+namespace test106 {
+int     *GLOB = NULL;
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+void Init() {
+  GLOB = new int;
+  ANNOTATE_TRACE_MEMORY(GLOB);
+  *GLOB = 777;
+}
+
+void Worker0() {
+  pthread_once(&once, Init);
+}
+void Worker1() {
+  usleep(100000);
+  pthread_once(&once, Init);
+  CHECK(*GLOB == 777);
+}
+
+
+void Run() {
+  printf("test106: negative\n");
+  MyThreadArray t(Worker0, Worker1, Worker1, Worker1);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", *GLOB);
+}
+REGISTER_TEST2(Run, 106, FEATURE)
+}  // namespace test106
+
+
+// test107: Test for ANNOTATE_EXPECT_RACE {{{1
+namespace test107 {
+int     GLOB = 0;
+void Run() {
+  printf("test107: negative\n");
+  ANNOTATE_EXPECT_RACE(&GLOB, "No race in fact. Just checking the tool."); 
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 107, FEATURE|EXCLUDE_FROM_ALL)
+}  // namespace test107
+
+
+// test108: TN. initialization of static object. {{{1
+namespace test108 {
+// Here we have a function-level static object. 
+// Starting from gcc 4 this is therad safe, 
+// but is is not thread safe with many other compilers.
+//
+// Helgrind supports this kind of initialization by 
+// intercepting __cxa_guard_acquire/__cxa_guard_release 
+// and ignoring all accesses between them. 
+// Helgrind also intercepts pthread_once in the same manner. 
+class Foo {
+ public:
+  Foo() {
+    ANNOTATE_TRACE_MEMORY(&a_);
+    a_ = 42;
+  }
+  void Check() const { CHECK(a_ == 42); }
+ private:
+  int a_;
+};
+
+const Foo *GetFoo() {
+  static const Foo *foo = new Foo();
+  return foo;
+}
+void Worker0() {
+  GetFoo();
+}
+
+void Worker() {
+  usleep(200000);
+  const Foo *foo = GetFoo();
+  foo->Check();
+}
+
+
+void Run() {
+  printf("test108: negative, initialization of static object\n");
+  MyThreadArray t(Worker0, Worker, Worker);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST2(Run, 108, FEATURE)
+}  // namespace test108
+
+
+// test109: TN. Checking happens before between parent and child threads. {{{1
+namespace test109 {
+// Check that the detector correctly connects 
+//   pthread_create with the new thread
+// and 
+//   thread exit with pthread_join
+const int N = 32;
+static int GLOB[N];
+
+void Worker(void *a) {
+  usleep(10000);
+//  printf("--Worker : %ld %p\n", (int*)a - GLOB, (void*)pthread_self());
+  int *arg = (int*)a;
+  (*arg)++;
+}
+
+void Run() {
+  printf("test109: negative\n");
+  MyThread *t[N];
+  for (int i  = 0; i < N; i++) {
+    t[i] = new MyThread(Worker, &GLOB[i]);
+  }
+  for (int i  = 0; i < N; i++) {
+    ANNOTATE_TRACE_MEMORY(&GLOB[i]);
+    GLOB[i] = 1;
+    t[i]->Start();
+//    printf("--Started: %p\n", (void*)t[i]->tid());
+  }
+  for (int i  = 0; i < N; i++) {
+//    printf("--Joining: %p\n", (void*)t[i]->tid());
+    t[i]->Join();
+//    printf("--Joined : %p\n", (void*)t[i]->tid());
+    GLOB[i]++;
+  }
+  for (int i  = 0; i < N; i++) delete t[i];
+
+  printf("\tGLOB=%d\n", GLOB[13]);
+}
+REGISTER_TEST(Run, 109)
+}  // namespace test109
+
+
+// test110: TP. Simple races with stack, global and heap objects. {{{1
+namespace test110 {
+int        GLOB = 0;
+static int STATIC;
+
+int       *STACK = 0;
+
+int       *MALLOC;
+int       *CALLOC;
+int       *REALLOC;
+int       *VALLOC;
+int       *PVALLOC;
+int       *MEMALIGN;
+union pi_pv_union { int* pi; void* pv; } POSIX_MEMALIGN;
+int       *MMAP;
+
+int       *NEW;
+int       *NEW_ARR;
+
+void Worker() {
+  GLOB++;
+  STATIC++;
+
+  (*STACK)++;
+
+  (*MALLOC)++;
+  (*CALLOC)++;
+  (*REALLOC)++;
+  (*VALLOC)++;
+  (*PVALLOC)++;
+  (*MEMALIGN)++;
+  (*(POSIX_MEMALIGN.pi))++;
+  (*MMAP)++;
+
+  (*NEW)++;
+  (*NEW_ARR)++;
+}
+void Run() {
+  int x = 0;
+  STACK = &x;
+
+  MALLOC = (int*)malloc(sizeof(int));
+  CALLOC = (int*)calloc(1, sizeof(int));
+  REALLOC = (int*)realloc(NULL, sizeof(int));
+  VALLOC = (int*)valloc(sizeof(int));
+  PVALLOC = (int*)valloc(sizeof(int));  // TODO: pvalloc breaks helgrind.
+  MEMALIGN = (int*)memalign(64, sizeof(int));
+  CHECK(0 == posix_memalign(&POSIX_MEMALIGN.pv, 64, sizeof(int)));
+  MMAP = (int*)mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,
+                    MAP_PRIVATE | MAP_ANON, -1, 0);
+
+  NEW     = new int;
+  NEW_ARR = new int[10];
+
+
+  FAST_MODE_INIT(STACK);
+  ANNOTATE_EXPECT_RACE(STACK, "real race on stack object");
+  FAST_MODE_INIT(&GLOB);
+  ANNOTATE_EXPECT_RACE(&GLOB, "real race on global object");
+  FAST_MODE_INIT(&STATIC);
+  ANNOTATE_EXPECT_RACE(&STATIC, "real race on a static global object");
+  FAST_MODE_INIT(MALLOC);
+  ANNOTATE_EXPECT_RACE(MALLOC, "real race on a malloc-ed object");
+  FAST_MODE_INIT(CALLOC);
+  ANNOTATE_EXPECT_RACE(CALLOC, "real race on a calloc-ed object");
+  FAST_MODE_INIT(REALLOC);
+  ANNOTATE_EXPECT_RACE(REALLOC, "real race on a realloc-ed object");
+  FAST_MODE_INIT(VALLOC);
+  ANNOTATE_EXPECT_RACE(VALLOC, "real race on a valloc-ed object");
+  FAST_MODE_INIT(PVALLOC);
+  ANNOTATE_EXPECT_RACE(PVALLOC, "real race on a pvalloc-ed object");
+  FAST_MODE_INIT(MEMALIGN);
+  ANNOTATE_EXPECT_RACE(MEMALIGN, "real race on a memalign-ed object");
+  FAST_MODE_INIT(POSIX_MEMALIGN.pi);
+  ANNOTATE_EXPECT_RACE(POSIX_MEMALIGN.pi, "real race on a posix_memalign-ed object");
+  FAST_MODE_INIT(MMAP);
+  ANNOTATE_EXPECT_RACE(MMAP, "real race on a mmap-ed object");
+
+  FAST_MODE_INIT(NEW);
+  ANNOTATE_EXPECT_RACE(NEW, "real race on a new-ed object");
+  FAST_MODE_INIT(NEW_ARR);
+  ANNOTATE_EXPECT_RACE(NEW_ARR, "real race on a new[]-ed object");
+
+  MyThreadArray t(Worker, Worker, Worker);
+  t.Start();
+  t.Join();
+  printf("test110: positive (race on a stack object)\n");
+  printf("\tSTACK=%d\n", *STACK);
+  CHECK(GLOB <= 3);
+  CHECK(STATIC <= 3);
+
+  free(MALLOC);
+  free(CALLOC);
+  free(REALLOC);
+  free(VALLOC);
+  free(PVALLOC);
+  free(MEMALIGN);
+  free(POSIX_MEMALIGN.pv);
+  munmap(MMAP, sizeof(int));
+  delete NEW;
+  delete [] NEW_ARR;
+}
+REGISTER_TEST(Run, 110)
+}  // namespace test110
+
+
+// test111: TN. Unit test for a bug related to stack handling. {{{1
+namespace test111 {
+char     *GLOB = 0;
+bool COND = false;
+Mutex mu;
+const int N = 3000;
+
+void write_to_p(char *p, int val) {
+  for (int i = 0; i < N; i++) 
+    p[i] = val;
+}
+
+static bool ArgIsTrue(bool *arg) {
+//  printf("ArgIsTrue: %d tid=%d\n", *arg, (int)pthread_self());
+  return *arg == true; 
+}
+
+void f1() {
+  char some_stack[N];
+  write_to_p(some_stack, 1);
+  mu.LockWhen(Condition(&ArgIsTrue, &COND));
+  mu.Unlock();
+}
+
+void f2() {
+  char some_stack[N];
+  char some_more_stack[N];
+  write_to_p(some_stack, 2);
+  write_to_p(some_more_stack, 2);
+}
+
+void f0() { f2(); }
+
+void Worker1() {
+  f0();
+  f1();
+  f2();
+}
+
+void Worker2() {
+  usleep(100000);
+  mu.Lock();
+  COND = true;
+  mu.Unlock();
+}
+
+void Run() {
+  printf("test111: regression test\n");
+  MyThreadArray t(Worker1, Worker1, Worker2);
+//  AnnotateSetVerbosity(__FILE__, __LINE__, 3);
+  t.Start();
+  t.Join();
+//  AnnotateSetVerbosity(__FILE__, __LINE__, 1);
+}
+REGISTER_TEST2(Run, 111, FEATURE)
+}  // namespace test111
+
+// test112: STAB. Test for ANNOTATE_PUBLISH_MEMORY_RANGE{{{1
+namespace test112 {
+char     *GLOB = 0;
+const int N = 64 * 5;
+Mutex mu;
+bool ready = false; // under mu
+int beg, end; // under mu
+
+Mutex mu1;
+
+void Worker() {
+
+  bool is_ready = false;
+  int b, e;
+  while (!is_ready) {
+    mu.Lock();
+    is_ready = ready;
+    b = beg;
+    e = end;
+    mu.Unlock();
+    usleep(1000);
+  }
+
+  mu1.Lock();
+  for (int i = b; i < e; i++) {
+    GLOB[i]++;
+  }
+  mu1.Unlock();
+}
+
+void PublishRange(int b, int e) {
+  MyThreadArray t(Worker, Worker);
+  ready = false; // runs before other threads
+  t.Start();
+
+  ANNOTATE_NEW_MEMORY(GLOB + b, e - b);
+  ANNOTATE_TRACE_MEMORY(GLOB + b);
+  for (int j = b; j < e; j++) {
+    GLOB[j] = 0; 
+  }
+  ANNOTATE_PUBLISH_MEMORY_RANGE(GLOB + b, e - b);
+
+  // hand off 
+  mu.Lock();
+  ready = true;
+  beg = b;
+  end = e;
+  mu.Unlock();
+
+  t.Join();
+}
+
+void Run() {
+  printf("test112: stability (ANNOTATE_PUBLISH_MEMORY_RANGE)\n");
+  GLOB = new char [N];
+  
+  PublishRange(0, 10);
+  PublishRange(3, 5);
+
+  PublishRange(12, 13);
+  PublishRange(10, 14);
+
+  PublishRange(15, 17);
+  PublishRange(16, 18);
+
+  // do few more random publishes.
+  for (int i = 0; i < 20; i++) {
+    const int begin = rand() % N;
+    const int size = (rand() % (N - begin)) + 1;
+    CHECK(size > 0);
+    CHECK(begin + size <= N);
+    PublishRange(begin, begin + size);
+  }
+
+  printf("GLOB = %d\n", (int)GLOB[0]);
+}
+REGISTER_TEST2(Run, 112, STABILITY)
+}  // namespace test112
+
+
+// test113: PERF. A lot of lock/unlock calls. Many locks {{{1
+namespace    test113 {
+const int kNumIter = 100000;
+const int kNumLocks = 7;
+Mutex   MU[kNumLocks]; 
+void Run() {
+  printf("test113: perf\n");
+  for (int i = 0; i < kNumIter; i++ ) {
+    for (int j = 0; j < kNumLocks; j++) {
+      if (i & (1 << j)) MU[j].Lock();
+    }
+    for (int j = kNumLocks - 1; j >= 0; j--) {
+      if (i & (1 << j)) MU[j].Unlock();
+    }
+  }
+}
+REGISTER_TEST(Run, 113)
+}  // namespace test113
+
+
+// test114: STAB. Recursive lock. {{{1
+namespace    test114 {
+int Bar() {
+  static int bar = 1;
+  return bar;
+}
+int Foo() {
+  static int foo = Bar();
+  return foo;
+}
+void Worker() {
+  static int x = Foo();
+  CHECK(x == 1);
+}
+void Run() {
+  printf("test114: stab\n");
+  MyThreadArray t(Worker, Worker);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST(Run, 114)
+}  // namespace test114
+
+
+// test115: TN. sem_open. {{{1
+namespace    test115 {
+int tid = 0;
+Mutex mu;
+const char *kSemName = "drt-test-sem";
+
+int GLOB = 0;
+
+sem_t *DoSemOpen() {
+  // TODO: there is some race report inside sem_open 
+  // for which suppressions do not work... (???)
+  ANNOTATE_IGNORE_WRITES_BEGIN();
+  sem_t *sem = sem_open(kSemName, O_CREAT, 0600, 3); 
+  ANNOTATE_IGNORE_WRITES_END();
+  return sem;
+}
+
+void Worker() {
+  mu.Lock();
+  int my_tid = tid++;
+  mu.Unlock();
+
+  if (my_tid == 0) {
+    GLOB = 1;
+  }
+
+  // if the detector observes a happens-before arc between 
+  // sem_open and sem_wait, it will be silent.
+  sem_t *sem = DoSemOpen(); 
+  usleep(100000);
+  CHECK(sem != SEM_FAILED);
+  CHECK(sem_wait(sem) == 0);
+
+  if (my_tid > 0) {
+    CHECK(GLOB == 1);
+  }
+}
+
+void Run() {
+  printf("test115: stab (sem_open())\n");
+
+  // just check that sem_open is not completely broken
+  sem_unlink(kSemName);
+  sem_t* sem = DoSemOpen();
+  CHECK(sem != SEM_FAILED);
+  CHECK(sem_wait(sem) == 0);
+  sem_unlink(kSemName);
+
+  // check that sem_open and sem_wait create a happens-before arc.
+  MyThreadArray t(Worker, Worker, Worker);
+  t.Start();
+  t.Join();
+  // clean up
+  sem_unlink(kSemName);
+}
+REGISTER_TEST(Run, 115)
+}  // namespace test115
+
+
+// test116: TN. some operations with string<> objects. {{{1
+namespace test116 {
+
+void Worker() {
+  string A[10], B[10], C[10];
+  for (int i = 0; i < 1000; i++) {
+    for (int j = 0; j < 10; j++) {
+      string &a = A[j];
+      string &b = B[j];
+      string &c = C[j];
+      a = "sdl;fkjhasdflksj df";
+      b = "sdf sdf;ljsd ";
+      c = "'sfdf df";
+      c = b;
+      a = c;
+      b = a;
+      swap(a,b);
+      swap(b,c);
+    }
+    for (int j = 0; j < 10; j++) {
+      string &a = A[j];
+      string &b = B[j];
+      string &c = C[j];
+      a.clear();
+      b.clear();
+      c.clear();
+    }
+  }
+}
+
+void Run() {
+  printf("test116: negative (strings)\n");
+  MyThreadArray t(Worker, Worker, Worker);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST2(Run, 116, FEATURE|EXCLUDE_FROM_ALL)
+}  // namespace test116
+
+// test117: TN. Many calls to function-scope static init. {{{1
+namespace test117 {
+const int N = 50;
+
+int Foo() {
+  usleep(20000);
+  return 1;
+}
+
+void Worker(void *a) {
+  static int foo = Foo();
+  CHECK(foo == 1);
+}
+
+void Run() {
+  printf("test117: negative\n");
+  MyThread *t[N];
+  for (int i  = 0; i < N; i++) {
+    t[i] = new MyThread(Worker);
+  }
+  for (int i  = 0; i < N; i++) {
+    t[i]->Start();
+  }
+  for (int i  = 0; i < N; i++) {
+    t[i]->Join();
+  }
+  for (int i  = 0; i < N; i++) delete t[i];
+}
+REGISTER_TEST(Run, 117)
+}  // namespace test117
+
+
+
+// test118 PERF: One signal, multiple waits. {{{1
+namespace   test118 {
+int     GLOB = 0;
+const int kNumIter = 2000000;
+void Signaller() {
+  usleep(50000);
+  ANNOTATE_CONDVAR_SIGNAL(&GLOB);
+}
+void Waiter() {
+  for (int i = 0; i < kNumIter; i++) {
+    ANNOTATE_CONDVAR_WAIT(&GLOB);
+    if (i == kNumIter / 2) 
+      usleep(100000);
+  }
+}
+void Run() {
+  printf("test118: perf\n");
+  MyThreadArray t(Signaller, Waiter, Signaller, Waiter);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 118)
+}  // namespace test118
+
+
+// test119: TP. Testing that malloc does not introduce any HB arc. {{{1
+namespace test119 {
+int     GLOB = 0;
+void Worker1() {
+  GLOB = 1;
+  free(malloc(123));
+}
+void Worker2() {
+  usleep(100000);
+  free(malloc(345));
+  GLOB = 2;
+}
+void Run() {
+  printf("test119: positive (checking if malloc creates HB arcs)\n");
+  FAST_MODE_INIT(&GLOB);
+  if (!(Tsan_PureHappensBefore() && kMallocUsesMutex))
+    ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "true race");
+  MyThreadArray t(Worker1, Worker2);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 119)
+}  // namespace test119
+
+
+// test120: TP. Thread1: write then read. Thread2: read. {{{1
+namespace test120 {
+int     GLOB = 0;
+
+void Thread1() {
+  GLOB = 1;           // write
+  CHECK(GLOB);        // read
+}
+
+void Thread2() {
+  usleep(100000);
+  CHECK(GLOB >= 0);   // read
+}
+
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "TP (T1: write then read, T2: read)");
+  printf("test120: positive\n");
+  MyThreadArray t(Thread1, Thread2);
+  GLOB = 1;
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 120)
+}  // namespace test120
+
+
+// test121: TP. Example of double-checked-locking  {{{1
+namespace test121 {
+struct Foo {
+  uintptr_t a, b[15];
+} __attribute__ ((aligned (64)));
+
+static Mutex mu;
+static Foo  *foo;
+
+void InitMe() {
+  if (!foo) {
+    MutexLock lock(&mu);
+    if (!foo) {
+      ANNOTATE_EXPECT_RACE_FOR_TSAN(&foo, "test121. Double-checked locking (ptr)");
+      foo = new Foo;
+      if (!Tsan_FastMode())
+        ANNOTATE_EXPECT_RACE_FOR_TSAN(&foo->a, "test121. Double-checked locking (obj)");
+      foo->a = 42;
+    }
+  }
+}
+
+void UseMe() { 
+  InitMe();
+  CHECK(foo && foo->a == 42); 
+}
+
+void Worker1() { UseMe(); }
+void Worker2() { UseMe(); }
+void Worker3() { UseMe(); }
+
+
+void Run() {  
+  FAST_MODE_INIT(&foo);
+  printf("test121: TP. Example of double-checked-locking\n");
+  MyThreadArray t1(Worker1, Worker2, Worker3);
+  t1.Start();  
+  t1.Join();
+  delete foo;
+}
+REGISTER_TEST(Run, 121)
+}  // namespace test121
+
+// test122 TP: Simple test with RWLock {{{1
+namespace  test122 {
+int     VAR1 = 0;
+int     VAR2 = 0;
+RWLock mu;
+
+void WriteWhileHoldingReaderLock(int *p) {
+  usleep(100000);
+  ReaderLockScoped lock(&mu);  // Reader lock for writing. -- bug.
+  (*p)++;
+}
+
+void CorrectWrite(int *p) {
+  WriterLockScoped lock(&mu);
+  (*p)++;
+}
+
+void Thread1() { WriteWhileHoldingReaderLock(&VAR1); } 
+void Thread2() { CorrectWrite(&VAR1); }
+void Thread3() { CorrectWrite(&VAR2); }
+void Thread4() { WriteWhileHoldingReaderLock(&VAR2); } 
+
+
+void Run() {
+  printf("test122: positive (rw-lock)\n");
+  VAR1 = 0;
+  VAR2 = 0;
+  ANNOTATE_TRACE_MEMORY(&VAR1);
+  ANNOTATE_TRACE_MEMORY(&VAR2);
+  if (!Tsan_PureHappensBefore()) {
+    ANNOTATE_EXPECT_RACE_FOR_TSAN(&VAR1, "test122. TP. ReaderLock-ed while writing");
+    ANNOTATE_EXPECT_RACE_FOR_TSAN(&VAR2, "test122. TP. ReaderLock-ed while writing");
+  }
+  MyThreadArray t(Thread1, Thread2, Thread3, Thread4);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST(Run, 122)
+}  // namespace test122
+
+
+// test123 TP: accesses of different sizes. {{{1
+namespace test123 {
+
+union uint_union {
+  uint64_t u64[1];
+  uint32_t u32[2];
+  uint16_t u16[4];
+  uint8_t  u8[8];
+};
+
+uint_union MEM[8];
+
+// Q. Hey dude, why so many functions? 
+// A. I need different stack traces for different accesses.
+
+void Wr64_0() { MEM[0].u64[0] = 1; } 
+void Wr64_1() { MEM[1].u64[0] = 1; } 
+void Wr64_2() { MEM[2].u64[0] = 1; } 
+void Wr64_3() { MEM[3].u64[0] = 1; } 
+void Wr64_4() { MEM[4].u64[0] = 1; } 
+void Wr64_5() { MEM[5].u64[0] = 1; } 
+void Wr64_6() { MEM[6].u64[0] = 1; } 
+void Wr64_7() { MEM[7].u64[0] = 1; } 
+
+void Wr32_0() { MEM[0].u32[0] = 1; } 
+void Wr32_1() { MEM[1].u32[1] = 1; } 
+void Wr32_2() { MEM[2].u32[0] = 1; } 
+void Wr32_3() { MEM[3].u32[1] = 1; } 
+void Wr32_4() { MEM[4].u32[0] = 1; } 
+void Wr32_5() { MEM[5].u32[1] = 1; } 
+void Wr32_6() { MEM[6].u32[0] = 1; } 
+void Wr32_7() { MEM[7].u32[1] = 1; } 
+
+void Wr16_0() { MEM[0].u16[0] = 1; } 
+void Wr16_1() { MEM[1].u16[1] = 1; } 
+void Wr16_2() { MEM[2].u16[2] = 1; } 
+void Wr16_3() { MEM[3].u16[3] = 1; } 
+void Wr16_4() { MEM[4].u16[0] = 1; } 
+void Wr16_5() { MEM[5].u16[1] = 1; } 
+void Wr16_6() { MEM[6].u16[2] = 1; } 
+void Wr16_7() { MEM[7].u16[3] = 1; } 
+
+void Wr8_0() { MEM[0].u8[0] = 1; } 
+void Wr8_1() { MEM[1].u8[1] = 1; } 
+void Wr8_2() { MEM[2].u8[2] = 1; } 
+void Wr8_3() { MEM[3].u8[3] = 1; } 
+void Wr8_4() { MEM[4].u8[4] = 1; } 
+void Wr8_5() { MEM[5].u8[5] = 1; } 
+void Wr8_6() { MEM[6].u8[6] = 1; } 
+void Wr8_7() { MEM[7].u8[7] = 1; } 
+
+void WriteAll64() {
+  Wr64_0();
+  Wr64_1();
+  Wr64_2();
+  Wr64_3();
+  Wr64_4();
+  Wr64_5();
+  Wr64_6();
+  Wr64_7();
+}
+
+void WriteAll32() {
+  Wr32_0();
+  Wr32_1();
+  Wr32_2();
+  Wr32_3();
+  Wr32_4();
+  Wr32_5();
+  Wr32_6();
+  Wr32_7();
+}
+
+void WriteAll16() {
+  Wr16_0();
+  Wr16_1();
+  Wr16_2();
+  Wr16_3();
+  Wr16_4();
+  Wr16_5();
+  Wr16_6();
+  Wr16_7();
+}
+
+void WriteAll8() {
+  Wr8_0();
+  Wr8_1();
+  Wr8_2();
+  Wr8_3();
+  Wr8_4();
+  Wr8_5();
+  Wr8_6();
+  Wr8_7();
+}
+
+void W00() { WriteAll64(); } 
+void W01() { WriteAll64(); } 
+void W02() { WriteAll64(); } 
+
+void W10() { WriteAll32(); } 
+void W11() { WriteAll32(); } 
+void W12() { WriteAll32(); } 
+
+void W20() { WriteAll16(); } 
+void W21() { WriteAll16(); } 
+void W22() { WriteAll16(); } 
+
+void W30() { WriteAll8(); } 
+void W31() { WriteAll8(); } 
+void W32() { WriteAll8(); } 
+
+typedef void (*F)(void);
+
+void TestTwoSizes(F f1, F f2) {
+  // first f1, then f2
+  ANNOTATE_NEW_MEMORY(&MEM, sizeof(MEM));
+  memset(&MEM, 0, sizeof(MEM));
+  MyThreadArray t1(f1, f2);
+  t1.Start();
+  t1.Join();
+  // reverse order
+  ANNOTATE_NEW_MEMORY(&MEM, sizeof(MEM));
+  memset(&MEM, 0, sizeof(MEM));
+  MyThreadArray t2(f2, f1);
+  t2.Start();
+  t2.Join();
+}
+
+void Run() {
+  printf("test123: positive (different sizes)\n");
+  TestTwoSizes(W00, W10);
+//  TestTwoSizes(W01, W20);
+//  TestTwoSizes(W02, W30);
+//  TestTwoSizes(W11, W21);
+//  TestTwoSizes(W12, W31);
+//  TestTwoSizes(W22, W32);
+
+}
+REGISTER_TEST2(Run, 123, FEATURE|EXCLUDE_FROM_ALL)
+}  // namespace test123
+
+
+// test124: What happens if we delete an unlocked lock? {{{1
+namespace test124 {
+// This test does not worg with pthreads (you can't call 
+// pthread_mutex_destroy on a locked lock).
+int     GLOB = 0;
+const int N = 1000;
+void Worker() {
+  Mutex *a_large_local_array_of_mutexes;
+  a_large_local_array_of_mutexes = new Mutex[N];
+  for (int i = 0; i < N; i++) {
+    a_large_local_array_of_mutexes[i].Lock();
+  }
+  delete []a_large_local_array_of_mutexes;
+  GLOB = 1; 
+}
+
+void Run() {
+  printf("test124: negative\n");
+  MyThreadArray t(Worker, Worker, Worker);
+  t.Start();
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 124, FEATURE|EXCLUDE_FROM_ALL)
+}  // namespace test124
+
+
+// test125 TN: Backwards lock (annotated). {{{1
+namespace test125 {
+// This test uses "Backwards mutex" locking protocol. 
+// We take a *reader* lock when writing to a per-thread data 
+// (GLOB[thread_num])  and we take a *writer* lock when we 
+// are reading from the entire array at once.
+//
+// Such locking protocol is not understood by ThreadSanitizer's 
+// hybrid state machine. So, you either have to use a pure-happens-before 
+// detector ("tsan --pure-happens-before") or apply pure happens-before mode 
+// to this particular lock by using ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&mu).
+
+const int n_threads = 3;
+RWLock   mu;
+int     GLOB[n_threads];
+
+int adder_num; // updated atomically.
+
+void Adder() {
+  int my_num = AtomicIncrement(&adder_num, 1);
+
+  ReaderLockScoped lock(&mu);
+  GLOB[my_num]++;
+}
+
+void Aggregator() {
+  int sum = 0;
+  {
+    WriterLockScoped lock(&mu);
+    for (int i = 0; i < n_threads; i++) {
+      sum += GLOB[i];
+    }
+  }
+  printf("sum=%d\n", sum);
+}
+
+void Run() {
+  printf("test125: negative\n");
+
+  ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&mu);
+
+  // run Adders, then Aggregator
+  {
+    MyThreadArray t(Adder, Adder, Adder, Aggregator);
+    t.Start();
+    t.Join();
+  }
+
+  // Run Aggregator first.
+  adder_num = 0;
+  {
+    MyThreadArray t(Aggregator, Adder, Adder, Adder);
+    t.Start();
+    t.Join();
+  }
+
+}
+REGISTER_TEST(Run, 125)
+}  // namespace test125
+
+// test126 TN: test for BlockingCounter {{{1
+namespace  test126 {
+BlockingCounter *blocking_counter;
+int     GLOB = 0;
+void Worker() {
+  CHECK(blocking_counter);
+  CHECK(GLOB == 0);
+  blocking_counter->DecrementCount();
+}
+void Run() {
+  printf("test126: negative\n");
+  MyThreadArray t(Worker, Worker, Worker);
+  blocking_counter = new BlockingCounter(3);
+  t.Start();
+  blocking_counter->Wait();
+  GLOB = 1;
+  t.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST(Run, 126)
+}  // namespace test126
+
+
+// test127. Bad code: unlocking a mutex locked by another thread. {{{1
+namespace test127 {
+Mutex mu;
+void Thread1() {
+  mu.Lock();
+}
+void Thread2() {
+  usleep(100000);
+  mu.Unlock();
+}
+void Run() {
+  printf("test127: unlocking a mutex locked by another thread.\n");
+  MyThreadArray t(Thread1, Thread2);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST(Run, 127)
+}  // namespace test127
+
+// test128. Suppressed code in concurrent accesses {{{1
+// Please use --suppressions=unittest.supp flag when running this test.
+namespace test128 {
+Mutex mu;
+int GLOB = 0;
+void Worker() {
+  usleep(100000);
+  mu.Lock();
+  GLOB++;
+  mu.Unlock();
+}
+void ThisFunctionShouldBeSuppressed() {
+  GLOB++;
+}
+void Run() {
+  printf("test128: Suppressed code in concurrent accesses.\n");
+  MyThreadArray t(Worker, ThisFunctionShouldBeSuppressed);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST2(Run, 128, FEATURE | EXCLUDE_FROM_ALL)
+}  // namespace test128
+
+// test129: TN. Synchronization via ReaderLockWhen(). {{{1
+namespace test129 {  
+int     GLOB = 0;
+Mutex   MU; 
+bool WeirdCondition(int* param) {
+  *param = GLOB;  // a write into Waiter's memory
+  return GLOB > 0;
+}
+void Waiter() {
+  int param = 0;
+  MU.ReaderLockWhen(Condition(WeirdCondition, &param));
+  MU.ReaderUnlock();
+  CHECK(GLOB > 0);
+  CHECK(param > 0);
+}
+void Waker() {
+  usleep(100000);  // Make sure the waiter blocks.
+  MU.Lock();
+  GLOB++;
+  MU.Unlock();     // calls ANNOTATE_CONDVAR_SIGNAL;
+}
+void Run() {
+  printf("test129: Synchronization via ReaderLockWhen()\n");
+  MyThread mt(Waiter, NULL, "Waiter Thread");
+  mt.Start();
+  Waker();
+  mt.Join();
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 129, FEATURE);
+}  // namespace test129
+
+// test130: TN. Per-thread. {{{1
+namespace test130 {
+#ifndef NO_TLS
+// This test verifies that the race detector handles 
+// thread-local storage (TLS) correctly.
+// As of 09-03-30 ThreadSanitizer has a bug: 
+//   - Thread1 starts
+//   - Thread1 touches per_thread_global
+//   - Thread1 ends
+//   - Thread2 starts (and there is no happens-before relation between it and
+//   Thread1)
+//   - Thread2 touches per_thread_global
+// It may happen so that Thread2 will have per_thread_global in the same address
+// as Thread1. Since there is no happens-before relation between threads, 
+// ThreadSanitizer reports a race.
+//
+// test131 does the same for stack.
+
+static __thread int per_thread_global[10] = {0};
+
+void RealWorker() {  // Touch per_thread_global.
+  per_thread_global[1]++;
+  errno++;
+}
+
+void Worker() {  // Spawn few threads that touch per_thread_global.
+  MyThreadArray t(RealWorker, RealWorker);
+  t.Start();
+  t.Join();
+}
+void Worker0() { sleep(0); Worker(); }
+void Worker1() { sleep(1); Worker(); }
+void Worker2() { sleep(2); Worker(); }
+void Worker3() { sleep(3); Worker(); }
+
+void Run() {
+  printf("test130: Per-thread\n");
+  MyThreadArray t1(Worker0, Worker1, Worker2, Worker3);
+  t1.Start();
+  t1.Join();
+  printf("\tper_thread_global=%d\n", per_thread_global[1]);
+}
+REGISTER_TEST(Run, 130)
+#endif // NO_TLS
+}  // namespace test130
+
+
+// test131: TN. Stack. {{{1
+namespace test131 {
+// Same as test130, but for stack.
+
+void RealWorker() {  // Touch stack.
+  int stack_var = 0;
+  stack_var++;
+}
+
+void Worker() {  // Spawn few threads that touch stack.
+  MyThreadArray t(RealWorker, RealWorker);
+  t.Start();
+  t.Join();
+}
+void Worker0() { sleep(0); Worker(); }
+void Worker1() { sleep(1); Worker(); }
+void Worker2() { sleep(2); Worker(); }
+void Worker3() { sleep(3); Worker(); }
+
+void Run() {
+  printf("test131: stack\n");
+  MyThreadArray t(Worker0, Worker1, Worker2, Worker3);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST(Run, 131)
+}  // namespace test131
+
+
+// test132: TP. Simple race (write vs write). Works in fast-mode. {{{1
+namespace test132 {
+int     GLOB = 0;
+void Worker() { GLOB = 1; }
+
+void Run1() {
+  FAST_MODE_INIT(&GLOB);
+  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test132");
+  printf("test132: positive; &GLOB=%p\n", &GLOB);
+  ANNOTATE_TRACE_MEMORY(&GLOB);
+  GLOB = 7;
+  MyThreadArray t(Worker, Worker);
+  t.Start();
+  t.Join();
+}
+
+void Run() {
+  Run1();
+}
+REGISTER_TEST(Run, 132);
+}  // namespace test132
+
+
+// test133: TP. Simple race (write vs write). Works in fast mode. {{{1
+namespace test133 {
+// Same as test132, but everything is run from a separate thread spawned from
+// the main thread.
+int     GLOB = 0;
+void Worker() { GLOB = 1; }
+
+void Run1() {
+  FAST_MODE_INIT(&GLOB);
+  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test133");
+  printf("test133: positive; &GLOB=%p\n", &GLOB);
+  ANNOTATE_TRACE_MEMORY(&GLOB);
+  GLOB = 7;
+  MyThreadArray t(Worker, Worker);
+  t.Start();
+  t.Join();
+}
+void Run() {
+  MyThread t(Run1);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST(Run, 133);
+}  // namespace test133
+
+
+// test134 TN. Swap. Variant of test79. {{{1
+namespace test134 {
+#if 0
+typedef __gnu_cxx::hash_map<int, int> map_t;
+#else
+typedef std::map<int, int> map_t;
+#endif
+map_t   map;
+Mutex   mu;
+// Here we use swap to pass map between threads.
+// The synchronization is correct, but w/o the annotation
+// any hybrid detector will complain.
+
+// Swap is very unfriendly to the lock-set (and hybrid) race detectors.
+// Since tmp is destructed outside the mutex, we need to have a happens-before
+// arc between any prior access to map and here.
+// Since the internals of tmp are created ouside the mutex and are passed to
+// other thread, we need to have a h-b arc between here and any future access.
+// These arcs can be created by HAPPENS_{BEFORE,AFTER} annotations, but it is
+// much simpler to apply pure-happens-before mode to the mutex mu.
+void Swapper() {
+  map_t tmp;
+  MutexLock lock(&mu);
+  ANNOTATE_HAPPENS_AFTER(&map);
+  // We swap the new empty map 'tmp' with 'map'.
+  map.swap(tmp);
+  ANNOTATE_HAPPENS_BEFORE(&map);
+  // tmp (which is the old version of map) is destroyed here.
+}
+
+void Worker() {
+  MutexLock lock(&mu);
+  ANNOTATE_HAPPENS_AFTER(&map);
+  map[1]++;
+  ANNOTATE_HAPPENS_BEFORE(&map);
+}
+
+void Run() {
+  printf("test134: negative (swap)\n");
+  // ********************** Shorter way: ***********************
+  // ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&mu);
+  MyThreadArray t(Worker, Worker, Swapper, Worker, Worker);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST(Run, 134)
+}  // namespace test134
+
+// test135 TN. Swap. Variant of test79. {{{1
+namespace test135 {
+
+void SubWorker() {
+  const long SIZE = 65536;
+  for (int i = 0; i < 32; i++) {
+    int *ptr = (int*)mmap(NULL, SIZE, PROT_READ | PROT_WRITE,
+                          MAP_PRIVATE | MAP_ANON, -1, 0);
+    *ptr = 42;
+    munmap(ptr, SIZE);
+  }
+}
+
+void Worker() {
+  MyThreadArray t(SubWorker, SubWorker, SubWorker, SubWorker);
+  t.Start();
+  t.Join();
+}
+
+void Run() {
+  printf("test135: negative (mmap)\n");
+  MyThreadArray t(Worker, Worker, Worker, Worker);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST(Run, 135)
+}  // namespace test135
+
+// test136. Unlock twice. {{{1
+namespace test136 {
+void Run() {
+  printf("test136: unlock twice\n");
+  pthread_mutexattr_t attr;
+  CHECK(0 == pthread_mutexattr_init(&attr));
+  CHECK(0 == pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK));
+
+  pthread_mutex_t mu;
+  CHECK(0 == pthread_mutex_init(&mu, &attr));
+  CHECK(0 == pthread_mutex_lock(&mu));
+  CHECK(0 == pthread_mutex_unlock(&mu));
+  int ret_unlock = pthread_mutex_unlock(&mu);  // unlocking twice.
+  int ret_destroy = pthread_mutex_destroy(&mu);
+  printf("  pthread_mutex_unlock returned %d\n", ret_unlock);
+  printf("  pthread_mutex_destroy returned %d\n", ret_destroy);
+
+}
+
+REGISTER_TEST(Run, 136)
+}  // namespace test136
+
+// test137 TP. Races on stack variables. {{{1
+namespace test137 {
+int GLOB = 0;
+ProducerConsumerQueue q(10);
+
+void Worker() {
+  int stack;
+  int *tmp = (int*)q.Get();
+  (*tmp)++;
+  int *racey = &stack;
+  q.Put(racey);
+  (*racey)++;
+  usleep(150000);
+  // We may miss the races if we sleep less due to die_memory events...
+}
+
+void Run() {
+  int tmp = 0;
+  printf("test137: TP. Races on stack variables.\n");
+  q.Put(&tmp);
+  MyThreadArray t(Worker, Worker, Worker, Worker);
+  t.Start();
+  t.Join();
+  q.Get();
+}
+
+REGISTER_TEST2(Run, 137, FEATURE | EXCLUDE_FROM_ALL)
+}  // namespace test137
+
+// test138 FN. Two closures hit the same thread in ThreadPool. {{{1
+namespace test138 {
+int GLOB = 0;
+
+void Worker() {
+  usleep(100000);
+  GLOB++;
+}
+
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  printf("test138: FN. Two closures hit the same thread in ThreadPool.\n");
+
+  // When using thread pools, two concurrent callbacks might be scheduled
+  // onto the same executor thread. As a result, unnecessary happens-before
+  // relation may be introduced between callbacks.
+  // If we set the number of executor threads to 1, any known data
+  // race detector will be silent. However, the same situation may happen
+  // with any number of executor threads (with some probability).
+  ThreadPool tp(1);
+  tp.StartWorkers();
+  tp.Add(NewCallback(Worker));
+  tp.Add(NewCallback(Worker));
+}
+
+REGISTER_TEST2(Run, 138, FEATURE)
+}  // namespace test138
+
+// test139: FN. A true race hidden by reference counting annotation. {{{1
+namespace test139 {
+int GLOB = 0;
+RefCountedClass *obj;
+
+void Worker1() {
+  GLOB++;  // First access.
+  obj->Unref();
+}
+
+void Worker2() {
+  usleep(100000);
+  obj->Unref();
+  GLOB++;  // Second access.
+}
+
+void Run() {
+  FAST_MODE_INIT(&GLOB);
+  printf("test139: FN. A true race hidden by reference counting annotation.\n");
+
+  obj = new RefCountedClass;
+  obj->AnnotateUnref();
+  obj->Ref();
+  obj->Ref();
+  MyThreadArray mt(Worker1, Worker2);
+  mt.Start();
+  mt.Join();
+}
+
+REGISTER_TEST2(Run, 139, FEATURE)
+}  // namespace test139
+
+// test140 TN. Swap. Variant of test79 and test134. {{{1
+namespace test140 {
+#if 0
+typedef __gnu_cxx::hash_map<int, int> Container;
+#else
+typedef std::map<int,int>             Container;
+#endif
+Mutex mu;
+static Container container;
+
+// Here we use swap to pass a Container between threads.
+// The synchronization is correct, but w/o the annotation
+// any hybrid detector will complain.
+//
+// Unlike the test134, we try to have a minimal set of annotations 
+// so that extra h-b arcs do not hide other races.
+
+// Swap is very unfriendly to the lock-set (and hybrid) race detectors.
+// Since tmp is destructed outside the mutex, we need to have a happens-before
+// arc between any prior access to map and here.
+// Since the internals of tmp are created ouside the mutex and are passed to
+// other thread, we need to have a h-b arc between here and any future access.
+//
+// We want to be able to annotate swapper so that we don't need to annotate
+// anything else.
+void Swapper() {
+  Container tmp;
+  tmp[1] = tmp[2] = tmp[3] = 0;
+  {
+    MutexLock lock(&mu);
+    container.swap(tmp);
+    // we are unpublishing the old container.
+    ANNOTATE_UNPUBLISH_MEMORY_RANGE(&container, sizeof(container));
+    // we are publishing the new container.
+    ANNOTATE_PUBLISH_MEMORY_RANGE(&container, sizeof(container));
+  }
+  tmp[1]++;
+  tmp[2]++;
+  // tmp (which is the old version of container) is destroyed here.
+}
+
+void Worker() {
+  MutexLock lock(&mu);
+  container[1]++;
+  int *v = &container[2];
+  for (int i = 0; i < 10; i++) {
+    // if uncommented, this will break ANNOTATE_UNPUBLISH_MEMORY_RANGE():
+    // ANNOTATE_HAPPENS_BEFORE(v);
+    if (i % 3) {
+      (*v)++;
+    }
+  }
+}
+
+void Run() {
+  printf("test140: negative (swap) %p\n", &container);
+  MyThreadArray t(Worker, Worker, Swapper, Worker, Worker);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST(Run, 140)
+}  // namespace test140
+
+// test141 FP. unlink/fopen, rmdir/opendir. {{{1
+namespace test141 {
+int GLOB1 = 0,
+    GLOB2 = 0;
+char *dir_name = NULL,
+     *filename = NULL;
+
+void Waker1() {
+  usleep(100000);
+  GLOB1 = 1;  // Write
+  // unlink deletes a file 'filename'
+  // which exits spin-loop in Waiter1().
+  printf("  Deleting file...\n");
+  CHECK(unlink(filename) == 0);
+}
+
+void Waiter1() {
+  FILE *tmp;
+  while ((tmp = fopen(filename, "r")) != NULL) {
+    fclose(tmp);
+    usleep(10000);
+  }
+  printf("  ...file has been deleted\n");
+  GLOB1 = 2;  // Write
+}
+
+void Waker2() {
+  usleep(100000);
+  GLOB2 = 1;  // Write
+  // rmdir deletes a directory 'dir_name'
+  // which exit spin-loop in Waker().
+  printf("  Deleting directory...\n");
+  CHECK(rmdir(dir_name) == 0);
+}
+
+void Waiter2() {
+  DIR *tmp;
+  while ((tmp = opendir(dir_name)) != NULL) {
+    closedir(tmp);
+    usleep(10000);
+  }
+  printf("  ...directory has been deleted\n");
+  GLOB2 = 2;
+}
+
+void Run() {
+  FAST_MODE_INIT(&GLOB1);
+  FAST_MODE_INIT(&GLOB2);
+  printf("test141: FP. unlink/fopen, rmdir/opendir.\n");
+
+  dir_name = strdup("/tmp/tsan-XXXXXX");
+  IGNORE_RETURN_VALUE(mkdtemp(dir_name));
+
+  filename = strdup((std::string() + dir_name + "/XXXXXX").c_str());
+  const int fd = mkstemp(filename);
+  CHECK(fd >= 0);
+  close(fd);
+
+  MyThreadArray mta1(Waker1, Waiter1);
+  mta1.Start();
+  mta1.Join();
+
+  MyThreadArray mta2(Waker2, Waiter2);
+  mta2.Start();
+  mta2.Join();
+  free(filename);
+  filename = 0;
+  free(dir_name);
+  dir_name = 0;
+}
+REGISTER_TEST(Run, 141)
+}  // namespace test141
+
+
+// Simple FIFO queue annotated with PCQ annotations. {{{1
+class FifoMessageQueue {
+ public:
+  FifoMessageQueue() { ANNOTATE_PCQ_CREATE(this); }
+  ~FifoMessageQueue() { ANNOTATE_PCQ_DESTROY(this); }
+  // Send a message. 'message' should be positive.
+  void Put(int message) {
+    CHECK(message);
+    MutexLock lock(&mu_);
+    ANNOTATE_PCQ_PUT(this);
+    q_.push(message);
+  }
+  // Return the message from the queue and pop it 
+  // or return 0 if there are no messages.
+  int Get() {
+    MutexLock lock(&mu_);
+    if (q_.empty()) return 0;
+    int res = q_.front();
+    q_.pop();
+    ANNOTATE_PCQ_GET(this);
+    return res;
+  }
+ private:
+  Mutex mu_;
+  queue<int> q_;
+};
+
+
+// test142: TN. Check PCQ_* annotations. {{{1
+namespace test142 {
+// Putter writes to array[i] and sends a message 'i'.
+// Getters receive messages and read array[message].
+// PCQ_* annotations calm down the hybrid detectors.
+
+const int N = 1000;
+int array[N+1];
+
+FifoMessageQueue q;
+
+void Putter() {
+  for (int i = 1; i <= N; i++) {
+    array[i] = i*i;
+    q.Put(i);
+    usleep(1000);
+  }
+}
+
+void Getter() {
+  int non_zero_received  = 0;
+  for (int i = 1; i <= N; i++) {
+    int res = q.Get();
+    if (res > 0) {
+      CHECK(array[res] = res * res);
+      non_zero_received++;
+    }
+    usleep(1000);
+  }
+  printf("T=%zd: non_zero_received=%d\n", 
+         (size_t)pthread_self(), non_zero_received);
+} 
+
+void Run() {
+  printf("test142: tests PCQ annotations\n");
+  MyThreadArray t(Putter, Getter, Getter);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST(Run, 142)
+}  // namespace test142
+
+
+// test143: TP. Check PCQ_* annotations. {{{1
+namespace test143 {
+// True positive.
+// We have a race on GLOB between Putter and one of the Getters.
+// Pure h-b will not see it.
+// If FifoMessageQueue was annotated using HAPPENS_BEFORE/AFTER, the race would
+// be missed too.
+// PCQ_* annotations do not hide this race.
+int     GLOB = 0;
+
+FifoMessageQueue q;
+
+void Putter() {
+  GLOB = 1;
+  q.Put(1);
+}
+
+void Getter() {
+  usleep(10000);
+  q.Get();
+  CHECK(GLOB == 1);  // Race here
+}
+
+void Run() {
+  q.Put(1);
+  if (!Tsan_PureHappensBefore()) {
+    ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "true races");
+  }
+  printf("test143: tests PCQ annotations (true positive)\n");
+  MyThreadArray t(Putter, Getter, Getter);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST(Run, 143);
+}  // namespace test143
+
+
+
+
+// test300: {{{1
+namespace test300 {
+int     GLOB = 0;
+void Run() {
+}
+REGISTER_TEST2(Run, 300, RACE_DEMO)
+}  // namespace test300
+
+// test301: Simple race.  {{{1
+namespace test301 {
+Mutex mu1;  // This Mutex guards var.
+Mutex mu2;  // This Mutex is not related to var.
+int   var;  // GUARDED_BY(mu1)
+
+void Thread1() {  // Runs in thread named 'test-thread-1'.
+  MutexLock lock(&mu1);  // Correct Mutex.
+  var = 1; 
+}
+
+void Thread2() {  // Runs in thread named 'test-thread-2'.
+  MutexLock lock(&mu2);  // Wrong Mutex.
+  var = 2; 
+}
+
+void Run() {  
+  var = 0;
+  printf("test301: simple race.\n");
+  MyThread t1(Thread1, NULL, "test-thread-1");
+  MyThread t2(Thread2, NULL, "test-thread-2");
+  t1.Start();  
+  t2.Start();  
+  t1.Join();   
+  t2.Join();
+}
+REGISTER_TEST2(Run, 301, RACE_DEMO)
+}  // namespace test301
+
+// test302: Complex race which happens at least twice.  {{{1
+namespace test302 {
+// In this test we have many different accesses to GLOB and only one access 
+// is not synchronized properly. 
+int     GLOB = 0;
+
+Mutex MU1;
+Mutex MU2;
+void Worker() {
+  for(int i = 0; i < 100; i++) {
+    switch(i % 4) {
+      case 0:
+        // This read is protected correctly. 
+        MU1.Lock(); CHECK(GLOB >= 0); MU1.Unlock();
+        break;
+      case 1:
+        // Here we used the wrong lock! The reason of the race is here. 
+        MU2.Lock(); CHECK(GLOB >= 0); MU2.Unlock();
+        break;
+      case 2:
+        // This read is protected correctly. 
+        MU1.Lock(); CHECK(GLOB >= 0); MU1.Unlock();
+        break;
+      case 3:
+        // This write is protected correctly. 
+        MU1.Lock(); GLOB++; MU1.Unlock();
+        break;
+    }
+    // sleep a bit so that the threads interleave 
+    // and the race happens at least twice. 
+    usleep(100); 
+  }
+}
+
+void Run() {  
+  printf("test302: Complex race that happens twice.\n");
+  MyThread t1(Worker), t2(Worker);
+  t1.Start();  
+  t2.Start();  
+  t1.Join();   t2.Join();
+}
+REGISTER_TEST2(Run, 302, RACE_DEMO)
+}  // namespace test302
+
+
+// test303: Need to trace the memory to understand the report. {{{1
+namespace test303 {
+int     GLOB = 0;
+
+Mutex MU;
+void Worker1() { CHECK(GLOB >= 0); }
+void Worker2() { MU.Lock(); GLOB=1;  MU.Unlock();}
+
+void Run() {  
+  printf("test303: a race that needs annotations.\n");
+  ANNOTATE_TRACE_MEMORY(&GLOB);
+  MyThreadArray t(Worker1, Worker2);
+  t.Start();  
+  t.Join(); 
+}
+REGISTER_TEST2(Run, 303, RACE_DEMO)
+}  // namespace test303
+
+
+
+// test304: Can not trace the memory, since it is a library object. {{{1
+namespace test304 {
+string *STR;
+Mutex   MU; 
+
+void Worker1() {
+  sleep(0); 
+  ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
+  MU.Lock(); CHECK(STR->length() >= 4); MU.Unlock();
+}
+void Worker2() {
+  sleep(1);            
+  ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
+  CHECK(STR->length() >= 4); // Unprotected! 
+}
+void Worker3() {
+  sleep(2); 
+  ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
+  MU.Lock(); CHECK(STR->length() >= 4); MU.Unlock();
+}
+void Worker4() {
+  sleep(3); 
+  ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
+  MU.Lock(); *STR += " + a very very long string"; MU.Unlock();  
+}
+
+void Run() {  
+  STR = new string ("The String");
+  printf("test304: a race where memory tracing does not work.\n");
+  MyThreadArray t(Worker1, Worker2, Worker3, Worker4);
+  t.Start();  
+  t.Join(); 
+
+  printf("%s\n", STR->c_str());
+  delete STR;
+}
+REGISTER_TEST2(Run, 304, RACE_DEMO)
+}  // namespace test304
+
+
+
+// test305: A bit more tricky: two locks used inconsistenly. {{{1
+namespace test305 {
+int     GLOB = 0;
+
+// In this test GLOB is protected by MU1 and MU2, but inconsistently.
+// The TRACES observed by helgrind are: 
+// TRACE[1]: Access{T2/S2 wr} -> new State{Mod; #LS=2; #SS=1; T2/S2}
+// TRACE[2]: Access{T4/S9 wr} -> new State{Mod; #LS=1; #SS=2; T2/S2, T4/S9}
+// TRACE[3]: Access{T5/S13 wr} -> new State{Mod; #LS=1; #SS=3; T2/S2, T4/S9, T5/S13}
+// TRACE[4]: Access{T6/S19 wr} -> new State{Mod; #LS=0; #SS=4; T2/S2, T4/S9, T5/S13, T6/S19}
+//
+// The guilty access is either Worker2() or Worker4(), depending on 
+// which mutex is supposed to protect GLOB.
+Mutex MU1;
+Mutex MU2;
+void Worker1() { MU1.Lock(); MU2.Lock(); GLOB=1; MU2.Unlock(); MU1.Unlock(); }
+void Worker2() { MU1.Lock();             GLOB=2;               MU1.Unlock(); }
+void Worker3() { MU1.Lock(); MU2.Lock(); GLOB=3; MU2.Unlock(); MU1.Unlock(); }
+void Worker4() {             MU2.Lock(); GLOB=4; MU2.Unlock();               }
+
+void Run() {  
+  ANNOTATE_TRACE_MEMORY(&GLOB);
+  printf("test305: simple race.\n");
+  MyThread t1(Worker1), t2(Worker2), t3(Worker3), t4(Worker4);
+  t1.Start(); usleep(100);
+  t2.Start(); usleep(100); 
+  t3.Start(); usleep(100);
+  t4.Start(); usleep(100);
+  t1.Join(); t2.Join(); t3.Join(); t4.Join();
+}
+REGISTER_TEST2(Run, 305, RACE_DEMO)
+}  // namespace test305
+
+// test306: Two locks are used to protect a var.  {{{1
+namespace test306 {
+int     GLOB = 0;
+// Thread1 and Thread2 access the var under two locks.
+// Thread3 uses no locks.
+
+Mutex MU1;
+Mutex MU2;
+void Worker1() { MU1.Lock(); MU2.Lock(); GLOB=1; MU2.Unlock(); MU1.Unlock(); }
+void Worker2() { MU1.Lock(); MU2.Lock(); GLOB=3; MU2.Unlock(); MU1.Unlock(); }
+void Worker3() {                         GLOB=4;               }
+
+void Run() {  
+  ANNOTATE_TRACE_MEMORY(&GLOB);
+  printf("test306: simple race.\n");
+  MyThread t1(Worker1), t2(Worker2), t3(Worker3);
+  t1.Start(); usleep(100);
+  t2.Start(); usleep(100); 
+  t3.Start(); usleep(100);
+  t1.Join(); t2.Join(); t3.Join();
+}
+REGISTER_TEST2(Run, 306, RACE_DEMO)
+}  // namespace test306
+
+// test307: Simple race, code with control flow  {{{1
+namespace test307 {
+int     *GLOB = 0;
+volatile /*to fake the compiler*/ bool some_condition = true;
+
+
+void SomeFunc() { }
+
+int FunctionWithControlFlow() {  
+  int unrelated_stuff = 0;
+  unrelated_stuff++;
+  SomeFunc();                // "--keep-history=1" will point somewhere here. 
+  if (some_condition) {      // Or here 
+    if (some_condition) {     
+      unrelated_stuff++;     // Or here.
+      unrelated_stuff++;
+      (*GLOB)++;             // "--keep-history=2" will point here (experimental).
+    }
+  }
+  usleep(100000);
+  return unrelated_stuff;
+}
+
+void Worker1() { FunctionWithControlFlow(); }
+void Worker2() { Worker1(); }
+void Worker3() { Worker2(); }
+void Worker4() { Worker3(); }
+
+void Run() {  
+  GLOB = new int;
+  *GLOB = 1;
+  printf("test307: simple race, code with control flow\n");
+  MyThreadArray t1(Worker1, Worker2, Worker3, Worker4);
+  t1.Start();  
+  t1.Join();
+}
+REGISTER_TEST2(Run, 307, RACE_DEMO)
+}  // namespace test307
+
+// test308: Example of double-checked-locking  {{{1
+namespace test308 {
+struct Foo {
+  int a;
+};
+
+static int   is_inited = 0;
+static Mutex lock;
+static Foo  *foo;
+
+void InitMe() {
+  if (!is_inited) {
+    lock.Lock();
+      if (!is_inited) {
+        foo = new Foo;
+        foo->a = 42;
+        is_inited = 1;
+      }
+    lock.Unlock();
+  }
+}
+
+void UseMe() { 
+  InitMe();
+  CHECK(foo && foo->a == 42); 
+}
+
+void Worker1() { UseMe(); }
+void Worker2() { UseMe(); }
+void Worker3() { UseMe(); }
+
+
+void Run() {  
+  ANNOTATE_TRACE_MEMORY(&is_inited);
+  printf("test308: Example of double-checked-locking\n");
+  MyThreadArray t1(Worker1, Worker2, Worker3);
+  t1.Start();  
+  t1.Join();
+}
+REGISTER_TEST2(Run, 308, RACE_DEMO)
+}  // namespace test308
+
+// test309: Simple race on an STL object.  {{{1
+namespace test309 {
+string  GLOB;
+
+void Worker1() { 
+  GLOB="Thread1";
+}
+void Worker2() { 
+  usleep(100000);
+  GLOB="Booooooooooo"; 
+}
+
+void Run() {  
+  printf("test309: simple race on an STL object.\n");
+  MyThread t1(Worker1), t2(Worker2);
+  t1.Start();  
+  t2.Start();  
+  t1.Join();   t2.Join();
+}
+REGISTER_TEST2(Run, 309, RACE_DEMO)
+}  // namespace test309
+
+// test310: One more simple race.  {{{1
+namespace test310 {
+int     *PTR = NULL;  // GUARDED_BY(mu1)
+
+Mutex mu1;  // Protects PTR.
+Mutex mu2;  // Unrelated to PTR.
+Mutex mu3;  // Unrelated to PTR.
+
+void Writer1() {
+  MutexLock lock3(&mu3);  // This lock is unrelated to PTR.
+  MutexLock lock1(&mu1);  // Protect PTR.
+  *PTR = 1; 
+}
+
+void Writer2() {
+  MutexLock lock2(&mu2);  // This lock is unrelated to PTR.
+  MutexLock lock1(&mu1);  // Protect PTR.
+  int some_unrelated_stuff = 0;
+  if (some_unrelated_stuff == 0)
+    some_unrelated_stuff++;
+  *PTR = 2; 
+}
+
+
+void Reader() {
+  MutexLock lock2(&mu2);  // Oh, gosh, this is a wrong mutex!
+  CHECK(*PTR <= 2); 
+}
+
+// Some functions to make the stack trace non-trivial.
+void DoWrite1() { Writer1();  }
+void Thread1()  { DoWrite1(); }
+
+void DoWrite2() { Writer2();  }
+void Thread2()  { DoWrite2(); }
+
+void DoRead()  { Reader();  }
+void Thread3() { DoRead();  }
+
+void Run() {  
+  printf("test310: simple race.\n");
+  PTR = new int;
+  ANNOTATE_TRACE_MEMORY(PTR);
+  *PTR = 0;
+  MyThread t1(Thread1, NULL, "writer1"), 
+           t2(Thread2, NULL, "writer2"), 
+           t3(Thread3, NULL, "buggy reader");
+  t1.Start();  
+  t2.Start();  
+  usleep(100000);  // Let the writers go first.
+  t3.Start();  
+
+  t1.Join();   
+  t2.Join();
+  t3.Join();
+}
+REGISTER_TEST2(Run, 310, RACE_DEMO)
+}  // namespace test310
+
+// test311: Yet another simple race.  {{{1
+namespace test311 {
+int     *PTR = NULL;  // GUARDED_BY(mu1)
+
+Mutex mu1;  // Protects PTR.
+Mutex mu2;  // Unrelated to PTR.
+Mutex mu3;  // Unrelated to PTR.
+
+void GoodWriter1() {
+  MutexLock lock3(&mu3);  // This lock is unrelated to PTR.
+  MutexLock lock1(&mu1);  // Protect PTR.
+  *PTR = 1; 
+}
+
+void GoodWriter2() {
+  MutexLock lock2(&mu2);  // This lock is unrelated to PTR.
+  MutexLock lock1(&mu1);  // Protect PTR.
+  *PTR = 2; 
+}
+
+void GoodReader() {
+  MutexLock lock1(&mu1);  // Protect PTR.
+  CHECK(*PTR >= 0); 
+}
+
+void BuggyWriter() {
+  MutexLock lock2(&mu2);  // Wrong mutex!
+  *PTR = 3;
+}
+
+// Some functions to make the stack trace non-trivial.
+void DoWrite1() { GoodWriter1();  }
+void Thread1()  { DoWrite1(); }
+
+void DoWrite2() { GoodWriter2();  }
+void Thread2()  { DoWrite2(); }
+
+void DoGoodRead()  { GoodReader();  }
+void Thread3()     { DoGoodRead();  }
+
+void DoBadWrite()  { BuggyWriter(); }
+void Thread4()     { DoBadWrite(); }
+
+void Run() {  
+  printf("test311: simple race.\n");
+  PTR = new int;
+  ANNOTATE_TRACE_MEMORY(PTR);
+  *PTR = 0;
+  MyThread t1(Thread1, NULL, "good writer1"), 
+           t2(Thread2, NULL, "good writer2"), 
+           t3(Thread3, NULL, "good reader"),
+           t4(Thread4, NULL, "buggy writer");
+  t1.Start();  
+  t3.Start();  
+  // t2 goes after t3. This way a pure happens-before detector has no chance.
+  usleep(10000);
+  t2.Start();  
+  usleep(100000);  // Let the good folks go first.
+  t4.Start();  
+
+  t1.Join();   
+  t2.Join();
+  t3.Join();
+  t4.Join();
+}
+REGISTER_TEST2(Run, 311, RACE_DEMO)
+}  // namespace test311
+
+// test312: A test with a very deep stack. {{{1
+namespace test312 {
+int     GLOB = 0;
+void RaceyWrite() { GLOB++; }
+void Func1() { RaceyWrite(); }
+void Func2() { Func1(); }
+void Func3() { Func2(); }
+void Func4() { Func3(); }
+void Func5() { Func4(); }
+void Func6() { Func5(); }
+void Func7() { Func6(); }
+void Func8() { Func7(); }
+void Func9() { Func8(); }
+void Func10() { Func9(); }
+void Func11() { Func10(); }
+void Func12() { Func11(); }
+void Func13() { Func12(); }
+void Func14() { Func13(); }
+void Func15() { Func14(); }
+void Func16() { Func15(); }
+void Func17() { Func16(); }
+void Func18() { Func17(); }
+void Func19() { Func18(); }
+void Worker() { Func19(); }
+void Run() {
+  printf("test312: simple race with deep stack.\n");
+  MyThreadArray t(Worker, Worker, Worker);
+  t.Start();
+  t.Join();
+}
+REGISTER_TEST2(Run, 312, RACE_DEMO)
+}  // namespace test312
+
+// test313 TP: test for thread graph output {{{1
+namespace  test313 {
+BlockingCounter *blocking_counter;
+int     GLOB = 0;
+
+// Worker(N) will do 2^N increments of GLOB, each increment in a separate thread
+void Worker(int depth) {
+  CHECK(depth >= 0);
+  if (depth > 0) {
+    ThreadPool pool(2);
+    pool.StartWorkers();
+    pool.Add(NewCallback(Worker, depth-1));
+    pool.Add(NewCallback(Worker, depth-1));
+  } else {
+    GLOB++; // Race here
+  }
+}
+void Run() {
+  printf("test313: positive\n");
+  Worker(4);
+  printf("\tGLOB=%d\n", GLOB);
+}
+REGISTER_TEST2(Run, 313, RACE_DEMO)
+}  // namespace test313
+
+
+
+// test400: Demo of a simple false positive. {{{1
+namespace test400 {
+static Mutex mu;
+static vector<int> *vec; // GUARDED_BY(mu);
+
+void InitAllBeforeStartingThreads() {
+  vec = new vector<int>;
+  vec->push_back(1);
+  vec->push_back(2);
+}
+
+void Thread1() {
+  MutexLock lock(&mu);
+  vec->pop_back();
+}
+
+void Thread2() {
+  MutexLock lock(&mu);
+  vec->pop_back();
+}
+
+//---- Sub-optimal code ---------
+size_t NumberOfElementsLeft() {
+  MutexLock lock(&mu);
+  return vec->size(); 
+}
+
+void WaitForAllThreadsToFinish_InefficientAndTsanUnfriendly() {
+  while(NumberOfElementsLeft()) {
+    ; // sleep or print or do nothing. 
+  }
+  // It is now safe to access vec w/o lock.
+  // But a hybrid detector (like ThreadSanitizer) can't see it. 
+  // Solutions: 
+  //   1. Use pure happens-before detector (e.g. "tsan --pure-happens-before")
+  //   2. Call ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&mu) 
+  //      in InitAllBeforeStartingThreads()
+  //   3. (preferred) Use WaitForAllThreadsToFinish_Good() (see below).   
+  CHECK(vec->empty());
+  delete vec;
+}
+
+//----- Better code -----------
+
+bool NoElementsLeft(vector<int> *v) {
+  return v->empty();
+}
+
+void WaitForAllThreadsToFinish_Good() {
+  mu.LockWhen(Condition(NoElementsLeft, vec));
+  mu.Unlock();
+
+  // It is now safe to access vec w/o lock.
+  CHECK(vec->empty());
+  delete vec;
+}
+
+
+void Run() {
+  MyThreadArray t(Thread1, Thread2);
+  InitAllBeforeStartingThreads();
+  t.Start();
+  WaitForAllThreadsToFinish_InefficientAndTsanUnfriendly();
+//  WaitForAllThreadsToFinish_Good();
+  t.Join();
+}
+REGISTER_TEST2(Run, 400, RACE_DEMO)
+}  // namespace test400
+
+// test401: Demo of false positive caused by reference counting. {{{1
+namespace test401 {
+// A simplified example of reference counting.
+// DecRef() does ref count increment in a way unfriendly to race detectors.
+// DecRefAnnotated() does the same in a friendly way.
+
+static vector<int> *vec;
+static int ref_count;
+
+void InitAllBeforeStartingThreads(int number_of_threads) {
+  vec = new vector<int>;
+  vec->push_back(1);
+  ref_count = number_of_threads;
+}
+
+// Correct, but unfriendly to race detectors.
+int DecRef() {
+  return AtomicIncrement(&ref_count, -1);
+}
+
+// Correct and friendly to race detectors.
+int DecRefAnnotated() {
+  ANNOTATE_CONDVAR_SIGNAL(&ref_count);
+  int res = AtomicIncrement(&ref_count, -1);
+  if (res == 0) {
+    ANNOTATE_CONDVAR_WAIT(&ref_count);
+  }
+  return res;
+}
+
+void ThreadWorker() {
+  CHECK(ref_count > 0);  
+  CHECK(vec->size() == 1);
+  if (DecRef() == 0) {  // Use DecRefAnnotated() instead!
+    // No one uses vec now ==> delete it.
+    delete vec;  // A false race may be reported here. 
+    vec = NULL;
+  }
+}
+
+void Run() {
+  MyThreadArray t(ThreadWorker, ThreadWorker, ThreadWorker);
+  InitAllBeforeStartingThreads(3 /*number of threads*/);
+  t.Start();
+  t.Join();
+  CHECK(vec == 0);
+}
+REGISTER_TEST2(Run, 401, RACE_DEMO)
+}  // namespace test401
+
+// test501: Manually call PRINT_* annotations {{{1
+namespace test501 {
+int  COUNTER = 0;
+int     GLOB = 0;
+Mutex muCounter, muGlob[65];
+
+void Worker() {
+   muCounter.Lock();
+   int myId = ++COUNTER;
+   muCounter.Unlock();
+  
+   usleep(100);
+  
+   muGlob[myId].Lock();
+   muGlob[0].Lock();
+   GLOB++;
+   muGlob[0].Unlock();
+   muGlob[myId].Unlock();
+}
+
+void Worker_1() {
+   MyThreadArray ta (Worker, Worker, Worker, Worker);
+   ta.Start();
+   usleep(500000);
+   ta.Join ();   
+}
+
+void Worker_2() {
+   MyThreadArray ta (Worker_1, Worker_1, Worker_1, Worker_1);
+   ta.Start();
+   usleep(300000);
+   ta.Join ();   
+}
+
+void Run() {
+   ANNOTATE_RESET_STATS();
+   printf("test501: Manually call PRINT_* annotations.\n");
+   MyThreadArray ta (Worker_2, Worker_2, Worker_2, Worker_2);
+   ta.Start();
+   usleep(100000);
+   ta.Join ();
+   ANNOTATE_PRINT_MEMORY_USAGE(0);
+   ANNOTATE_PRINT_STATS();
+}
+
+REGISTER_TEST2(Run, 501, FEATURE | EXCLUDE_FROM_ALL)
+}  // namespace test501
+
+// test502: produce lots of segments without cross-thread relations {{{1
+namespace test502 {
+
+/*
+ * This test produces ~1Gb of memory usage when run with the following options:
+ * 
+ * --tool=helgrind
+ * --trace-after-race=0
+ * --num-callers=2
+ * --more-context=no
+ */
+
+Mutex MU;
+int     GLOB = 0;
+
+void TP() {
+   for (int i = 0; i < 750000; i++) {
+      MU.Lock();
+      GLOB++;
+      MU.Unlock();
+   }
+}
+
+void Run() {
+   MyThreadArray t(TP, TP);
+   printf("test502: produce lots of segments without cross-thread relations\n");
+   
+   t.Start();
+   t.Join();
+}
+
+REGISTER_TEST2(Run, 502, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL
+                              | PERFORMANCE)
+}  // namespace test502
+
+// test503: produce lots of segments with simple HB-relations {{{1
+// HB cache-miss rate is ~55%
+namespace test503 {
+
+//  |- |  |  |  |  |
+//  | \|  |  |  |  |
+//  |  |- |  |  |  |
+//  |  | \|  |  |  |
+//  |  |  |- |  |  |
+//  |  |  | \|  |  |
+//  |  |  |  |- |  |
+//  |  |  |  | \|  |
+//  |  |  |  |  |- |
+//  |  |  |  |  | \|
+//  |  |  |  |  |  |----
+//->|  |  |  |  |  |
+//  |- |  |  |  |  |
+//  | \|  |  |  |  |
+//     ...
+  
+const int N_threads = 32;
+const int ARRAY_SIZE = 128;
+int       GLOB[ARRAY_SIZE];
+ProducerConsumerQueue *Q[N_threads];
+int GLOB_limit = 100000;
+int count = -1;
+
+void Worker(){
+   int myId = AtomicIncrement(&count, 1);
+   
+   ProducerConsumerQueue &myQ = *Q[myId], &nextQ = *Q[(myId+1) % N_threads];
+   
+   // this code produces a new SS with each new segment
+   while (myQ.Get() != NULL) {
+      for (int i = 0; i < ARRAY_SIZE; i++)
+         GLOB[i]++;
+      
+      if (myId == 0 && GLOB[0] > GLOB_limit) {
+         // Stop all threads
+         for (int i = 0; i < N_threads; i++)
+            Q[i]->Put(NULL);
+      } else
+         nextQ.Put(GLOB);
+   }
+}
+
+void Run() {
+   printf("test503: produce lots of segments with simple HB-relations\n");
+   for (int i = 0; i < N_threads; i++)
+      Q[i] = new ProducerConsumerQueue(1);
+   Q[0]->Put(GLOB);
+   
+   {      
+      ThreadPool pool(N_threads);
+      pool.StartWorkers();
+      for (int i = 0; i < N_threads; i++) {
+         pool.Add(NewCallback(Worker));
+      }
+   } // all folks are joined here.
+   
+   for (int i = 0; i < N_threads; i++)
+      delete Q[i];
+}
+
+REGISTER_TEST2(Run, 503, MEMORY_USAGE | PRINT_STATS
+                  | PERFORMANCE | EXCLUDE_FROM_ALL)
+}  // namespace test503
+
+// test504: force massive cache fetch-wback (50% misses, mostly CacheLineZ) {{{1
+namespace test504 {
+
+const int N_THREADS = 2,
+          HG_CACHELINE_COUNT = 1 << 16,
+          HG_CACHELINE_SIZE  = 1 << 6,
+          HG_CACHE_SIZE = HG_CACHELINE_COUNT * HG_CACHELINE_SIZE;
+
+// int gives us ~4x speed of the byte test
+// 4x array size gives us
+// total multiplier of 16x over the cachesize 
+// so we can neglect the cached-at-the-end memory 
+const int ARRAY_SIZE = 4 * HG_CACHE_SIZE,
+          ITERATIONS = 30;
+int array[ARRAY_SIZE];
+
+int count = 0;
+Mutex count_mu;
+
+void Worker() {
+   count_mu.Lock();
+   int myId = ++count;
+   count_mu.Unlock();
+   
+   // all threads write to different memory locations,
+   // so no synchronization mechanisms are needed
+   int lower_bound = ARRAY_SIZE * (myId-1) / N_THREADS,
+       upper_bound = ARRAY_SIZE * ( myId ) / N_THREADS;
+   for (int j = 0; j < ITERATIONS; j++)
+   for (int i = lower_bound; i < upper_bound; 
+            i += HG_CACHELINE_SIZE / sizeof(array[0])) {
+      array[i] = i; // each array-write generates a cache miss
+   }
+}
+
+void Run() {
+   printf("test504: force massive CacheLineZ fetch-wback\n");
+   MyThreadArray t(Worker, Worker);
+   t.Start();
+   t.Join();
+}
+
+REGISTER_TEST2(Run, 504, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL)
+}  // namespace test504
+
+// test505: force massive cache fetch-wback (60% misses) {{{1
+// modification of test504 - more threads, byte accesses and lots of mutexes
+// so it produces lots of CacheLineF misses (30-50% of CacheLineZ misses)
+namespace test505 {
+
+const int N_THREADS = 2,
+          HG_CACHELINE_COUNT = 1 << 16,
+          HG_CACHELINE_SIZE  = 1 << 6,
+          HG_CACHE_SIZE = HG_CACHELINE_COUNT * HG_CACHELINE_SIZE;
+
+const int ARRAY_SIZE = 4 * HG_CACHE_SIZE,
+          ITERATIONS = 3;
+int64_t array[ARRAY_SIZE];
+
+int count = 0;
+Mutex count_mu;
+
+void Worker() {
+   const int N_MUTEXES = 5;
+   Mutex mu[N_MUTEXES];
+   count_mu.Lock();
+   int myId = ++count;
+   count_mu.Unlock();
+   
+   // all threads write to different memory locations,
+   // so no synchronization mechanisms are needed
+   int lower_bound = ARRAY_SIZE * (myId-1) / N_THREADS,
+       upper_bound = ARRAY_SIZE * ( myId ) / N_THREADS;
+   for (int j = 0; j < ITERATIONS; j++)
+   for (int mutex_id = 0; mutex_id < N_MUTEXES; mutex_id++) {
+      Mutex *m = & mu[mutex_id];
+      m->Lock();
+      for (int i = lower_bound + mutex_id, cnt = 0; 
+               i < upper_bound;
+               i += HG_CACHELINE_SIZE / sizeof(array[0]), cnt++) {
+         array[i] = i; // each array-write generates a cache miss
+      }
+      m->Unlock();
+   }
+}
+
+void Run() {
+   printf("test505: force massive CacheLineF fetch-wback\n");
+   MyThreadArray t(Worker, Worker);
+   t.Start();
+   t.Join();
+}
+
+REGISTER_TEST2(Run, 505, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL)
+}  // namespace test505
+
+// test506: massive HB's using Barriers {{{1
+// HB cache miss is ~40%
+// segments consume 10x more memory than SSs
+// modification of test39
+namespace test506 {
+#ifndef NO_BARRIER
+// Same as test17 but uses Barrier class (pthread_barrier_t). 
+int     GLOB = 0;
+const int N_threads = 64,
+          ITERATIONS = 1000;
+Barrier *barrier[ITERATIONS];
+Mutex   MU; 
+
+void Worker() {
+  for (int i = 0; i < ITERATIONS; i++) {
+     MU.Lock();
+     GLOB++;
+     MU.Unlock();
+     barrier[i]->Block();
+  }
+}
+void Run() {
+  printf("test506: massive HB's using Barriers\n");
+  for (int i = 0; i < ITERATIONS; i++) {
+     barrier[i] = new Barrier(N_threads);
+  }
+  {
+    ThreadPool pool(N_threads);
+    pool.StartWorkers();
+    for (int i = 0; i < N_threads; i++) {
+      pool.Add(NewCallback(Worker));
+    }
+  } // all folks are joined here.
+  CHECK(GLOB == N_threads * ITERATIONS);
+  for (int i = 0; i < ITERATIONS; i++) {
+     delete barrier[i];
+  }
+}
+REGISTER_TEST2(Run, 506, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL);
+#endif // NO_BARRIER
+}  // namespace test506
+
+// test507: vgHelgrind_initIterAtFM/stackClear benchmark {{{1
+// vgHelgrind_initIterAtFM/stackClear consume ~8.5%/5.5% CPU
+namespace test507 {
+const int N_THREADS    = 1,
+          BUFFER_SIZE  = 1,
+          ITERATIONS   = 1 << 20;
+
+void Foo() {
+  struct T {
+    char temp;
+    T() {
+      ANNOTATE_RWLOCK_CREATE(&temp);
+    }
+    ~T() {
+      ANNOTATE_RWLOCK_DESTROY(&temp);
+    }
+  } s[BUFFER_SIZE];
+  s->temp = '\0';
+}
+
+void Worker() {
+  for (int j = 0; j < ITERATIONS; j++) {
+    Foo();
+  }
+}
+
+void Run() {
+  printf("test507: vgHelgrind_initIterAtFM/stackClear benchmark\n");
+  {
+    ThreadPool pool(N_THREADS);
+    pool.StartWorkers();
+    for (int i = 0; i < N_THREADS; i++) {
+      pool.Add(NewCallback(Worker));
+    }
+  } // all folks are joined here.
+}
+REGISTER_TEST2(Run, 507, EXCLUDE_FROM_ALL);
+}  // namespace test507
+
+// test508: cmp_WordVecs_for_FM benchmark {{{1
+// 50+% of CPU consumption by cmp_WordVecs_for_FM
+namespace test508 {
+const int N_THREADS    = 1,
+          BUFFER_SIZE  = 1 << 10,
+          ITERATIONS   = 1 << 9;
+
+void Foo() {
+  struct T {
+    char temp;
+    T() {
+      ANNOTATE_RWLOCK_CREATE(&temp);
+    }
+    ~T() {
+      ANNOTATE_RWLOCK_DESTROY(&temp);
+    }
+  } s[BUFFER_SIZE];
+  s->temp = '\0';
+}
+
+void Worker() {
+  for (int j = 0; j < ITERATIONS; j++) {
+    Foo();
+  }
+}
+
+void Run() {
+  printf("test508: cmp_WordVecs_for_FM benchmark\n");
+  {
+    ThreadPool pool(N_THREADS);
+    pool.StartWorkers();
+    for (int i = 0; i < N_THREADS; i++) {
+      pool.Add(NewCallback(Worker));
+    }
+  } // all folks are joined here.
+}
+REGISTER_TEST2(Run, 508, EXCLUDE_FROM_ALL);
+}  // namespace test508
+
+// test509: avl_find_node benchmark {{{1
+// 10+% of CPU consumption by avl_find_node
+namespace test509 {
+const int N_THREADS    = 16,
+          ITERATIONS   = 1 << 8;
+
+void Worker() {
+  std::vector<Mutex*> mu_list;
+  for (int i = 0; i < ITERATIONS; i++) {
+    Mutex * mu = new Mutex();
+    mu_list.push_back(mu);
+    mu->Lock();
+  }
+  for (int i = ITERATIONS - 1; i >= 0; i--) {
+    Mutex * mu = mu_list[i];
+    mu->Unlock();
+    delete mu;
+  }
+}
+
+void Run() {
+  printf("test509: avl_find_node benchmark\n");
+  {
+    ThreadPool pool(N_THREADS);
+    pool.StartWorkers();
+    for (int i = 0; i < N_THREADS; i++) {
+      pool.Add(NewCallback(Worker));
+    }
+  } // all folks are joined here.
+}
+REGISTER_TEST2(Run, 509, EXCLUDE_FROM_ALL);
+}  // namespace test509
+
+// test510: SS-recycle test {{{1
+// this tests shows the case where only ~1% of SS are recycled
+namespace test510 {
+const int N_THREADS    = 16,
+          ITERATIONS   = 1 << 10;
+int GLOB = 0;
+
+void Worker() {
+  usleep(100000);
+  for (int i = 0; i < ITERATIONS; i++) {
+    ANNOTATE_CONDVAR_SIGNAL((void*)0xDeadBeef);
+    GLOB++;
+    usleep(10);
+  }
+}
+
+void Run() {
+  //ANNOTATE_BENIGN_RACE(&GLOB, "Test");
+  printf("test510: SS-recycle test\n");
+  {
+    ThreadPool pool(N_THREADS);
+    pool.StartWorkers();
+    for (int i = 0; i < N_THREADS; i++) {
+      pool.Add(NewCallback(Worker));
+    }
+  } // all folks are joined here.  
+}
+REGISTER_TEST2(Run, 510, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
+}  // namespace test510
+
+// test511: Segment refcounting test ('1' refcounting) {{{1
+namespace test511 {
+int GLOB = 0;
+
+void Run () {
+   for (int i = 0; i < 300; i++) {
+      ANNOTATE_CONDVAR_SIGNAL(&GLOB);
+      usleep(1000);
+      GLOB++;
+      ANNOTATE_CONDVAR_WAIT(&GLOB);
+      if (i % 100 == 0)
+         ANNOTATE_PRINT_MEMORY_USAGE(0);
+   }
+}
+REGISTER_TEST2(Run, 511, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
+}  // namespace test511
+
+// test512: Segment refcounting test ('S' refcounting) {{{1
+namespace test512 {
+int GLOB = 0;
+sem_t SEM;
+
+void Run () {
+   sem_init(&SEM, 0, 0);
+   for (int i = 0; i < 300; i++) {
+      sem_post(&SEM);
+      usleep(1000);
+      GLOB++;
+      sem_wait(&SEM);
+      /*if (i % 100 == 0)
+         ANNOTATE_PRINT_MEMORY_USAGE(0);*/
+   }
+   sem_destroy(&SEM);
+}
+REGISTER_TEST2(Run, 512, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
+}  // namespace test512
+
+// test513: --fast-mode benchmark {{{1
+namespace test513 {
+
+const int N_THREADS = 2,
+          HG_CACHELINE_SIZE  = 1 << 6,
+          ARRAY_SIZE = HG_CACHELINE_SIZE * 512,
+          MUTEX_ID_BITS = 8,
+          MUTEX_ID_MASK = (1 << MUTEX_ID_BITS) - 1;
+
+// Each thread has its own cacheline and tackles with it intensively
+const int ITERATIONS = 1024;
+int array[N_THREADS][ARRAY_SIZE];
+
+int count = 0;
+Mutex count_mu;
+Mutex mutex_arr[N_THREADS][MUTEX_ID_BITS];
+
+void Worker() {
+   count_mu.Lock();
+   int myId = count++;
+   count_mu.Unlock();
+   
+   // all threads write to different memory locations
+   for (int j = 0; j < ITERATIONS; j++) {
+      int mutex_mask = j & MUTEX_ID_BITS;
+      for (int m = 0; m < MUTEX_ID_BITS; m++)
+         if (mutex_mask & (1 << m))
+            mutex_arr[myId][m].Lock();
+      
+      for (int i = 0; i < ARRAY_SIZE; i++) {
+         array[myId][i] = i;
+      }
+      
+      for (int m = 0; m < MUTEX_ID_BITS; m++)
+         if (mutex_mask & (1 << m))
+            mutex_arr[myId][m].Unlock();
+   }
+}
+
+void Run() {
+   printf("test513: --fast-mode benchmark\n");
+   {
+      ThreadPool pool(N_THREADS);
+      pool.StartWorkers();
+      for (int i = 0; i < N_THREADS; i++) {
+         pool.Add(NewCallback(Worker));
+      }
+   } // all folks are joined here.
+}
+
+REGISTER_TEST2(Run, 513, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL)
+}  // namespace test513
+
+// End {{{1
+// vim:shiftwidth=2:softtabstop=2:expandtab:foldmethod=marker
diff --git a/drd/tests/unified_annotations.h b/drd/tests/unified_annotations.h
new file mode 100644
index 0000000..13259d6
--- /dev/null
+++ b/drd/tests/unified_annotations.h
@@ -0,0 +1,70 @@
+#ifndef _UNIFIED_ANNOTATIONS_H_
+#define _UNIFIED_ANNOTATIONS_H_
+
+
+#include "../../drd/drd.h"
+
+
+/*
+ * Define annotation macros such that these can be intercepted by DRD, Helgrind
+ * and ThreadSanitizer. See also
+ * http://code.google.com/p/data-race-test/source/browse/trunk/dynamic_annotations/dynamic_annotations.h
+ */
+#define U_ANNOTATE_NEW_MEMORY(addr, size) ANNOTATE_NEW_MEMORY(addr, size)
+#define U_ANNOTATE_HAPPENS_BEFORE(addr) U_AnnotateHappensBefore(addr)
+#define U_ANNOTATE_HAPPENS_AFTER(addr) U_AnnotateHappensAfter(addr)
+#define U_ANNOTATE_HAPPENS_DONE(addr)		\
+  do {						\
+    ANNOTATE_HAPPENS_DONE(addr);		\
+  } while(0)
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if 0
+}
+#endif
+
+
+void  __attribute__((weak,noinline))
+AnnotateCondVarSignal(const char *file, int line, const volatile void *cv)
+{
+  asm("");
+}
+
+void  __attribute__((weak,noinline))
+AnnotateCondVarWait(const char *file, int line, const volatile void *cv,
+		    const volatile void *lock)
+{
+  asm("");
+}
+
+static __inline__ void U_AnnotateHappensBefore(void* addr)
+{
+  ANNOTATE_HAPPENS_BEFORE(addr);
+  AnnotateCondVarSignal(__FILE__, __LINE__, addr);
+}
+
+static __inline__ void U_AnnotateHappensAfter(void *addr)
+{
+  ANNOTATE_HAPPENS_AFTER(addr);
+  AnnotateCondVarWait(__FILE__, __LINE__, addr, NULL);
+}
+
+
+#if 0
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _UNIFIED_ANNOTATIONS_H_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff --git a/drd/tests/unit_bitmap.c b/drd/tests/unit_bitmap.c
new file mode 100644
index 0000000..236cf06
--- /dev/null
+++ b/drd/tests/unit_bitmap.c
@@ -0,0 +1,345 @@
+/** @brief Unit-test for DRD's bitmap implementation. */
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "coregrind/m_oset.c"
+#include "drd/drd_bitmap.c"
+#include "drd/drd_bitmap2_node.c"
+#include "drd/pub_drd_bitmap.h"
+
+
+#ifndef MIN
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+#endif
+#ifndef MAX
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+#endif
+
+
+/* Replacements for Valgrind core functionality. */
+
+void* VG_(malloc)(HChar* cc, SizeT nbytes)
+{ return malloc(nbytes); }
+void  VG_(free)(void* p)
+{ return free(p); }
+void  VG_(assert_fail)(Bool isCore, const Char* assertion, const Char* file,
+                       Int line, const Char* function, const HChar* format,
+                       ...)
+{
+  fprintf(stderr,
+          "%s:%u: %s%sAssertion `%s' failed.\n",
+          file,
+          line,
+          function ? (char*)function : "",
+          function ? ": " : "",
+          assertion);
+  fflush(stdout);
+  fflush(stderr);
+  abort();
+}
+
+void* VG_(memset)(void *s, Int c, SizeT sz)
+{ return memset(s, c, sz); }
+void* VG_(memcpy)(void *d, const void *s, SizeT sz)
+{ return memcpy(d, s, sz); }
+Int VG_(memcmp)(const void* s1, const void* s2, SizeT n)
+{ return memcmp(s1, s2, n); }
+UInt VG_(printf)(const HChar *format, ...)
+{ UInt ret; va_list vargs; va_start(vargs, format); ret = vprintf(format, vargs); va_end(vargs); return ret; }
+UInt VG_(message)(VgMsgKind kind, const HChar* format, ...)
+{ UInt ret; va_list vargs; va_start(vargs, format); ret = vprintf(format, vargs); va_end(vargs); printf("\n"); return ret; }
+Bool DRD_(is_suppressed)(const Addr a1, const Addr a2)
+{ assert(0); }
+
+
+/* Actual unit test */
+
+static int s_verbose = 1;
+
+static
+struct { Addr address; SizeT size; BmAccessTypeT access_type; }
+  s_test1_args[] = {
+    {                           0, 0, eLoad  },
+    {                           0, 1, eLoad  },
+    {                         666, 4, eLoad  },
+    {                         667, 2, eStore },
+    {                        1024, 1, eStore },
+    {                   0xffffULL, 1, eStore },
+    {               0x0001ffffULL, 1, eLoad  },
+    {               0x00ffffffULL, 1, eLoad  },
+    { 0xffffffffULL - (((1 << ADDR_LSB_BITS) + 1) << ADDR_IGNORED_BITS),
+                                   1, eStore },
+#if defined(VGP_amd64_linux) || defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
+    { 0xffffffffULL - (1 << ADDR_LSB_BITS << ADDR_IGNORED_BITS),
+                                   1, eStore },
+    {               0xffffffffULL, 1, eStore },
+    {              0x100000000ULL, 1, eStore },
+    { -2ULL - (1 << ADDR_LSB_BITS << ADDR_IGNORED_BITS),
+                                   1, eStore },
+#endif
+  };
+
+/**
+ * Compare two bitmaps and if different, print the differences.
+ */
+int bm_equal_print_diffs(struct bitmap* bm1, struct bitmap* bm2)
+{
+  int equal;
+
+  equal = DRD_(bm_equal)(bm1, bm2);
+  if (s_verbose && ! equal)
+  {
+    unsigned i;
+
+    VG_(printf)("Bitmaps are different.\n");
+    for (i = 0; i < 0x10000; i++)
+    {
+      if (DRD_(bm_has_1)(bm1, i, eLoad) != DRD_(bm_has_1)(bm2, i, eLoad)
+          || DRD_(bm_has_1)(bm1, i, eStore) != DRD_(bm_has_1)(bm2, i, eStore))
+      {
+        printf("0x%x %c %c %c %c\n",
+               i,
+               DRD_(bm_has_1)(bm1, i, eLoad)  ? 'R' : ' ',
+               DRD_(bm_has_1)(bm1, i, eStore) ? 'W' : ' ',
+               DRD_(bm_has_1)(bm2, i, eLoad)  ? 'R' : ' ',
+               DRD_(bm_has_1)(bm2, i, eStore) ? 'W' : ' '
+               );
+      }
+    }
+    fflush(stdout);
+  }
+
+  return equal;
+}
+
+void bm_test1(void)
+{
+  struct bitmap* bm;
+  struct bitmap* bm2;
+  unsigned i, j;
+
+  bm = DRD_(bm_new)();
+
+  for (i = 0; i < sizeof(s_test1_args)/sizeof(s_test1_args[0]); i++)
+  {
+    DRD_(bm_access_range)(bm,
+                          s_test1_args[i].address,
+                          s_test1_args[i].address + s_test1_args[i].size,
+                          s_test1_args[i].access_type);
+  }
+
+  for (i = 0; i < sizeof(s_test1_args)/sizeof(s_test1_args[0]); i++)
+  {
+    for (j = 0;
+         first_address_with_higher_lsb(j) <= s_test1_args[i].size;
+         j = first_address_with_higher_lsb(j))
+    {
+      tl_assert(DRD_(bm_has_1)(bm,
+                               s_test1_args[i].address + j,
+                               s_test1_args[i].access_type));
+    }
+  }
+
+  bm2 = DRD_(bm_new)();
+  DRD_(bm_merge2)(bm2, bm);
+  DRD_(bm_merge2)(bm2, bm);
+  assert(bm_equal_print_diffs(bm2, bm));
+
+  if (s_verbose)
+    VG_(printf)("Deleting bitmap bm\n");
+  DRD_(bm_delete)(bm);
+  if (s_verbose)
+    VG_(printf)("Deleting bitmap bm2\n");
+  DRD_(bm_delete)(bm2);
+}
+
+/** Test whether bm_equal() works correctly. */
+void bm_test2()
+{
+  struct bitmap* bm1;
+  struct bitmap* bm2;
+
+  bm1 = DRD_(bm_new)();
+  bm2 = DRD_(bm_new)();
+  DRD_(bm_access_load_1)(bm1, 7);
+  DRD_(bm_access_load_1)(bm2, make_address(1, 0) + 7);
+  assert(! DRD_(bm_equal)(bm1, bm2));
+  assert(! DRD_(bm_equal)(bm2, bm1));
+  DRD_(bm_access_load_1)(bm2, 7);
+  assert(! DRD_(bm_equal)(bm1, bm2));
+  assert(! DRD_(bm_equal)(bm2, bm1));
+  DRD_(bm_access_store_1)(bm1, make_address(1, 0) + 7);
+  assert(! DRD_(bm_equal)(bm1, bm2));
+  assert(! DRD_(bm_equal)(bm2, bm1));
+  DRD_(bm_delete)(bm2);
+  DRD_(bm_delete)(bm1);
+}
+
+/** Torture test of the functions that set or clear a range of bits. */
+void bm_test3(const int outer_loop_step, const int inner_loop_step)
+{
+  unsigned i, j;
+  struct bitmap* bm1;
+  struct bitmap* bm2;
+
+  const Addr lb = make_address(2, 0) - 2 * BITS_PER_UWORD;
+  const Addr ub = make_address(2, 0) + 2 * BITS_PER_UWORD;
+
+  assert(outer_loop_step >= 1);
+  assert((outer_loop_step % ADDR_GRANULARITY) == 0);
+  assert(inner_loop_step >= 1);
+  assert((inner_loop_step % ADDR_GRANULARITY) == 0);
+
+  bm1 = DRD_(bm_new)();
+  bm2 = DRD_(bm_new)();
+  for (i = lb; i < ub; i += outer_loop_step)
+  {
+    for (j = i + ADDR_GRANULARITY; j < ub; j += inner_loop_step)
+    {
+      DRD_(bm_access_range_load)(bm1, i, j);
+      DRD_(bm_clear_load)(bm1, i, j);
+      assert(bm_equal_print_diffs(bm1, bm2));
+      DRD_(bm_access_load_1)(bm1, i);
+      DRD_(bm_clear_load)(bm1, i, i + MAX(1, ADDR_GRANULARITY));
+      assert(bm_equal_print_diffs(bm1, bm2));
+      DRD_(bm_access_load_2)(bm1, i);
+      DRD_(bm_clear_load)(bm1, i, i + MAX(2, ADDR_GRANULARITY));
+      assert(bm_equal_print_diffs(bm1, bm2));
+      DRD_(bm_access_load_4)(bm1, i);
+      DRD_(bm_clear_load)(bm1, i, i + MAX(4, ADDR_GRANULARITY));
+      assert(bm_equal_print_diffs(bm1, bm2));
+      DRD_(bm_access_load_8)(bm1, i);
+      DRD_(bm_clear_load)(bm1, i, i + MAX(8, ADDR_GRANULARITY));
+      assert(bm_equal_print_diffs(bm1, bm2));
+
+      DRD_(bm_access_range_store)(bm1, i, j);
+      DRD_(bm_clear_store)(bm1, i, j);
+      assert(bm_equal_print_diffs(bm1, bm2));
+      DRD_(bm_access_store_1)(bm1, i);
+      DRD_(bm_clear_store)(bm1, i, i + MAX(1, ADDR_GRANULARITY));
+      assert(bm_equal_print_diffs(bm1, bm2));
+      DRD_(bm_access_store_2)(bm1, i);
+      DRD_(bm_clear_store)(bm1, i, i + MAX(2, ADDR_GRANULARITY));
+      assert(bm_equal_print_diffs(bm1, bm2));
+      DRD_(bm_access_store_4)(bm1, i);
+      DRD_(bm_clear_store)(bm1, i, i + MAX(4, ADDR_GRANULARITY));
+      assert(bm_equal_print_diffs(bm1, bm2));
+      DRD_(bm_access_store_8)(bm1, i);
+      DRD_(bm_clear_store)(bm1, i, i + MAX(8, ADDR_GRANULARITY));
+      assert(bm_equal_print_diffs(bm1, bm2));
+
+      DRD_(bm_access_range_load)(bm1, i, j);
+      DRD_(bm_access_range_store)(bm1, i, j);
+      DRD_(bm_clear)(bm1, i, j);
+      assert(bm_equal_print_diffs(bm1, bm2));
+      DRD_(bm_access_load_1)(bm1, i);
+      DRD_(bm_access_store_1)(bm1, i);
+      DRD_(bm_clear)(bm1, i, i + MAX(1, ADDR_GRANULARITY));
+      assert(bm_equal_print_diffs(bm1, bm2));
+      DRD_(bm_access_load_2)(bm1, i);
+      DRD_(bm_access_store_2)(bm1, i);
+      DRD_(bm_clear)(bm1, i, i + MAX(2, ADDR_GRANULARITY));
+      assert(bm_equal_print_diffs(bm1, bm2));
+      DRD_(bm_access_load_4)(bm1, i);
+      DRD_(bm_access_store_4)(bm1, i);
+      DRD_(bm_clear)(bm1, i, i + MAX(4, ADDR_GRANULARITY));
+      assert(bm_equal_print_diffs(bm1, bm2));
+      DRD_(bm_access_load_8)(bm1, i);
+      DRD_(bm_access_store_8)(bm1, i);
+      DRD_(bm_clear)(bm1, i, i + MAX(8, ADDR_GRANULARITY));
+      assert(bm_equal_print_diffs(bm1, bm2));
+    }
+  }
+  DRD_(bm_access_range_load)(bm1, 0, make_address(2, 0) + 2 * BITS_PER_UWORD);
+  DRD_(bm_access_range_store)(bm1, 0, make_address(2, 0) + 2 * BITS_PER_UWORD);
+  DRD_(bm_access_range_load)(bm2, 0, make_address(2, 0) + 2 * BITS_PER_UWORD);
+  DRD_(bm_access_range_store)(bm2, 0, make_address(2, 0) + 2 * BITS_PER_UWORD);
+  for (i = make_address(1, 0) - 2 * BITS_PER_UWORD;
+       i < make_address(1, 0) + 2 * BITS_PER_UWORD;
+       i += outer_loop_step)
+  {
+    for (j = i + 1; j < ub; j += inner_loop_step)
+    {
+      DRD_(bm_clear_load)(bm1, i, j);
+      DRD_(bm_access_range_load)(bm1, i, j);
+      assert(bm_equal_print_diffs(bm1, bm2));
+      DRD_(bm_clear_load)(bm1, i, i+1);
+      DRD_(bm_access_load_1)(bm1, i);
+      assert(bm_equal_print_diffs(bm1, bm2));
+      DRD_(bm_clear_load)(bm1, i, i+2);
+      DRD_(bm_access_load_2)(bm1, i);
+      assert(bm_equal_print_diffs(bm1, bm2));
+      DRD_(bm_clear_load)(bm1, i, i+4);
+      DRD_(bm_access_load_4)(bm1, i);
+      assert(bm_equal_print_diffs(bm1, bm2));
+      DRD_(bm_clear_load)(bm1, i, i+8);
+      DRD_(bm_access_load_8)(bm1, i);
+      assert(bm_equal_print_diffs(bm1, bm2));
+
+      DRD_(bm_clear_store)(bm1, i, j);
+      DRD_(bm_access_range_store)(bm1, i, j);
+      assert(bm_equal_print_diffs(bm1, bm2));
+      DRD_(bm_clear_store)(bm1, i, i+1);
+      DRD_(bm_access_store_1)(bm1, i);
+      assert(bm_equal_print_diffs(bm1, bm2));
+      DRD_(bm_clear_store)(bm1, i, i+2);
+      DRD_(bm_access_store_2)(bm1, i);
+      assert(bm_equal_print_diffs(bm1, bm2));
+      DRD_(bm_clear_store)(bm1, i, i+4);
+      DRD_(bm_access_store_4)(bm1, i);
+      assert(bm_equal_print_diffs(bm1, bm2));
+      DRD_(bm_clear_store)(bm1, i, i+8);
+      DRD_(bm_access_store_8)(bm1, i);
+      assert(bm_equal_print_diffs(bm1, bm2));
+
+      DRD_(bm_clear)(bm1, i, j);
+      DRD_(bm_access_range_load)(bm1, i, j);
+      DRD_(bm_access_range_store)(bm1, i, j);
+      assert(bm_equal_print_diffs(bm1, bm2));
+    }
+  }
+  DRD_(bm_delete)(bm2);
+  DRD_(bm_delete)(bm1);
+}
+
+int main(int argc, char** argv)
+{
+  int outer_loop_step = ADDR_GRANULARITY;
+  int inner_loop_step = ADDR_GRANULARITY;
+  int optchar;
+
+  while ((optchar = getopt(argc, argv, "s:t:q")) != EOF)
+  {
+    switch (optchar)
+    {
+    case 's':
+      outer_loop_step = atoi(optarg);
+      break;
+    case 't':
+      inner_loop_step = atoi(optarg);
+      break;
+    case 'q':
+      s_verbose = 0;
+      break;
+    default:
+      fprintf(stderr,
+              "Usage: %s [-s<outer_loop_step>] [-t<inner_loop_step>] [-q].\n",
+              argv[0]);
+      break;
+    }
+  }
+
+  fprintf(stderr, "Start of DRD BM unit test.\n");
+
+  bm_test1();
+  bm_test2();
+  bm_test3(outer_loop_step, inner_loop_step);
+
+  fprintf(stderr, "End of DRD BM unit test.\n");
+
+  return 0;
+}
diff --git a/drd/tests/unit_bitmap.stderr.exp b/drd/tests/unit_bitmap.stderr.exp
new file mode 100644
index 0000000..2efe8bd
--- /dev/null
+++ b/drd/tests/unit_bitmap.stderr.exp
@@ -0,0 +1,2 @@
+Start of DRD BM unit test.
+End of DRD BM unit test.
diff --git a/drd/tests/unit_bitmap.vgtest b/drd/tests/unit_bitmap.vgtest
new file mode 100644
index 0000000..a3b93e7
--- /dev/null
+++ b/drd/tests/unit_bitmap.vgtest
@@ -0,0 +1,3 @@
+prog: unit_bitmap
+args: -s 93 -t 97 -q
+vgopts: -q --tool=memcheck --leak-check=full --show-reachable=yes
diff --git a/drd/tests/unit_vc.c b/drd/tests/unit_vc.c
new file mode 100644
index 0000000..353ce4b
--- /dev/null
+++ b/drd/tests/unit_vc.c
@@ -0,0 +1,110 @@
+/** @brief Unit-test for DRD's vector clock implementation. */
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "drd/drd_vc.c"
+
+
+/* Replacements for Valgrind core functionality. */
+
+void* VG_(malloc)(HChar* cc, SizeT nbytes)
+{ return malloc(nbytes); }
+void* VG_(realloc)(HChar* cc, void* p, SizeT size)
+{ return realloc(p, size); }
+void  VG_(free)(void* p)
+{ return free(p); }
+void  VG_(assert_fail)(Bool isCore, const Char* assertion, const Char* file,
+                       Int line, const Char* function, const HChar* format,
+                       ...)
+{
+  fprintf(stderr,
+          "%s:%u: %s%sAssertion `%s' failed.\n",
+          file,
+          line,
+          function ? (char*)function : "",
+          function ? ": " : "",
+          assertion);
+  fflush(stdout);
+  fflush(stderr);
+  abort();
+}
+
+void* VG_(memset)(void *s, Int c, SizeT sz)
+{ return memset(s, c, sz); }
+void* VG_(memcpy)(void *d, const void *s, SizeT sz)
+{ return memcpy(d, s, sz); }
+Int VG_(memcmp)(const void* s1, const void* s2, SizeT n)
+{ return memcmp(s1, s2, n); }
+UInt VG_(printf)(const HChar *format, ...)
+{ UInt ret; va_list vargs; va_start(vargs, format); ret = vprintf(format, vargs); va_end(vargs); return ret; }
+UInt VG_(snprintf)(Char* buf, Int size, const HChar *format, ...)
+{ UInt ret; va_list vargs; va_start(vargs, format); ret = vsnprintf(buf, size, format, vargs); va_end(vargs); return ret; }
+SizeT VG_(strlen)(const Char* str) { return strlen(str); }
+UInt VG_(message)(VgMsgKind kind, const HChar* format, ...)
+{ UInt ret; va_list vargs; va_start(vargs, format); ret = vprintf(format, vargs); va_end(vargs); printf("\n"); return ret; }
+Bool DRD_(is_suppressed)(const Addr a1, const Addr a2)
+{ assert(0); }
+
+
+/* Actual unit test */
+
+static void vc_unittest(void)
+{
+  int i;
+  char *str;
+  VectorClock vc1;
+  VCElem vc1elem[] = { { 3, 7 }, { 5, 8 }, };
+  VectorClock vc2;
+  VCElem vc2elem[] = { { 1, 4 }, { 3, 9 }, };
+  VectorClock vc3;
+  VCElem vc4elem[] = { { 1, 3 }, { 2, 1 }, };
+  VectorClock vc4;
+  VCElem vc5elem[] = { { 1, 4 }, };
+  VectorClock vc5;
+
+  DRD_(vc_init)(&vc1, vc1elem, sizeof(vc1elem)/sizeof(vc1elem[0]));
+  DRD_(vc_init)(&vc2, vc2elem, sizeof(vc2elem)/sizeof(vc2elem[0]));
+  DRD_(vc_init)(&vc3, 0, 0);
+  DRD_(vc_init)(&vc4, vc4elem, sizeof(vc4elem)/sizeof(vc4elem[0]));
+  DRD_(vc_init)(&vc5, vc5elem, sizeof(vc5elem)/sizeof(vc5elem[0]));
+
+  DRD_(vc_combine)(&vc3, &vc1);
+  DRD_(vc_combine)(&vc3, &vc2);
+
+  fprintf(stderr, "vc1: %s", (str = DRD_(vc_aprint)(&vc1)));
+  free(str);
+  fprintf(stderr, "\nvc2: %s", (str = DRD_(vc_aprint)(&vc2)));
+  free(str);
+  fprintf(stderr, "\nvc3: %s", (str = DRD_(vc_aprint)(&vc3)));
+  free(str);
+  fprintf(stderr, "\n");
+  fprintf(stderr, "vc_lte(vc1, vc2) = %d, vc_lte(vc1, vc3) = %d,"
+          " vc_lte(vc2, vc3) = %d\nvc_lte(",
+          DRD_(vc_lte)(&vc1, &vc2), DRD_(vc_lte)(&vc1, &vc3),
+          DRD_(vc_lte)(&vc2, &vc3));
+  fprintf(stderr, "%s", (str = DRD_(vc_aprint)(&vc4)));
+  free(str);
+  fprintf(stderr, ", ");
+  fprintf(stderr, "%s", (str = DRD_(vc_aprint)(&vc5)));
+  free(str);
+  fprintf(stderr, ") = %d sw %d\n",
+          DRD_(vc_lte)(&vc4, &vc5), DRD_(vc_lte)(&vc5, &vc4));
+
+  for (i = 0; i < 64; i++)
+    DRD_(vc_reserve)(&vc1, i);
+  for (i = 64; i > 0; i--)
+    DRD_(vc_reserve)(&vc1, i);
+
+  DRD_(vc_cleanup)(&vc1);
+  DRD_(vc_cleanup)(&vc2);
+  DRD_(vc_cleanup)(&vc3);
+}
+
+int main(int argc, char** argv)
+{
+  vc_unittest();
+  return 0;
+}
diff --git a/drd/tests/unit_vc.stderr.exp b/drd/tests/unit_vc.stderr.exp
new file mode 100644
index 0000000..484cfc4
--- /dev/null
+++ b/drd/tests/unit_vc.stderr.exp
@@ -0,0 +1,5 @@
+vc1: [ 3: 7, 5: 8 ]
+vc2: [ 1: 4, 3: 9 ]
+vc3: [ 1: 4, 3: 9, 5: 8 ]
+vc_lte(vc1, vc2) = 0, vc_lte(vc1, vc3) = 1, vc_lte(vc2, vc3) = 1
+vc_lte([ 1: 3, 2: 1 ], [ 1: 4 ]) = 0 sw 0
diff --git a/drd/tests/unit_vc.vgtest b/drd/tests/unit_vc.vgtest
new file mode 100644
index 0000000..c044696
--- /dev/null
+++ b/drd/tests/unit_vc.vgtest
@@ -0,0 +1,3 @@
+prog: unit_vc
+args:
+vgopts: -q --tool=memcheck --leak-check=full --show-reachable=yes