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=<n></literal> and
+<literal>--shared-threshold=<n></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><valgrind/drd.h></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(&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>&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(&x)</literal>. Trace all
+ load and store activity that touches at least the single byte at the
+ address <literal>&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><valgrind/drd.h></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, ¶m));
+ 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