Hello community,
here is the log from the commit of package valgrind
checked in at Tue Aug 29 00:13:07 CEST 2006.
--------
--- valgrind/valgrind.changes 2006-08-24 14:52:54.000000000 +0200
+++ valgrind/valgrind.changes 2006-08-28 13:37:24.000000000 +0200
@@ -1,0 +2,6 @@
+Mon Aug 28 13:37:11 CEST 2006 - dmueller@suse.de
+
+- fix suppressions
+- update drd plugin
+
+-------------------------------------------------------------------
Old:
----
valgrind-5999-drd-2006-08-14.tar.bz2
valgrind-5999.patch
New:
----
valgrind-6012-drd-2006-08-26.tar.bz2
valgrind-6012.patch
valgrind-ppc.diff
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ valgrind.spec ++++++
--- /var/tmp/diff_new_pack.fJdC20/_old 2006-08-29 00:13:00.000000000 +0200
+++ /var/tmp/diff_new_pack.fJdC20/_new 2006-08-29 00:13:00.000000000 +0200
@@ -11,7 +11,7 @@
# norootforbuild
Name: valgrind
-BuildRequires: gcc-c++ glibc-devel-32bit
+BuildRequires: gcc-c++ glibc-devel-32bit xorg-x11-devel
%ifarch x86_64
BuildRequires: gcc41-32bit
%endif
@@ -21,16 +21,17 @@
Summary: Memory Management Debugger
BuildRoot: %{_tmppath}/%{name}-%{version}-build
Version: 3.2.0
-Release: 6
+Release: 7
Source0: %{name}-%{version}.tar.bz2
# svn di svn://svn.valgrind.org/valgrind/tags/VALGRIND_3_1_0 svn://svn.valgrind.org/valgrind/branches/VALGRIND_3_1_BRANCH > 3_1_BRANCH.diff
# svn di svn://svn.valgrind.org/vex/tags/VEX_3_1_0 svn://svn.valgrind.org/vex/branches/VEX_3_1_BRANCH > VEX_3_1_BRANCH.diff
#Patch0: 3_1_BRANCH.diff
#Patch1: VEX_3_1_BRANCH.diff
-Source1: valgrind-5999-drd-2006-08-14.tar.bz2
+Source1: valgrind-6012-drd-2006-08-26.tar.bz2
Patch2: multibyte-nop.diff
-Patch3: valgrind-5999.patch
+Patch3: valgrind-6012.patch
Patch4: drd-fixes.diff
+Patch5: valgrind-ppc.diff
Provides: callgrind
Obsoletes: callgrind
ExclusiveArch: %ix86 x86_64 ppc ppc64
@@ -78,13 +79,14 @@
%patch2
%patch3
%patch4
+%patch5
%build
export CFLAGS="$RPM_OPT_FLAGS"
export CXXFLAGS="$RPM_OPT_FLAGS"
autoreconf -fi
export GDB=/usr/bin/gdb
-%configure --with-x
+%configure
make %{?jobs:-j%jobs}
%install
@@ -102,6 +104,9 @@
%doc %_mandir/*/*
%changelog -n valgrind
+* Mon Aug 28 2006 - dmueller@suse.de
+- fix suppressions
+- update drd plugin
* Thu Aug 24 2006 - dmueller@suse.de
- add experimental drd plugin
- fix build on x86_64
++++++ drd-fixes.diff ++++++
--- /var/tmp/diff_new_pack.fJdC20/_old 2006-08-29 00:13:00.000000000 +0200
+++ /var/tmp/diff_new_pack.fJdC20/_new 2006-08-29 00:13:00.000000000 +0200
@@ -1,20 +1,20 @@
---- drd/drd_malloc_wrappers.c 2006/08/23 13:43:15 1.1
-+++ drd/drd_malloc_wrappers.c 2006/08/23 13:43:56
-@@ -263,6 +263,8 @@
- SizeT* const size,
- ExeContext** const where)
- {
-+ return False;
-+
- DRD_Chunk* mc;
+--- drd/drd_main.c
++++ drd/drd_main.c
+@@ -110,7 +110,7 @@
+ addr, size, VG_(get_running_tid)());
+ }
+ #endif
+- sg = thread_get_segment(VG_(running_tid));
++ sg = thread_get_segment(VG_(get_running_tid)());
+ bm_access_range(sg->bm, addr, size, eLoad);
+ }
- tl_assert(data);
-@@ -289,6 +291,8 @@
+@@ -124,7 +124,7 @@
+ addr, size, VG_(get_running_tid)());
+ }
+ #endif
+- sg = thread_get_segment(VG_(running_tid));
++ sg = thread_get_segment(VG_(get_running_tid)());
+ bm_access_range(sg->bm, addr, size, eStore);
+ }
- void drd_print_malloc_stats(void)
- {
-+ return;
-+
- DRD_Chunk* mc;
- SizeT nblocks = 0;
- SizeT nbytes = 0;
++++++ valgrind-5999-drd-2006-08-14.tar.bz2 -> valgrind-6012-drd-2006-08-26.tar.bz2 ++++++
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/drd/Makefile.am new/drd/Makefile.am
--- old/drd/Makefile.am 2006-08-14 15:40:44.000000000 +0200
+++ new/drd/Makefile.am 2006-08-26 15:30:09.000000000 +0200
@@ -2,66 +2,28 @@
noinst_PROGRAMS =
if VG_X86_LINUX
- noinst_PROGRAMS += drd-x86-linux vgpreload_drd-x86-linux.so
+ noinst_PROGRAMS += drd-x86-linux
PLATFORM = X86
endif
if VG_AMD64_LINUX
- noinst_PROGRAMS += drd-amd64-linux vgpreload_drd-amd64-linux.so
+ noinst_PROGRAMS += drd-amd64-linux
PLATFORM = AMD64
endif
if VG_PPC32_LINUX
- noinst_PROGRAMS += drd-ppc32-linux vgpreload_drd-ppc32-linux.so
+ noinst_PROGRAMS += drd-ppc32-linux
PLATFORM = PPC32
endif
if VG_PPC64_LINUX
-noinst_PROGRAMS += drd-ppc64-linux vgpreload_drd-ppc64-linux.so
+ noinst_PROGRAMS += drd-ppc64-linux
+ PLATFORM = PPC64
endif
-VGPRELOAD_DRD_SOURCES_COMMON =
-
-vgpreload_drd_x86_linux_so_SOURCES = $(VGPRELOAD_DRD_SOURCES_COMMON)
-vgpreload_drd_x86_linux_so_CPPFLAGS = $(AM_CPPFLAGS_X86_LINUX)
-vgpreload_drd_x86_linux_so_CFLAGS = $(AM_CFLAGS_X86_LINUX) $(AM_CFLAGS_PIC) -O2
-vgpreload_drd_x86_linux_so_CCASFLAGS = $(AM_CCASFLAGS_X86_LINUX)
-vgpreload_drd_x86_linux_so_DEPENDENCIES = $(LIBREPLACEMALLOC_X86_LINUX)
-vgpreload_drd_x86_linux_so_LDFLAGS = \
- $(PRELOAD_LDFLAGS_X86_LINUX) \
- $(LIBREPLACEMALLOC_LDFLAGS_X86_LINUX)
-
-vgpreload_drd_amd64_linux_so_SOURCES = $(VGPRELOAD_DRD_SOURCES_COMMON)
-vgpreload_drd_amd64_linux_so_CPPFLAGS = $(AM_CPPFLAGS_AMD64_LINUX)
-vgpreload_drd_amd64_linux_so_CFLAGS = $(AM_CFLAGS_AMD64_LINUX) $(AM_CFLAGS_PIC) -O2
-vgpreload_drd_amd64_linux_so_CCASFLAGS = $(AM_CCASFLAGS_AMD64_LINUX)
-vgpreload_drd_amd64_linux_so_DEPENDENCIES = $(LIBREPLACEMALLOC_AMD64_LINUX)
-vgpreload_drd_amd64_linux_so_LDFLAGS = \
- $(PRELOAD_LDFLAGS_AMD64_LINUX) \
- $(LIBREPLACEMALLOC_LDFLAGS_AMD64_LINUX)
-
-vgpreload_drd_ppc32_linux_so_SOURCES = $(VGPRELOAD_DRD_SOURCES_COMMON)
-vgpreload_drd_ppc32_linux_so_CPPFLAGS = $(AM_CPPFLAGS_PPC32_LINUX)
-vgpreload_drd_ppc32_linux_so_CFLAGS = $(AM_CFLAGS_PPC32_LINUX) $(AM_CFLAGS_PIC) -O2
-vgpreload_drd_ppc32_linux_so_CCASFLAGS = $(AM_CCASFLAGS_PPC32_LINUX)
-vgpreload_drd_ppc32_linux_so_DEPENDENCIES = $(LIBREPLACEMALLOC_PPC32_LINUX)
-vgpreload_drd_ppc32_linux_so_LDFLAGS = \
- $(PRELOAD_LDFLAGS_PPC32_LINUX) \
- $(LIBREPLACEMALLOC_LDFLAGS_PPC32_LINUX)
-
-vgpreload_drd_ppc64_linux_so_SOURCES = $(VGPRELOAD_DRD_SOURCES_COMMON)
-vgpreload_drd_ppc64_linux_so_CPPFLAGS = $(AM_CPPFLAGS_PPC64_LINUX)
-vgpreload_drd_ppc64_linux_so_CFLAGS = $(AM_CFLAGS_PPC64_LINUX) $(AM_CFLAGS_PIC) -O2
-vgpreload_drd_ppc64_linux_so_CCASFLAGS = $(AM_CCASFLAGS_PPC64_LINUX)
-vgpreload_drd_ppc64_linux_so_DEPENDENCIES = $(LIBREPLACEMALLOC_PPC64_LINUX)
-vgpreload_drd_ppc64_linux_so_LDFLAGS = \
- $(PRELOAD_LDFLAGS_PPC64_LINUX) \
- $(LIBREPLACEMALLOC_LDFLAGS_PPC64_LINUX)
-
DRD_SOURCES_COMMON = \
drd_bitmap3.c \
drd_clientreq.c \
drd_error.c \
drd_main.c \
- drd_malloc_wrappers.c \
drd_mutex.c \
drd_segment.c \
drd_suppression.c \
@@ -71,6 +33,7 @@
AM_CFLAGS_X86_LINUX += -DCHECK_FORMAT_STRINGS -I$(top_srcdir)/coregrind
AM_CFLAGS_AMD64_LINUX += -DCHECK_FORMAT_STRINGS -I$(top_srcdir)/coregrind
AM_CFLAGS_PPC32_LINUX += -DCHECK_FORMAT_STRINGS -I$(top_srcdir)/coregrind
+AM_CFLAGS_PPC64_LINUX += -DCHECK_FORMAT_STRINGS -I$(top_srcdir)/coregrind
drd_x86_linux_SOURCES = $(DRD_SOURCES_COMMON)
drd_x86_linux_CPPFLAGS = $(AM_CPPFLAGS_$(PLATFORM)_LINUX)
@@ -92,3 +55,10 @@
drd_ppc32_linux_DEPENDENCIES = $(COREGRIND_LIBS_$(PLATFORM)_LINUX)
drd_ppc32_linux_LDADD = $(TOOL_LDADD_$(PLATFORM)_LINUX)
drd_ppc32_linux_LDFLAGS = $(TOOL_LDFLAGS_$(PLATFORM)_LINUX)
+
+drd_ppc64_linux_SOURCES = $(DRD_SOURCES_COMMON)
+drd_ppc64_linux_CPPFLAGS = $(AM_CPPFLAGS_$(PLATFORM)_LINUX)
+drd_ppc64_linux_CFLAGS = $(AM_CFLAGS_$(PLATFORM)_LINUX)
+drd_ppc64_linux_DEPENDENCIES = $(COREGRIND_LIBS_$(PLATFORM)_LINUX)
+drd_ppc64_linux_LDADD = $(TOOL_LDADD_$(PLATFORM)_LINUX)
+drd_ppc64_linux_LDFLAGS = $(TOOL_LDFLAGS_$(PLATFORM)_LINUX)
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/drd/TODO.txt new/drd/TODO.txt
--- old/drd/TODO.txt 2006-08-14 18:41:16.000000000 +0200
+++ new/drd/TODO.txt 2006-08-26 17:56:08.000000000 +0200
@@ -14,14 +14,23 @@
- testing on PPC (current implementation is only tested on x86 yet).
- Replace representation of suppression ranges as a list of ranges by a
bitmap.
+- Potential optimization: don't keep any bitmaps if only one thread is running.
Known bugs:
+- valgrind --tool=drd none/tests/pth_cvsimple triggers an assertion failure.
- Gets killed by the OOM handler for some applications.
+- drd_malloc_wrappers.c: when data addresses are reused because of a
+ malloc()/free()/malloc() sequence, the reported allocation stack will be
+ wrong.
+
+Valgrind core changes
+~~~~~~~~~~~~~~~~~~~~~
+- Explain each of the changes, and submit them as a patch. Especially explain
+ why the change in the thread state handling is necessary.
Error reporting
~~~~~~~~~~~~~~~
-- better error reporting for stack variables -- currently only an address is
- printed when a data race is detected for a stack variable, and no name.
+- Make sure that Valgrind counts data races reported by drd as errors.
Testing
~~~~~~~
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/drd/drd_bitmap.h new/drd/drd_bitmap.h
--- old/drd/drd_bitmap.h 2006-08-14 14:30:22.000000000 +0200
+++ new/drd/drd_bitmap.h 2006-08-26 14:26:04.000000000 +0200
@@ -60,9 +60,6 @@
Addr address,
SizeT size,
enum bm_access_type access_type);
-void bm_access_1(struct bitmap* bm,
- Addr address,
- enum bm_access_type access_type);
void bm_access_4(struct bitmap* bm,
Addr address,
enum bm_access_type access_type);
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/drd/drd_bitmap3.c new/drd/drd_bitmap3.c
--- old/drd/drd_bitmap3.c 2006-08-14 16:45:00.000000000 +0200
+++ new/drd/drd_bitmap3.c 2006-08-26 14:33:07.000000000 +0200
@@ -88,28 +88,10 @@
}
/**
- * Record an access of type access_type at addresses a .. a + size - 1 in
- * bitmap bm.
- */
-void bm_access_range(struct bitmap* const bm,
- Addr const a,
- SizeT const size,
- enum bm_access_type access_type)
-{
- Addr b;
-
- tl_assert(bm);
- tl_assert(0 < size && size < 4096);
-
- for (b = a; b != a + size; b++)
- {
- bm_access_1(bm, b, access_type);
- }
-}
-
-/**
* Record an access of type access_type at addresses a in bitmap bm.
*/
+static
+__inline__
void bm_access_1(struct bitmap* bm,
Addr a, enum bm_access_type access_type)
{
@@ -118,7 +100,7 @@
unsigned* p0;
SPLIT_ADDRESS(a);
- tl_assert(bm);
+ // tl_assert(bm);
p2 = &bm->bm2[a2];
if (*p2 == 0)
@@ -136,7 +118,31 @@
void bm_access_4(struct bitmap* bm,
Addr a, enum bm_access_type access_type)
{
- bm_access_range(bm, a, 4, access_type);
+ tl_assert(bm);
+ bm_access_1(bm, a + 0, access_type);
+ bm_access_1(bm, a + 1, access_type);
+ bm_access_1(bm, a + 2, access_type);
+ bm_access_1(bm, a + 3, access_type);
+}
+
+/**
+ * Record an access of type access_type at addresses a .. a + size - 1 in
+ * bitmap bm.
+ */
+void bm_access_range(struct bitmap* const bm,
+ Addr const a,
+ SizeT const size,
+ enum bm_access_type access_type)
+{
+ Addr b;
+
+ tl_assert(bm);
+ tl_assert(0 < size && size < 4096);
+
+ for (b = a; b != a + size; b++)
+ {
+ bm_access_1(bm, b, access_type);
+ }
}
/**
@@ -240,7 +246,7 @@
unsigned range_access = 0;
unsigned i;
- VG_(message)(Vg_UserMsg, "Actual data races:");
+ VG_(message)(Vg_UserMsg, "Data addresses accessed by both segments:");
for (i = 0; i < ADDR2_COUNT; i++)
{
@@ -271,6 +277,7 @@
range_end = a + 1;
else
{
+ tl_assert(range_begin < range_end);
if (HAS_RACE(range_access)
&& ! drd_is_suppressed(range_begin, range_end))
{
@@ -280,11 +287,16 @@
dri.range_begin = range_begin;
dri.range_end = range_end;
dri.range_access = range_access;
+ tl_assert(dri.range_begin < dri.range_end);
+#if 0
VG_(maybe_record_error)(tid1,
DataRaceErr,
VG_(get_IP)(tid1), // where
"data race",
&dri);
+#else
+ drd_report_data_race(&dri);
+#endif
}
range_access = access;
range_begin = a;
@@ -297,7 +309,7 @@
}
}
- VG_(message)(Vg_UserMsg, "End of detected data races");
+ // VG_(message)(Vg_UserMsg, "End of detected data races");
}
void bm_print(struct bitmap const* bm)
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/drd/drd_error.c new/drd/drd_error.c
--- old/drd/drd_error.c 2006-08-14 15:03:01.000000000 +0200
+++ new/drd/drd_error.c 2006-08-26 14:41:21.000000000 +0200
@@ -39,10 +39,10 @@
// See also memcheck/mc_main.c
-/* Describe a data address as good as you can, for error messages,
+/* Describe a data address range [a,a+len[ as good as you can, for error messages,
putting the result in ai. */
// See also memcheck/mc_main.c
-void describe_addr(Addr a, AddrInfo* ai)
+void describe_addr(Addr const a, SizeT const len, AddrInfo* const ai)
{
ThreadId tid;
Addr stack_min, stack_max;
@@ -55,7 +55,10 @@
if (stack_min <= a && a <= stack_max)
{
ai->akind = Stack;
+ ai->size = len;
+ ai->rwoffset = 0;
ai->stack_tid = tid;
+ tl_assert(a + ai->size <= stack_max);
return;
}
}
@@ -64,20 +67,71 @@
sg = VG_(find_seginfo)(a);
if (sg)
{
+ int i, n;
+
ai->akind = Segment;
ai->seginfo = sg;
+ ai->name[0] = 0;
+
+ n = VG_(seginfo_syms_howmany)(sg);
+ for (i = 0; i < n; i++)
+ {
+ Addr addr;
+ UInt size;
+ HChar* name;
+ Char filename[256];
+ Int linenum;
+
+ VG_(seginfo_syms_getidx)(sg, i, &addr, &size, &name);
+ if (addr <= a && a < addr + size)
+ {
+ ai->size = size;
+ ai->rwoffset = a - addr;
+ tl_assert(name && name[0]);
+ VG_(snprintf)(ai->name, sizeof(ai->name), "%s", name);
+ if (VG_(get_filename_linenum)(addr,
+ filename, sizeof(filename),
+ 0, 0, 0,
+ &linenum))
+ {
+ VG_(snprintf)(ai->descr, sizeof(ai->descr),
+ " in %s:%d", filename, linenum);
+ }
+ else
+ {
+ i = n;
+ }
+ break;
+ }
+ }
+ if (i == n)
+ {
+ Char sect_kind_name[16];
+
+ ai->size = 1;
+ ai->rwoffset = 0;
+ VG_(seginfo_sect_kind_name)(a, sect_kind_name,
+ sizeof(sect_kind_name));
+ VG_(snprintf)(ai->descr, sizeof(ai->descr),
+ " %s, %s:%s",
+ VG_(seginfo_filename)(sg),
+ VG_(seginfo_soname)(sg),
+ sect_kind_name);
+ }
return;
}
/* Search for a currently malloc'd block which might bracket it. */
{
+#if 0
Addr data;
- if (drd_heap_addrinfo(a, &data, &ai->blksize, &ai->lastchange))
+ if (drd_heap_addrinfo(a, &data, &ai->size, &ai->lastchange))
{
ai->akind = Mallocd;
ai->rwoffset = a - data;
return;
}
+#endif
}
/* Clueless ... */
@@ -88,14 +142,14 @@
/**
* Generate a description string for the data residing at address a.
*/
-Char* describe_addr_text(Addr const a, AddrInfo* const ai,
+Char* describe_addr_text(Addr const a, SizeT const len, AddrInfo* const ai,
Char* const buf, UInt const n_buf)
{
tl_assert(a);
tl_assert(ai);
tl_assert(buf);
- describe_addr(a, ai);
+ describe_addr(a, len, ai);
switch (ai->akind)
{
@@ -107,70 +161,29 @@
VG_(get_pthread_id)(ai->stack_tid));
break;
case Segment: {
- Char sect_kind_name[16];
- int i, n;
-
- buf[0] = 0;
-
- n = VG_(seginfo_syms_howmany)(ai->seginfo);
- for (i = 0; i < n; i++)
+ if (ai->name[0])
{
- Addr addr;
- UInt size;
- HChar* name;
- VG_(seginfo_syms_getidx)(ai->seginfo, i, &addr, &size, &name);
- if (addr <= a && a < addr + size)
- {
- Char filename[256] = "";
- UInt linenum = 0;
- VG_(snprintf)(buf + VG_(strlen)(buf), n_buf - VG_(strlen)(buf),
- "%s (offset %ld, size %d) in ",
- name, a - addr, size);
- if (VG_(get_filename_linenum)(addr,
- filename, sizeof(filename),
- 0, 0, 0,
- &linenum))
- {
- VG_(snprintf)(buf + VG_(strlen)(buf), n_buf - VG_(strlen)(buf),
- "%s:%d, ",
- filename,
- linenum);
- }
- else
- {
- i = n;
- break;
- }
- break;
- }
+ VG_(snprintf)(buf, n_buf,
+ "%s (offset %ld, size %ld) in %s",
+ ai->name, ai->rwoffset, ai->size, ai->descr);
}
- if (i == n)
+ else
{
- VG_(seginfo_sect_kind_name)(a, sect_kind_name,
- sizeof(sect_kind_name));
- VG_(snprintf)(buf + VG_(strlen)(buf), n_buf - VG_(strlen)(buf),
- "%s, %s:%s",
- VG_(seginfo_filename)(ai->seginfo),
- VG_(seginfo_soname)(ai->seginfo),
- sect_kind_name);
+ VG_(snprintf)(buf, n_buf,
+ "%s",
+ ai->descr);
}
break;
}
case Mallocd: {
- Addr data;
- SizeT size;
- ExeContext* where;
VG_(snprintf)(buf, n_buf, "heap");
- if (drd_heap_addrinfo(a, &data, &size, &where))
- {
- VG_(snprintf)(buf + VG_(strlen)(buf), n_buf - VG_(strlen)(buf),
- ", offset %ld in block at 0x%lx of size %ld",
- a - data, data, size);
- }
+ VG_(snprintf)(buf + VG_(strlen)(buf), n_buf - VG_(strlen)(buf),
+ ", offset %ld in block at 0x%lx of size %ld",
+ ai->rwoffset, a - ai->rwoffset, ai->size);
break;
}
case Unknown:
- VG_(snprintf)(buf, n_buf, "unknown");
+ VG_(snprintf)(buf, n_buf, "heap");
break;
default:
tl_assert(0);
@@ -178,12 +191,40 @@
return buf;
}
+void drd_report_data_race(DataRaceInfo const* const dri)
+{
+ AddrInfo ai;
+ Char descr[256];
+
+ tl_assert(dri);
+ tl_assert(dri->range_begin < dri->range_end);
+ describe_addr_text(dri->range_begin, dri->range_end - dri->range_begin,
+ &ai, descr, sizeof(descr));
+ VG_(message)(Vg_UserMsg,
+ "0x%08lx sz %ld %c %c (%s)",
+ dri->range_begin,
+ dri->range_end - dri->range_begin,
+ dri->range_access & LHS_W ? 'W' : 'R',
+ dri->range_access & RHS_W ? 'W' : 'R',
+ descr);
+ if (ai.akind == Mallocd && ai.lastchange)
+ {
+ VG_(message)(Vg_UserMsg, "Allocation context:");
+ VG_(pp_ExeContext)(ai.lastchange);
+ }
+ // Note: for stack and heap variables suppression should be
+ // stopped automatically as soon as the specified memory
+ // range has been freed.
+ tl_assert(dri->range_begin < dri->range_end);
+ drd_start_suppression(dri->range_begin, dri->range_end);
+}
+
static Bool drd_tool_error_eq(VgRes res, Error* e1, Error* e2)
{
return False;
}
-static void drd_tool_error_pp(Error* e)
+static void drd_tool_error_pp(Error* const e)
{
switch (VG_(get_error_kind)(e))
{
@@ -198,29 +239,7 @@
break;
}
case DataRaceErr: {
- AddrInfo ai;
- DataRaceInfo* dri;
- Char descr[256];
-
- dri = VG_(get_error_extra)(e);
- tl_assert(dri);
- describe_addr_text(dri->range_begin, &ai, descr, sizeof(descr));
- VG_(message)(Vg_UserMsg,
- "0x%08lx sz %ld %c %c (%s)",
- dri->range_begin,
- dri->range_end - dri->range_begin,
- dri->range_access & LHS_W ? 'W' : 'R',
- dri->range_access & RHS_W ? 'W' : 'R',
- descr);
- if (ai.akind == Mallocd && ai.lastchange)
- {
- VG_(message)(Vg_UserMsg, "Allocation context:");
- VG_(pp_ExeContext)(ai.lastchange);
- }
- // Note: for stack and heap variables suppression should be
- // stopped automatically as soon as the specified memory
- // range has been freed.
- drd_start_suppression(dri->range_begin, dri->range_end);
+ drd_report_data_race(VG_(get_error_extra)(e));
break;
}
default:
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/drd/drd_error.h new/drd/drd_error.h
--- old/drd/drd_error.h 2006-08-14 14:53:04.000000000 +0200
+++ new/drd/drd_error.h 2006-08-26 18:01:29.000000000 +0200
@@ -35,8 +35,8 @@
/* DRD error types. */
typedef enum {
- DataRaceErr = 1,
- MutexErr = 2,
+ DataRaceErr = 1,
+ MutexErr = 2,
} DrdErrorKind;
/* The classification of a faulting address. */
@@ -56,13 +56,15 @@
/* Records info about a faulting address. */
typedef
- struct { // Used by:
- AddrKind akind; // ALL
- SizeT blksize; // Mallocd
- OffT rwoffset; // Mallocd
- ExeContext* lastchange; // Mallocd
- ThreadId stack_tid; // Stack
- SegInfo* seginfo; // Segment
+ struct { // Used by:
+ AddrKind akind; // ALL
+ SizeT size; // ALL
+ OffT rwoffset; // ALL
+ ExeContext* lastchange; // Mallocd
+ ThreadId stack_tid; // Stack
+ SegInfo* seginfo; // Segment
+ Char name[256]; // Segment
+ Char descr[256]; // Segment
}
AddrInfo;
@@ -75,9 +77,10 @@
UInt range_access; // How the range was accessed (LHS_[RW] | RHS_[RW]).
} DataRaceInfo;
-void describe_addr(Addr const a, AddrInfo* const ai);
-Char* describe_addr_text(Addr const a, AddrInfo* const ai,
+void describe_addr(Addr const a, SizeT const len, AddrInfo* const ai);
+Char* describe_addr_text(Addr const a, SizeT const len, AddrInfo* const ai,
Char* const buf, UInt const n_buf);
+void drd_report_data_race(DataRaceInfo const* const dri);
void drd_register_error_handlers(void);
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/drd/drd_main.c new/drd/drd_main.c
--- old/drd/drd_main.c 2006-08-14 17:43:23.000000000 +0200
+++ new/drd/drd_main.c 2006-08-26 17:48:27.000000000 +0200
@@ -26,7 +26,9 @@
#include "drd_bitmap.h"
#include "drd_clientreq.h"
#include "drd_error.h"
+#ifdef USE_MALLOC_WRAPPERS
#include "drd_malloc_wrappers.h"
+#endif
#include "drd_mutex.h"
#include "drd_segment.h"
#include "drd_suppression.h"
@@ -101,28 +103,28 @@
VG_REGPARM(2) void drd_trace_load(Addr addr, SizeT size)
{
struct segment* sg;
-
+#if 0
if (drd_trace_mem)
{
VG_(message)(Vg_UserMsg, "load 0x%lx size %ld thread %d",
addr, size, VG_(get_running_tid)());
}
-
- sg = thread_get_segment(VG_(get_running_tid)());
+#endif
+ sg = thread_get_segment(VG_(running_tid));
bm_access_range(sg->bm, addr, size, eLoad);
}
VG_REGPARM(2) void drd_trace_store(Addr addr, SizeT size)
{
struct segment* sg;
-
+#if 0
if (drd_trace_mem)
{
VG_(message)(Vg_UserMsg, "store 0x%lx size %ld thread %d",
addr, size, VG_(get_running_tid)());
}
-
- sg = thread_get_segment(VG_(get_running_tid)());
+#endif
+ sg = thread_get_segment(VG_(running_tid));
bm_access_range(sg->bm, addr, size, eStore);
}
@@ -176,7 +178,8 @@
p = mutex_get(mutex);
if (p)
{
- // To do: report an error in case the recursion count is not zero.
+ // To do: report an error in case the recursion count is not zero
+ // before asserting.
tl_assert(p->recursion_count == 0);
mutex_destroy(p);
}
@@ -327,20 +330,35 @@
{
IRDirty* d = st->Ist.Dirty.details;
IREffect const mFx = d->mFx;
- if (mFx != Ifx_None)
- {
- VG_(message)(Vg_UserMsg,
- "Encountered Ist_Dirty with effect %s addr %p size %d",
- mFx == Ifx_None ? "-"
- : mFx == Ifx_Read ? "R"
- : mFx == Ifx_Write ? "W"
- : mFx == Ifx_Modify ? "RW"
- : "?",
- d->mAddr,
- d->mSize);
+ 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);
+ addStmtToIRBB(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);
+ addStmtToIRBB(bb, IRStmt_Dirty(di));
+ }
+ break;
+ default:
+ tl_assert(0);
}
- // To do: implement handling of Ist_Dirty.
- tl_assert(mFx == Ifx_None);
}
addStmtToIRBB(bb, st);
break;
@@ -403,12 +421,12 @@
// Other stuff.
VG_(needs_data_syms)();
+#ifdef USE_MALLOC_WRAPPERS
drd_register_malloc_wrappers();
+#endif
drd_clientreq_init();
- //VG_(needs_client_requests)(drd_handle_client_request);
-
// Unit tests.
// bm_test();
// vc_test();
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/drd/drd_malloc_wrappers.c new/drd/drd_malloc_wrappers.c
--- old/drd/drd_malloc_wrappers.c 2006-08-14 09:07:00.000000000 +0200
+++ new/drd/drd_malloc_wrappers.c 2006-08-26 17:43:07.000000000 +0200
@@ -1,11 +1,8 @@
/*
- This file is part of drd, a data race detector. Based on
- mc_malloc_wrappers.c, part of MemCheck, a heavyweight Valgrind tool for
- detecting memory errors, and AddrCheck, a lightweight Valgrind tool
- for detecting memory errors.
+ This file is part of drd, a data race detector.
- Copyright (C) 2000-2006 Julian Seward
- jseward@acm.org
+ Copyright (C) 2006 Bart Van Assche
+ bart.vanassche@gmail.com
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -25,7 +22,9 @@
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"
@@ -71,7 +70,7 @@
static
DRD_Chunk* create_DRD_Chunk(ThreadId tid, Addr p, SizeT size)
{
- DRD_Chunk* mc = VG_(malloc)(sizeof(DRD_Chunk));
+ DRD_Chunk* mc = VG_(malloc)(sizeof(DRD_Chunk));
mc->data = p;
mc->size = size;
mc->where = VG_(record_ExeContext)(tid);
@@ -151,7 +150,6 @@
mc = VG_(HT_remove)(drd_malloc_list, (UWord)p );
if (mc == NULL) {
tl_assert(0);
- // drd_record_free_error(tid, p );
} else {
VG_(free)(mc);
}
@@ -190,8 +188,6 @@
mc = VG_(HT_remove)(drd_malloc_list, (UWord)p_old );
if (mc == NULL) {
tl_assert(0);
- // drd_record_free_error(tid, (Addr)p_old );
- /* We return to the program regardless. */
return NULL;
}
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/drd/drd_mutex.c new/drd/drd_mutex.c
--- old/drd/drd_mutex.c 2006-08-12 14:54:06.000000000 +0200
+++ new/drd/drd_mutex.c 2006-08-26 14:25:20.000000000 +0200
@@ -84,16 +84,18 @@
struct mutex_info* p;
p = mutex_get_or_allocate(mutex);
- p->recursion_count++;
- if (p->recursion_count == 1)
+ if (p->recursion_count == 0)
p->owner = tid;
else if (p->owner != tid)
{
- // The impossible happened ...
- VG_(message)(Vg_DebugMsg, "mutex 0x%lx recursion count %d owner %d -> %d",
+ VG_(message)(Vg_DebugMsg,
+ "The impossible happened: mutex 0x%lx is locked"
+ " simultaneously by two threads (recursion count %d,"
+ " owners %d and %d) !",
p->mutex, p->recursion_count, p->owner, tid);
tl_assert(0);
}
+ p->recursion_count++;
return p->recursion_count;
}
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/drd/drd_thread.c new/drd/drd_thread.c
--- old/drd/drd_thread.c 2006-08-14 16:46:26.000000000 +0200
+++ new/drd/drd_thread.c 2006-08-26 13:30:47.000000000 +0200
@@ -44,8 +44,8 @@
typedef struct
{
- struct segment* first;
- struct segment* last;
+ struct segment* first;
+ struct segment* last;
} ThreadInfo;
@@ -62,15 +62,37 @@
// Function definitions.
/**
+ * Sanity check of the doubly linked list of segments referenced by a ThreadInfo struct.
+ * @return True if sane, False if not.
+ */
+static Bool sane_ThreadInfo(ThreadInfo const* const ti)
+{
+ struct 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;
+}
+
+/**
* Allocate thread-specific data structure. Call this just after
* pthread_create(). Assumption: thread id's are small integers.
*/
void thread_new(ThreadId const creator, ThreadId const created)
{
- tl_assert(0 < created && created < MAXTHREADS);
- tl_assert(s_threadinfo[created].first == 0);
- tl_assert(s_threadinfo[created].last == 0);
- thread_append_segment(created, sg_new(creator, created));
+ tl_assert(0 < created && created < MAXTHREADS);
+ tl_assert(s_threadinfo[created].first == 0);
+ tl_assert(s_threadinfo[created].last == 0);
+ thread_append_segment(created, sg_new(creator, created));
}
/**
@@ -79,17 +101,17 @@
*/
void thread_delete(ThreadId const threadid)
{
- struct segment* sg;
- struct segment* sg_prev;
+ struct segment* sg;
+ struct segment* sg_prev;
- tl_assert(0 < threadid && threadid < MAXTHREADS);
- for (sg = s_threadinfo[threadid].last; sg; sg = sg_prev)
- {
- sg_prev = sg->prev;
- sg_delete(sg);
- }
- s_threadinfo[threadid].first = 0;
- s_threadinfo[threadid].last = 0;
+ tl_assert(0 < threadid && threadid < MAXTHREADS);
+ for (sg = s_threadinfo[threadid].last; sg; sg = sg_prev)
+ {
+ sg_prev = sg->prev;
+ sg_delete(sg);
+ }
+ s_threadinfo[threadid].first = 0;
+ s_threadinfo[threadid].last = 0;
}
/**
@@ -97,9 +119,9 @@
*/
struct segment* thread_get_segment(ThreadId const threadid)
{
- tl_assert(0 < threadid && threadid < MAXTHREADS);
- tl_assert(s_threadinfo[threadid].last);
- return s_threadinfo[threadid].last;
+ tl_assert(0 < threadid && threadid < MAXTHREADS);
+ tl_assert(s_threadinfo[threadid].last);
+ return s_threadinfo[threadid].last;
}
/**
@@ -108,11 +130,15 @@
static void thread_append_segment(ThreadId const threadid,
struct segment* const sg)
{
- sg->prev = s_threadinfo[threadid].last;
- sg->next = 0;
- s_threadinfo[threadid].last = sg;
- if (s_threadinfo[threadid].first == 0)
- s_threadinfo[threadid].first = sg;
+ tl_assert(sane_ThreadInfo(&s_threadinfo[threadid]));
+ sg->prev = s_threadinfo[threadid].last;
+ sg->next = 0;
+ if (s_threadinfo[threadid].last)
+ s_threadinfo[threadid].last->next = sg;
+ s_threadinfo[threadid].last = sg;
+ if (s_threadinfo[threadid].first == 0)
+ s_threadinfo[threadid].first = sg;
+ tl_assert(sane_ThreadInfo(&s_threadinfo[threadid]));
}
/**
@@ -122,22 +148,24 @@
static void thread_discard_segment(ThreadId const threadid,
struct segment* const sg)
{
- if (sg->prev)
- sg->prev->next = sg->next;
- if (sg->next)
- sg->next->prev = sg->prev;
- if (sg == s_threadinfo[threadid].first)
- s_threadinfo[threadid].first = sg->next;
- if (sg == s_threadinfo[threadid].last)
- s_threadinfo[threadid].last = sg->prev;
- sg_delete(sg);
+ tl_assert(sane_ThreadInfo(&s_threadinfo[threadid]));
+ if (sg->prev)
+ sg->prev->next = sg->next;
+ if (sg->next)
+ sg->next->prev = sg->prev;
+ if (sg == s_threadinfo[threadid].first)
+ s_threadinfo[threadid].first = sg->next;
+ if (sg == s_threadinfo[threadid].last)
+ s_threadinfo[threadid].last = sg->prev;
+ sg_delete(sg);
+ tl_assert(sane_ThreadInfo(&s_threadinfo[threadid]));
}
struct vectorclock* thread_get_vc(ThreadId const threadid)
{
- tl_assert(0 < threadid && threadid < MAXTHREADS);
- tl_assert(s_threadinfo[threadid].last);
- return &s_threadinfo[threadid].last->vc;
+ tl_assert(0 < threadid && threadid < MAXTHREADS);
+ tl_assert(s_threadinfo[threadid].last);
+ return &s_threadinfo[threadid].last->vc;
}
/**
@@ -147,50 +175,50 @@
*/
static void thread_compute_minimum_vc(struct vectorclock* vc)
{
- int i;
- Bool first;
- struct segment* latest_sg;
-
- first = True;
- for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
- {
- latest_sg = s_threadinfo[i].last;
- if (latest_sg)
- {
- if (first)
+ int i;
+ Bool first;
+ struct segment* latest_sg;
+
+ first = True;
+ for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
+ {
+ latest_sg = s_threadinfo[i].last;
+ if (latest_sg)
{
- vc_cleanup(vc);
- vc_copy(vc, &latest_sg->vc);
+ if (first)
+ {
+ vc_cleanup(vc);
+ vc_copy(vc, &latest_sg->vc);
+ }
+ else
+ vc_min(vc, &latest_sg->vc);
+ first = False;
}
- else
- vc_min(vc, &latest_sg->vc);
- first = False;
- }
- }
+ }
}
static void thread_compute_maximum_vc(struct vectorclock* vc)
{
- int i;
- Bool first;
- struct segment* latest_sg;
-
- first = True;
- for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
- {
- latest_sg = s_threadinfo[i].last;
- if (latest_sg)
- {
- if (first)
+ int i;
+ Bool first;
+ struct segment* latest_sg;
+
+ first = True;
+ for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
+ {
+ latest_sg = s_threadinfo[i].last;
+ if (latest_sg)
{
- vc_cleanup(vc);
- vc_copy(vc, &latest_sg->vc);
+ if (first)
+ {
+ vc_cleanup(vc);
+ vc_copy(vc, &latest_sg->vc);
+ }
+ else
+ vc_combine(vc, &latest_sg->vc);
+ first = False;
}
- else
- vc_combine(vc, &latest_sg->vc);
- first = False;
- }
- }
+ }
}
/**
@@ -200,134 +228,134 @@
*/
static void thread_discard_ordered_segments(void)
{
- struct vectorclock thread_vc_min;
- int i;
+ struct vectorclock thread_vc_min;
+ int i;
- vc_init(&thread_vc_min, 0, 0);
- thread_compute_minimum_vc(&thread_vc_min);
- if (sg_get_trace())
- {
- char msg[256];
- struct vectorclock thread_vc_max;
-
- vc_init(&thread_vc_max, 0, 0);
- thread_compute_maximum_vc(&thread_vc_max);
- VG_(snprintf)(msg, sizeof(msg),
- "Discarding ordered segments -- min vc is ");
- vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
- &thread_vc_min);
- VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
- ", max vc is ");
- vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
- &thread_vc_max);
- VG_(message)(Vg_DebugMsg, "%s", msg);
- vc_cleanup(&thread_vc_max);
- }
-
- for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
- {
- struct segment* sg;
- struct segment* sg_next;
- for (sg = s_threadinfo[i].first;
- sg && (sg_next = sg->next) && vc_lte(&sg->vc, &thread_vc_min);
- sg = sg_next)
- {
-#if 1
- VG_(printf)("Discarding a segment of thread %d: ", i);
- vc_print(&sg->vc);
- VG_(printf)("\n");
+ vc_init(&thread_vc_min, 0, 0);
+ thread_compute_minimum_vc(&thread_vc_min);
+ if (sg_get_trace())
+ {
+ char msg[256];
+ struct vectorclock thread_vc_max;
+
+ vc_init(&thread_vc_max, 0, 0);
+ thread_compute_maximum_vc(&thread_vc_max);
+ VG_(snprintf)(msg, sizeof(msg),
+ "Discarding ordered segments -- min vc is ");
+ vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
+ &thread_vc_min);
+ VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
+ ", max vc is ");
+ vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
+ &thread_vc_max);
+ VG_(message)(Vg_DebugMsg, "%s", msg);
+ vc_cleanup(&thread_vc_max);
+ }
+
+ for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
+ {
+ struct segment* sg;
+ struct segment* sg_next;
+ for (sg = s_threadinfo[i].first;
+ sg && (sg_next = sg->next) && vc_lte(&sg->vc, &thread_vc_min);
+ sg = sg_next)
+ {
+#if 0
+ VG_(printf)("Discarding a segment of thread %d: ", i);
+ vc_print(&sg->vc);
+ VG_(printf)("\n");
#endif
- thread_discard_segment(i, sg);
- }
- }
- vc_cleanup(&thread_vc_min);
+ thread_discard_segment(i, sg);
+ }
+ }
+ vc_cleanup(&thread_vc_min);
}
void thread_new_segment(ThreadId const threadid)
{
- static int s_calls_since_last_discard = 0;
- struct segment* sg;
+ static int s_calls_since_last_discard = 0;
+ struct segment* sg;
- tl_assert(0 < threadid && threadid < MAXTHREADS);
+ tl_assert(0 < threadid && threadid < MAXTHREADS);
- if (s_threadinfo[threadid].last)
- {
- thread_report_races_segment(threadid, s_threadinfo[threadid].last);
- }
-
- sg = sg_new(threadid, threadid);
- thread_append_segment(threadid, sg);
-
- if (++s_calls_since_last_discard > 16)
- {
- s_calls_since_last_discard = 0;
- thread_discard_ordered_segments();
- }
+ if (s_threadinfo[threadid].last)
+ {
+ thread_report_races_segment(threadid, s_threadinfo[threadid].last);
+ }
+
+ sg = sg_new(threadid, threadid);
+ thread_append_segment(threadid, sg);
+
+ // if (++s_calls_since_last_discard > 16)
+ {
+ s_calls_since_last_discard = 0;
+ thread_discard_ordered_segments();
+ }
}
void thread_combine_vc(ThreadId joiner, ThreadId joinee)
{
- tl_assert(joiner != joinee);
- tl_assert(0 < joiner && joiner < MAXTHREADS);
- tl_assert(0 < joinee && joinee < MAXTHREADS);
- tl_assert(s_threadinfo[joiner].last);
- tl_assert(s_threadinfo[joinee].last);
- vc_combine(&s_threadinfo[joiner].last->vc, &s_threadinfo[joinee].last->vc);
- thread_discard_ordered_segments();
+ tl_assert(joiner != joinee);
+ tl_assert(0 < joiner && joiner < MAXTHREADS);
+ tl_assert(0 < joinee && joinee < MAXTHREADS);
+ tl_assert(s_threadinfo[joiner].last);
+ tl_assert(s_threadinfo[joinee].last);
+ vc_combine(&s_threadinfo[joiner].last->vc, &s_threadinfo[joinee].last->vc);
+ thread_discard_ordered_segments();
}
void thread_print_all(void)
{
- unsigned i;
- struct segment* p;
+ unsigned i;
+ struct segment* p;
- for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
- {
- if (s_threadinfo[i].first)
- {
- VG_(printf)("**************\n"
- "* thread %2d *\n"
- "**************\n",
- i);
- for (p = s_threadinfo[i].first; p; p = p->next)
+ for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
+ {
+ if (s_threadinfo[i].first)
{
- sg_print(p);
+ VG_(printf)("**************\n"
+ "* thread %2d *\n"
+ "**************\n",
+ i);
+ for (p = s_threadinfo[i].first; p; p = p->next)
+ {
+ sg_print(p);
+ }
}
- }
- }
+ }
}
static void show_call_stack(ThreadId const tid,
Char const* const msg,
ExeContext* const callstack)
{
- VG_(message)(Vg_UserMsg,
- "%s (VG t %d, kernel t %d, POSIX t %d)",
- msg,
- tid,
- VG_(get_tid_lwp)(tid),
- VG_(get_pthread_id)(tid));
- if (callstack)
- {
- VG_(pp_ExeContext)(callstack);
- }
- else
- {
- VG_(get_and_pp_StackTrace)(tid, 32/*n_ips*/);
- }
- VG_(message)(Vg_UserMsg, " ");
+ VG_(message)(Vg_UserMsg,
+ "%s (VG t %d, kernel t %d, POSIX t %d)",
+ msg,
+ tid,
+ VG_(get_tid_lwp)(tid),
+ VG_(get_pthread_id)(tid));
+ if (callstack)
+ {
+ VG_(pp_ExeContext)(callstack);
+ }
+ else
+ {
+ VG_(get_and_pp_StackTrace)(tid, 32/*n_ips*/);
+ }
+ VG_(message)(Vg_UserMsg, " ");
}
void thread_report_races(ThreadId const threadid)
{
- struct segment* p;
+ struct segment* p;
- tl_assert(0 < threadid && threadid < MAXTHREADS);
+ tl_assert(0 < threadid && threadid < MAXTHREADS);
- for (p = s_threadinfo[threadid].first; p; p = p->next)
- {
- thread_report_races_segment(threadid, p);
- }
+ for (p = s_threadinfo[threadid].first; p; p = p->next)
+ {
+ thread_report_races_segment(threadid, p);
+ }
}
/**
@@ -337,68 +365,74 @@
void thread_report_races_segment(ThreadId const threadid,
struct segment* const p)
{
- unsigned i;
+ unsigned i;
- tl_assert(0 < threadid && threadid < MAXTHREADS);
- tl_assert(p);
+ tl_assert(0 < threadid && threadid < MAXTHREADS);
+ tl_assert(p);
- for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
- {
- if (i != threadid)
- {
- struct segment* q;
- for (q = s_threadinfo[i].last; q; q = q->prev)
+ for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
+ {
+ if (i != threadid)
{
+ struct segment* q;
+ for (q = s_threadinfo[i].last; q; q = q->prev)
+ {
#if 0
- char msg[256];
- VG_(snprintf)(msg, sizeof(msg), "Examining thread %d (vc ", threadid);
- vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
- &p->vc);
- VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
- ") versus thread %d (vc ", i);
- vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
- &q->vc);
- VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
- ") %d %d",
- vc_lte(&p->vc, &q->vc), vc_lte(&q->vc, &p->vc));
- VG_(message)(Vg_DebugMsg, "%s", msg);
+ char msg[256];
+ VG_(snprintf)(msg, sizeof(msg), "Examining thread %d (vc ", threadid);
+ vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
+ &p->vc);
+ VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
+ ") versus thread %d (vc ", i);
+ vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
+ &q->vc);
+ VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
+ ") %d %d",
+ vc_lte(&p->vc, &q->vc), vc_lte(&q->vc, &p->vc));
+ VG_(message)(Vg_DebugMsg, "%s", msg);
#endif
- // 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 (vc_lte(&q->vc, &p->vc))
- break;
- if (! vc_lte(&p->vc, &q->vc))
- {
- if (bm_has_races(p->bm, q->bm))
- {
- VG_(message)(Vg_UserMsg, "Detected data races. Context:");
- tl_assert(p->stacktrace);
- show_call_stack(threadid, "1st segment start", p->stacktrace);
- show_call_stack(threadid, "1st segment end",
- p->next ? p->next->stacktrace : 0);
- tl_assert(q->stacktrace);
- show_call_stack(i, "2nd segment start", q->stacktrace);
- show_call_stack(i, "2nd segment end",
- q->next ? q->next->stacktrace : 0);
- bm_report_races(threadid, i, p->bm, q->bm);
- }
- }
+ // 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 (vc_lte(&q->vc, &p->vc))
+ break;
+ if (! vc_lte(&p->vc, &q->vc))
+ {
+ if (bm_has_races(p->bm, q->bm))
+ {
+ VG_(message)(Vg_UserMsg, "----------------------------------------------------------------------");
+ tl_assert(p->stacktrace);
+ show_call_stack(threadid, "1st segment start", p->stacktrace);
+ show_call_stack(threadid, "1st segment end",
+ p->next ? p->next->stacktrace : 0);
+ tl_assert(q->stacktrace);
+ show_call_stack(i, "2nd segment start", q->stacktrace);
+ show_call_stack(i, "2nd segment end",
+ q->next ? q->next->stacktrace : 0);
+ bm_report_races(threadid, i, p->bm, q->bm);
+ }
+ }
+ }
}
- }
- }
+ }
}
void thread_report_all_races(void)
{
- unsigned i;
+ unsigned i;
- for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
- {
- if (s_threadinfo[i].last)
- {
- thread_report_races(i);
- }
- }
+ for (i = 0; i < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); i++)
+ {
+ if (s_threadinfo[i].last)
+ {
+ thread_report_races(i);
+ }
+ }
}
+
+/*
+ * Local variables:
+ * c-basic-offset: 3
+ * End:
+ */
++++++ valgrind-5999.patch -> valgrind-6012.patch ++++++
--- valgrind/valgrind-5999.patch 2006-08-24 14:43:08.000000000 +0200
+++ valgrind/valgrind-6012.patch 2006-08-26 18:06:22.000000000 +0200
@@ -1,6 +1,6 @@
Index: helgrind/hg_main.c
===================================================================
---- helgrind/hg_main.c (revision 5999)
+--- helgrind/hg_main.c (revision 6012)
+++ helgrind/hg_main.c (working copy)
@@ -2857,17 +2857,17 @@
/* Do nothing */
@@ -58,7 +58,7 @@
/*--------------------------------------------------------------------*/
Index: include/pub_tool_tooliface.h
===================================================================
---- include/pub_tool_tooliface.h (revision 5999)
+--- include/pub_tool_tooliface.h (revision 6012)
+++ include/pub_tool_tooliface.h (working copy)
@@ -411,20 +411,32 @@
void VG_(track_post_thread_join) (void(*f)(ThreadId joiner, ThreadId joinee));
@@ -110,7 +110,7 @@
*/
Index: include/pub_tool_threadstate.h
===================================================================
---- include/pub_tool_threadstate.h (revision 5999)
+--- include/pub_tool_threadstate.h (revision 6012)
+++ include/pub_tool_threadstate.h (working copy)
@@ -46,6 +46,10 @@
/* Get the TID of the thread which currently has the CPU. */
@@ -125,7 +125,7 @@
/*--------------------------------------------------------------------*/
Index: include/pub_tool_libcprint.h
===================================================================
---- include/pub_tool_libcprint.h (revision 5999)
+--- include/pub_tool_libcprint.h (revision 6012)
+++ include/pub_tool_libcprint.h (working copy)
@@ -39,15 +39,27 @@
* --log-fd/--log-file/--log-socket argument, which defaults to 2 (stderr).
@@ -173,7 +173,7 @@
#endif // __PUB_TOOL_LIBCPRINT_H
Index: include/pub_tool_debuginfo.h
===================================================================
---- include/pub_tool_debuginfo.h (revision 5999)
+--- include/pub_tool_debuginfo.h (revision 6012)
+++ include/pub_tool_debuginfo.h (working copy)
@@ -135,6 +135,9 @@
@@ -187,7 +187,7 @@
/*--------------------------------------------------------------------*/
Index: include/valgrind.h
===================================================================
---- include/valgrind.h (revision 5999)
+--- include/valgrind.h (revision 6012)
+++ include/valgrind.h (working copy)
@@ -2298,6 +2298,48 @@
VG_USERREQ__STACK_REGISTER = 0x1501,
@@ -240,21 +240,28 @@
#if !defined(__GNUC__)
Index: include/pub_tool_basics.h
===================================================================
---- include/pub_tool_basics.h (revision 5999)
+--- include/pub_tool_basics.h (revision 6012)
+++ include/pub_tool_basics.h (working copy)
-@@ -97,6 +97,9 @@
+@@ -97,6 +97,16 @@
/* ThreadIds are simply indices into the VG_(threads)[] array. */
typedef UInt ThreadId;
-+/* pthread_t as handled internally in valgrind. */
-+typedef UInt PosixThreadId;
++/* A PosixThreadId uniquely identifies a POSIX thread in the client. This
++ datatype must be able to represent any client pthread_t value. The only
++ operations performed on this datatype are copying and comparison (==).
++ Note: the POSIX standard specifies that POSIX thread IDs may be implemented
++ as a struct, and that these must be compared by calling pthread_equal().
++ Representing POSIX thread IDs by an integer, and comparing these IDs via
++ "==" is a shortcut that works (at least) on Linux.
++ */
++typedef UWord PosixThreadId;
+
/* An abstraction of syscall return values.
When .isError == False, val holds the return value.
When .isError == True, val holds the error code.
Index: configure.in
===================================================================
---- configure.in (revision 5999)
+--- configure.in (revision 6012)
+++ configure.in (working copy)
@@ -738,6 +738,9 @@
none/tests/ppc64/Makefile
@@ -268,7 +275,7 @@
cat<