You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(122) |
Nov
(152) |
Dec
(69) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(6) |
Feb
(25) |
Mar
(73) |
Apr
(82) |
May
(24) |
Jun
(25) |
Jul
(10) |
Aug
(11) |
Sep
(10) |
Oct
(54) |
Nov
(203) |
Dec
(182) |
| 2004 |
Jan
(307) |
Feb
(305) |
Mar
(430) |
Apr
(312) |
May
(187) |
Jun
(342) |
Jul
(487) |
Aug
(637) |
Sep
(336) |
Oct
(373) |
Nov
(441) |
Dec
(210) |
| 2005 |
Jan
(385) |
Feb
(480) |
Mar
(636) |
Apr
(544) |
May
(679) |
Jun
(625) |
Jul
(810) |
Aug
(838) |
Sep
(634) |
Oct
(521) |
Nov
(965) |
Dec
(543) |
| 2006 |
Jan
(494) |
Feb
(431) |
Mar
(546) |
Apr
(411) |
May
(406) |
Jun
(322) |
Jul
(256) |
Aug
(401) |
Sep
(345) |
Oct
(542) |
Nov
(308) |
Dec
(481) |
| 2007 |
Jan
(427) |
Feb
(326) |
Mar
(367) |
Apr
(255) |
May
(244) |
Jun
(204) |
Jul
(223) |
Aug
(231) |
Sep
(354) |
Oct
(374) |
Nov
(497) |
Dec
(362) |
| 2008 |
Jan
(322) |
Feb
(482) |
Mar
(658) |
Apr
(422) |
May
(476) |
Jun
(396) |
Jul
(455) |
Aug
(267) |
Sep
(280) |
Oct
(253) |
Nov
(232) |
Dec
(304) |
| 2009 |
Jan
(486) |
Feb
(470) |
Mar
(458) |
Apr
(423) |
May
(696) |
Jun
(461) |
Jul
(551) |
Aug
(575) |
Sep
(134) |
Oct
(110) |
Nov
(157) |
Dec
(102) |
| 2010 |
Jan
(226) |
Feb
(86) |
Mar
(147) |
Apr
(117) |
May
(107) |
Jun
(203) |
Jul
(193) |
Aug
(238) |
Sep
(300) |
Oct
(246) |
Nov
(23) |
Dec
(75) |
| 2011 |
Jan
(133) |
Feb
(195) |
Mar
(315) |
Apr
(200) |
May
(267) |
Jun
(293) |
Jul
(353) |
Aug
(237) |
Sep
(278) |
Oct
(611) |
Nov
(274) |
Dec
(260) |
| 2012 |
Jan
(303) |
Feb
(391) |
Mar
(417) |
Apr
(441) |
May
(488) |
Jun
(655) |
Jul
(590) |
Aug
(610) |
Sep
(526) |
Oct
(478) |
Nov
(359) |
Dec
(372) |
| 2013 |
Jan
(467) |
Feb
(226) |
Mar
(391) |
Apr
(281) |
May
(299) |
Jun
(252) |
Jul
(311) |
Aug
(352) |
Sep
(481) |
Oct
(571) |
Nov
(222) |
Dec
(231) |
| 2014 |
Jan
(185) |
Feb
(329) |
Mar
(245) |
Apr
(238) |
May
(281) |
Jun
(399) |
Jul
(382) |
Aug
(500) |
Sep
(579) |
Oct
(435) |
Nov
(487) |
Dec
(256) |
| 2015 |
Jan
(338) |
Feb
(357) |
Mar
(330) |
Apr
(294) |
May
(191) |
Jun
(108) |
Jul
(142) |
Aug
(261) |
Sep
(190) |
Oct
(54) |
Nov
(83) |
Dec
(22) |
| 2016 |
Jan
(49) |
Feb
(89) |
Mar
(33) |
Apr
(50) |
May
(27) |
Jun
(34) |
Jul
(53) |
Aug
(53) |
Sep
(98) |
Oct
(206) |
Nov
(93) |
Dec
(53) |
| 2017 |
Jan
(65) |
Feb
(82) |
Mar
(102) |
Apr
(86) |
May
(187) |
Jun
(67) |
Jul
(23) |
Aug
(93) |
Sep
(65) |
Oct
(45) |
Nov
(35) |
Dec
(17) |
| 2018 |
Jan
(26) |
Feb
(35) |
Mar
(38) |
Apr
(32) |
May
(8) |
Jun
(43) |
Jul
(27) |
Aug
(30) |
Sep
(43) |
Oct
(42) |
Nov
(38) |
Dec
(67) |
| 2019 |
Jan
(32) |
Feb
(37) |
Mar
(53) |
Apr
(64) |
May
(49) |
Jun
(18) |
Jul
(14) |
Aug
(53) |
Sep
(25) |
Oct
(30) |
Nov
(49) |
Dec
(31) |
| 2020 |
Jan
(87) |
Feb
(45) |
Mar
(37) |
Apr
(51) |
May
(99) |
Jun
(36) |
Jul
(11) |
Aug
(14) |
Sep
(20) |
Oct
(24) |
Nov
(40) |
Dec
(23) |
| 2021 |
Jan
(14) |
Feb
(53) |
Mar
(85) |
Apr
(15) |
May
(19) |
Jun
(3) |
Jul
(14) |
Aug
(1) |
Sep
(57) |
Oct
(73) |
Nov
(56) |
Dec
(22) |
| 2022 |
Jan
(3) |
Feb
(22) |
Mar
(6) |
Apr
(55) |
May
(46) |
Jun
(39) |
Jul
(15) |
Aug
(9) |
Sep
(11) |
Oct
(34) |
Nov
(20) |
Dec
(36) |
| 2023 |
Jan
(79) |
Feb
(41) |
Mar
(99) |
Apr
(169) |
May
(48) |
Jun
(16) |
Jul
(16) |
Aug
(57) |
Sep
(19) |
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
|
1
(12) |
2
(5) |
3
(12) |
4
(9) |
5
(4) |
6
(7) |
|
7
(6) |
8
(10) |
9
(5) |
10
(5) |
11
(4) |
12
(7) |
13
(19) |
|
14
(11) |
15
(9) |
16
(6) |
17
(21) |
18
(13) |
19
(12) |
20
(9) |
|
21
(22) |
22
(24) |
23
(21) |
24
(12) |
25
(6) |
26
(3) |
27
(4) |
|
28
(3) |
29
(5) |
30
(11) |
31
(7) |
|
|
|
|
From: <sv...@va...> - 2008-12-21 23:11:21
|
Author: sewardj
Date: 2008-12-21 23:11:14 +0000 (Sun, 21 Dec 2008)
New Revision: 8859
Log:
More documentation updates. Urr. I knew there was a reason I'd been
putting this off.
Modified:
trunk/helgrind/docs/hg-manual.xml
Modified: trunk/helgrind/docs/hg-manual.xml
===================================================================
--- trunk/helgrind/docs/hg-manual.xml 2008-12-21 21:17:24 UTC (rev 8858)
+++ trunk/helgrind/docs/hg-manual.xml 2008-12-21 23:11:14 UTC (rev 8859)
@@ -362,17 +362,6 @@
-
-
-
-
-
-
-
-
-
-
-
<sect2 id="hg-manual.data-races.algorithm" xreflabel="DR Algorithm">
<title>Helgrind's Race Detection Algorithm</title>
@@ -573,10 +562,6 @@
-
-
-
-
<sect2 id="hg-manual.data-races.errmsgs" xreflabel="Race Error Messages">
<title>Interpreting Race Error Messages</title>
@@ -586,113 +571,99 @@
<programlisting><![CDATA[
Thread #2 was created
- at 0x510548E: clone (in /lib64/libc-2.5.so)
- by 0x4E2F305: do_clone (in /lib64/libpthread-2.5.so)
- by 0x4E2F7C5: pthread_create@@GLIBC_2.2.5 (in /lib64/libpthread-2.5.so)
- by 0x4C23870: pthread_create@* (hg_intercepts.c:198)
- by 0x400CEF: main (tc17_sembar.c:195)
+ at 0x511C08E: clone (in /lib64/libc-2.8.so)
+ by 0x4E333A4: do_clone (in /lib64/libpthread-2.8.so)
+ by 0x4E33A30: pthread_create@@GLIBC_2.2.5 (in /lib64/libpthread-2.8.so)
+ by 0x4C299D4: pthread_create@* (hg_intercepts.c:214)
+ by 0x4008F2: main (tc21_pthonce.c:86)
-// And the same for threads #3, #4 and #5 -- omitted for conciseness
+Thread #3 was created
+ at 0x511C08E: clone (in /lib64/libc-2.8.so)
+ by 0x4E333A4: do_clone (in /lib64/libpthread-2.8.so)
+ by 0x4E33A30: pthread_create@@GLIBC_2.2.5 (in /lib64/libpthread-2.8.so)
+ by 0x4C299D4: pthread_create@* (hg_intercepts.c:214)
+ by 0x4008F2: main (tc21_pthonce.c:86)
-Possible data race during read of size 4 at 0x602174
- at 0x400BE5: gomp_barrier_wait (tc17_sembar.c:122)
- by 0x400C44: child (tc17_sembar.c:161)
- by 0x4C25DF7: mythread_wrapper (hg_intercepts.c:178)
- by 0x4E2F09D: start_thread (in /lib64/libpthread-2.5.so)
- by 0x51054CC: clone (in /lib64/libc-2.5.so)
- Old state: shared-modified by threads #2, #3, #4, #5
- New state: shared-modified by threads #2, #3, #4, #5
- Reason: this thread, #2, holds no consistent locks
- Last consistently used lock for 0x602174 was first observed
- at 0x4C25D01: pthread_mutex_init (hg_intercepts.c:326)
- by 0x4009E4: gomp_barrier_init (tc17_sembar.c:46)
- by 0x400CBC: main (tc17_sembar.c:192)
+Possible data race during read of size 4 at 0x601070 by thread #3
+ at 0x40087A: child (tc21_pthonce.c:74)
+ by 0x4C29AFF: mythread_wrapper (hg_intercepts.c:194)
+ by 0x4E3403F: start_thread (in /lib64/libpthread-2.8.so)
+ by 0x511C0CC: clone (in /lib64/libc-2.8.so)
+ This conflicts with a previous write of size 4 by thread #2
+ at 0x400883: child (tc21_pthonce.c:74)
+ by 0x4C29AFF: mythread_wrapper (hg_intercepts.c:194)
+ by 0x4E3403F: start_thread (in /lib64/libpthread-2.8.so)
+ by 0x511C0CC: clone (in /lib64/libc-2.8.so)
+ Location 0x601070 is 0 bytes inside local var "unprotected2"
+ declared at tc21_pthonce.c:51, in frame #0 of thread 3
]]></programlisting>
<para>Helgrind first announces the creation points of any threads
referenced in the error message. This is so it can speak concisely
-about threads and sets of threads without repeatedly printing their
-creation point call stacks. Each thread is only ever announced once,
-the first time it appears in any Helgrind error message.</para>
+about threads without repeatedly printing their creation point call
+stacks. Each thread is only ever announced once, the first time it
+appears in any Helgrind error message.</para>
<para>The main error message begins at the text
-"<computeroutput>Possible data race during read</computeroutput>".
-At the start is information you would expect to see -- address and
-size of the racing access, whether a read or a write, and the call
-stack at the point it was detected.</para>
+"<computeroutput>Possible data race during read</computeroutput>". At
+the start is information you would expect to see -- address and size
+of the racing access, whether a read or a write, and the call stack at
+the point it was detected.</para>
-<para>More interesting is the state transition caused by this access.
-This memory is already in the shared-modified state, and up to now has
-been consistently protected by at least one lock. However, the thread
-making the access in question (thread #2, here) does not hold any
-locks in common with those held during all previous accesses to the
-location -- "no consistent locks", in other words.</para>
+<para>A second call stack is presented starting at the text
+"<computeroutput>This conflicts with a previous
+write</computeroutput>". This shows a previous access which also
+accessed the stated address, and which is believed to be racing
+against the access in the first call stack.</para>
-<para>Finally, Helgrind shows the lock which has protected this
-location in all previous accesses. (If there is more than one, only
-one is shown). This can be a useful hint, because it typically shows
-the lock that the programmers intended to use to protect the location,
-but in this case forgot.</para>
+<para>Finally, Helgrind may attempt to give a description of the
+raced-on address in source level terms. In this example, it
+identifies it as a local variable, shows its name, declaration point,
+and in which frame (of the first call stack) it lives. Note that this
+information is only shown when <varname>--read-var-info=yes</varname>
+is specified on the command line. That's because reading the DWARF3
+debug information in enough detail to capture variable type and
+location information makes Helgrind much slower at startup, and also
+requires considerable amounts of memory, for large programs.
+</para>
-<para>Here are some more examples of race reports. This not an
-exhaustive list of combinations, but should give you some insight into
-how to interpret the output.</para>
+<para>Once you have your two call stacks, how do you begin to get to
+the root problem?</para>
-<programlisting><![CDATA[
-Possible data race during write ...
- Old state: shared-readonly by threads #1, #2, #3
- New state: shared-modified by threads #1, #2, #3
- Reason: this thread, #3, holds no consistent locks
- Location ... has never been protected by any lock
-]]></programlisting>
+<para>The first thing to do is examine the source locations referred
+to by each call stack. They should both show an access to the same
+location, or variable.</para>
-<para>The location is shared by 3 threads, all of which have been
-reading it without locking ("has never been protected by any lock").
-Now one of them is writing it. Regardless of whether the writer has a
-lock or not, this is still an error, because the write races against
-the previously observed reads.</para>
+<para>Now figure out how how that location should have been made
+thread-safe:</para>
-<programlisting><![CDATA[
-Possible data race during read ...
- Old state: shared-modified by threads #1, #2, #3
- New state: shared-modified by threads #1, #2, #3
- Reason: this thread, #3, holds no consistent locks
- Last consistently used lock for ... was first observed ...
-]]></programlisting>
+<itemizedlist>
+ <listitem><para>Perhaps the location was intended to be protected by
+ a mutex? If so, you need to lock and unlock the mutex at both
+ access points, even if one of the accesses is reported to be a read.
+ Did you perhaps forget the locking at one or other of the
+ accesses?</para>
+ </listitem>
+ <listitem><para>Alternatively, you intended to use a some other
+ scheme to make it safe, such as signalling on a condition variable.
+ In all such cases, try to find a synchronisation event (or a chain
+ thereof) which separates the earlier-observed access (as shown in the
+ second call stack) from the later-observed access (as shown in the
+ first call stack). In other words, try to find evidence that the
+ earlier access "happens-before" the later access. See the previous
+ subsection for an explanation of the happens-before
+ relationship.</para>
+ <para>
+ The fact that Helgrind is reporting a race means it did not observe
+ any happens-before relationship between the two accesses. If
+ Helgrind is working correctly, it should also be the case that you
+ also cannot find any such relationship, even on detailed inspection
+ of the source code. Hopefully, though, your inspection of the code
+ will show where the missing synchronisation operation(s) should have
+ been.</para>
+ </listitem>
+</itemizedlist>
-<para>The location is shared by 3 threads, all of which have been
-reading and writing it while (as required) holding at least one lock
-in common. Now it is being read without that lock being held. In the
-"Last consistently used lock" part, Helgrind offers its best guess as
-to the identity of the lock that should have been used.</para>
-
-<programlisting><![CDATA[
-Possible data race during write ...
- Old state: owned exclusively by thread #4
- New state: shared-modified by threads #4, #5
- Reason: this thread, #5, holds no locks at all
-]]></programlisting>
-
-<para>A location that has so far been accessed exclusively by thread
-#4 has now been written by thread #5, without use of any lock. This
-can be a sign that the programmer did not consider the possibility of
-the location being shared between threads, or, alternatively, forgot
-to use the appropriate lock.</para>
-
-<para>Note that thread #4 exclusively owns the location, and so has
-the right to access it without holding a lock. However, this message
-does not say that thread #4 is not using a lock for this location.
-Indeed, it could be using a lock for the location because it intends
-to make it available to other threads, one of which is thread #5 --
-and thread #5 has forgotten to use the lock.</para>
-
-<para>Also, this message implies that Helgrind did not see any
-synchronisation event between threads #4 and #5 that would have
-allowed #5 to acquire exclusive ownership from #4. See
-<link linkend="hg-manual.data-races.exclusive">above</link>
-for a discussion of transfers of exclusive ownership states between
-threads.</para>
-
</sect2>
@@ -731,9 +702,9 @@
pthread_ functions.</para>
<para>Do not roll your own threading primitives (mutexes, etc)
- from combinations of the Linux futex syscall, counters and wotnot.
- These throw Helgrind's internal what's-going-on models way off
- course and will give bogus results.</para>
+ from combinations of the Linux futex syscall, atomic counters and
+ wotnot. These throw Helgrind's internal what's-going-on models
+ way off course and will give bogus results.</para>
<para>Also, do not reimplement existing POSIX abstractions using
other POSIX abstractions. For example, don't build your own
@@ -743,26 +714,39 @@
<para>Helgrind directly supports the following POSIX threading
abstractions: mutexes, reader-writer locks, condition variables
- (but see below), and semaphores. Currently spinlocks and barriers
- are not supported, although they could be in future. A prototype
- "safe" implementation of barriers, based on semaphores, is
- available: please contact the Valgrind authors for details.</para>
+ (but see below), semaphores and barriers. Currently spinlocks
+ are not supported, although they could be in future.</para>
<para>At the time of writing, the following popular Linux packages
are known to implement their own threading primitives:</para>
<itemizedlist>
- <listitem><para>Qt version 4.X. Qt 3.X is fine, but not 4.X.
- Helgrind contains partial direct support for Qt 4.X threading,
- but this is not yet in a usable state. Assistance from folks
- knowledgeable in Qt 4 threading internals would be
- appreciated.</para></listitem>
-
- <listitem><para>Runtime support library for GNU OpenMP (part of
- GCC), at least GCC versions 4.2 and 4.3. With some minor effort
- of modifying the GNU OpenMP runtime support sources, it is
- possible to use Helgrind on GNU OpenMP compiled codes. Please
- contact the Valgrind authors for details.</para></listitem>
+ <listitem><para>Qt version 4.X. Qt 3.X is harmless in that it
+ only uses POSIX pthreads primitives. Unfortunately Qt 4.X
+ has its own implementation of mutexes (QMutex) and thread reaping.
+ Helgrind 3.4.x contains direct support
+ for Qt 4.X threading, which is experimental but is believed to
+ work fairly well. A side effect of supporting Qt 4 directly is
+ that Helgrind can be used to debug KDE4 applications. As this
+ is an experimental feature, we would particularly appreciate
+ feedback from folks who have used Helgrind to successfully debug
+ Qt 4 and/or KDE4 applications.</para>
+ </listitem>
+ <listitem><para>Runtime support library for GNU OpenMP (part of
+ GCC), at least GCC versions 4.2 and 4.3. The GNU OpenMP runtime
+ library (libgomp.so) constructs its own synchronisation
+ primitives using combinations of atomic memory instructions and
+ the futex syscall, which causes total chaos since in Helgrind
+ since it cannot "see" those.</para>
+ <para>Fortunately, this can be solved using a configuration-time
+ flag (for gcc). Rebuild gcc from source, and configure using
+ <varname>--disable-linux-futex</varname>.
+ This makes libgomp.so use the standard
+ POSIX threading primitives instead. Note that this was tested
+ using gcc-4.2.3 and has not been re-tested using more recent gcc
+ versions. We would appreciate hearing about any successes or
+ failures with more recent versions.</para>
+ </listitem>
</itemizedlist>
</listitem>
@@ -810,10 +794,7 @@
<para>The result of Helgrind missing some inter-thread
synchronisation events is to cause it to report false positives.
- That's because missing such events reduces the extent to which it
- can transfer exclusive memory ownership between threads. So
- memory may end up in a shared-modified state when that was not
- intended by the application programmers.</para>
+ </para>
<para>The root cause of this synchronisation lossage is
particularly hard to understand, so an example is helpful. It was
@@ -862,16 +843,10 @@
<listitem>
<para>Make sure you are using a supported Linux distribution. At
- present, Helgrind only properly supports x86-linux and amd64-linux
- with glibc-2.3 or later. The latter restriction means we only
- support glibc's NPTL threading implementation. The old
- LinuxThreads implementation is not supported.</para>
-
- <para>Unsupported targets may work to varying degrees. In
- particular ppc32-linux and ppc64-linux running NPTL should work,
- but you will get false race errors because Helgrind does not know
- how to properly handle atomic instruction sequences created using
- the lwarx/stwcx instructions.</para>
+ present, Helgrind only properly supports glibc-2.3 or later. This
+ in turn means we only support glibc's NPTL threading
+ implementation. The old LinuxThreads implementation is not
+ supported.</para>
</listitem>
<listitem>
@@ -881,13 +856,7 @@
<para>Using pthread_join to round up finished threads provides a
clear synchronisation point that both Helgrind and programmers can
- see. This synchronisation point allows Helgrind to adjust its
- memory ownership
- models <link linkend="hg-manual.data-races.exclusive">as described
- extensively above</link>, which helps Helgrind produce more
- accurate error reports.</para>
-
- <para>If you don't call pthread_join on a thread, Helgrind has no
+ see. If you don't call pthread_join on a thread, Helgrind has no
way to know when it finishes, relative to any significant
synchronisation points for other threads in the program. So it
assumes that the thread lingers indefinitely and can potentially
|
|
From: <sv...@va...> - 2008-12-21 21:17:29
|
Author: sewardj
Date: 2008-12-21 21:17:24 +0000 (Sun, 21 Dec 2008)
New Revision: 8858
Log:
Partial update of the Helgrind documentation (incomplete).
Modified:
trunk/helgrind/docs/hg-manual.xml
Modified: trunk/helgrind/docs/hg-manual.xml
===================================================================
--- trunk/helgrind/docs/hg-manual.xml 2008-12-21 17:44:32 UTC (rev 8857)
+++ trunk/helgrind/docs/hg-manual.xml 2008-12-21 21:17:24 UTC (rev 8858)
@@ -22,16 +22,16 @@
threading primitives.</para>
<para>The main abstractions in POSIX pthreads are: a set of threads
-sharing a common address space, thread creation, thread joinage,
+sharing a common address space, thread creation, thread joining,
thread exit, mutexes (locks), condition variables (inter-thread event
-notifications), reader-writer locks, and semaphores.</para>
+notifications), reader-writer locks, semaphores and barriers.</para>
<para>Helgrind is aware of all these abstractions and tracks their
effects as accurately as it can. Currently it does not correctly
-handle pthread barriers and pthread spinlocks, although it will not
-object if you use them. On x86 and amd64 platforms, it understands
-and partially handles implicit locking arising from the use of the
-LOCK instruction prefix.
+handle pthread spinlocks, although it will not object if you use them.
+Adding support for spinlocks would be easy enough if the demand arises.
+On x86 and amd64 platforms, it understands and partially handles
+implicit locking arising from the use of the LOCK instruction prefix.
</para>
<para>Helgrind can detect three classes of errors, which are discussed
@@ -49,8 +49,12 @@
</listitem>
<listitem>
<para><link linkend="hg-manual.data-races">
- Data races -- accessing memory without adequate locking.
- </link></para>
+ Data races -- accessing memory without adequate locking
+ or synchronisation</link>.
+ Note that Helgrind in Valgrind 3.4.0 and later uses a
+ different algorithm than in 3.3.x. Hence, if you have been using
+ Helgrind in 3.3.x, you may want to re-read this section.
+ </para>
</listitem>
</orderedlist>
@@ -80,8 +84,8 @@
<para>Helgrind intercepts calls to many POSIX pthreads functions, and
is therefore able to report on various common problems. Although
these are unglamourous errors, their presence can lead to undefined
-program behaviour and hard-to-find bugs later in execution. The
-detected errors are:</para>
+program behaviour and hard-to-find bugs later on. The detected errors
+are:</para>
<itemizedlist>
<listitem><para>unlocking an invalid mutex</para></listitem>
@@ -100,8 +104,23 @@
<listitem><para>when a thread exits whilst still holding locked
locks</para></listitem>
<listitem><para>calling <computeroutput>pthread_cond_wait</computeroutput>
- with a not-locked mutex, or one locked by a different
+ with a not-locked mutex, an invalid mutex,
+ or one locked by a different
thread</para></listitem>
+ <listitem><para>invalid or duplicate initialisation of a pthread
+ barrier</para></listitem>
+ <listitem><para>initialisation of a pthread barrier on which threads
+ are still waiting</para></listitem>
+ <listitem><para>destruction of a pthread barrier object which was
+ never initialised, or on which threads are still
+ waiting</para></listitem>
+ <listitem><para>waiting on an uninitialised pthread
+ barrier</para></listitem>
+ <listitem><para>for all of the pthread_ functions that Helgrind
+ intercepts, an error is reported, along with a stack
+ trace, if the system threading library routine returns
+ an error code, even if Helgrind itself detected no
+ error</para></listitem>
</itemizedlist>
<para>Checks pertaining to the validity of mutexes are generally also
@@ -131,7 +150,7 @@
]]></programlisting>
<para>Helgrind has a way of summarising thread identities, as
-evidenced here by the text "<computeroutput>Thread
+you see here with the text "<computeroutput>Thread
#1</computeroutput>". This is so that it can speak about threads and
sets of threads without overwhelming you with details. See
<link linkend="hg-manual.data-races.errmsgs">below</link>
@@ -226,15 +245,15 @@
<sect1 id="hg-manual.data-races" xreflabel="Data Races">
<title>Detected errors: Data Races</title>
-<para>A data race happens, or could happen, when two threads
-access a shared memory location without using suitable locks to
-ensure single-threaded access. Such missing locking can cause
-obscure timing dependent bugs. Ensuring programs are race-free is
-one of the central difficulties of threaded programming.</para>
+<para>A data race happens, or could happen, when two threads access a
+shared memory location without using suitable locks or other
+synchronisation to ensure single-threaded access. Such missing
+locking can cause obscure timing dependent bugs. Ensuring programs
+are race-free is one of the central difficulties of threaded
+programming.</para>
<para>Reliably detecting races is a difficult problem, and most
of Helgrind's internals are devoted to do dealing with it.
-As a consequence this section is somewhat long and involved.
We begin with a simple example.</para>
@@ -277,455 +296,284 @@
Thread #1 is the program's root thread
Thread #2 was created
- at 0x510548E: clone (in /lib64/libc-2.5.so)
- by 0x4E2F305: do_clone (in /lib64/libpthread-2.5.so)
- by 0x4E2F7C5: pthread_create@@GLIBC_2.2.5 (in /lib64/libpthread-2.5.so)
- by 0x4C23870: pthread_create@* (hg_intercepts.c:198)
- by 0x4005F1: main (simple_race.c:12)
+ at 0x511C08E: clone (in /lib64/libc-2.8.so)
+ by 0x4E333A4: do_clone (in /lib64/libpthread-2.8.so)
+ by 0x4E33A30: pthread_create@@GLIBC_2.2.5 (in /lib64/libpthread-2.8.so)
+ by 0x4C299D4: pthread_create@* (hg_intercepts.c:214)
+ by 0x400605: main (simple_race.c:12)
-Possible data race during write of size 4 at 0x601034
- at 0x4005F2: main (simple_race.c:13)
- Old state: shared-readonly by threads #1, #2
- New state: shared-modified by threads #1, #2
- Reason: this thread, #1, holds no consistent locks
- Location 0x601034 has never been protected by any lock
+Possible data race during read of size 4 at 0x601038 by thread #1
+ at 0x400606: main (simple_race.c:13)
+ This conflicts with a previous write of size 4 by thread #2
+ at 0x4005DC: child_fn (simple_race.c:6)
+ by 0x4C29AFF: mythread_wrapper (hg_intercepts.c:194)
+ by 0x4E3403F: start_thread (in /lib64/libpthread-2.8.so)
+ by 0x511C0CC: clone (in /lib64/libc-2.8.so)
+ Location 0x601038 is 0 bytes inside global var "var"
+ declared at simple_race.c:3
]]></programlisting>
<para>This is quite a lot of detail for an apparently simple error.
The last clause is the main error message. It says there is a race as
-a result of a write of size 4 (bytes), at 0x601034, which is
-presumably the address of <computeroutput>var</computeroutput>,
-happening in function <computeroutput>main</computeroutput> at line 13
-in the program.</para>
+a result of a read of size 4 (bytes), at 0x601038, which is the
+address of <computeroutput>var</computeroutput>, happening in
+function <computeroutput>main</computeroutput> at line 13 in the
+program.</para>
-<para>Note that it is purely by chance that the race is
-reported for the parent thread's access. It could equally have been
-reported instead for the child's access, at line 6. The error will
-only be reported for one of the locations, since neither the parent
-nor child is, by itself, incorrect. It is only when both access
-<computeroutput>var</computeroutput> without a lock that an error
-exists.</para>
+<para>The error message shows two other important:</para>
-<para>The error message shows some other interesting details. The
-sections below explain them. Here we merely note their presence:</para>
-
<itemizedlist>
- <listitem><para>Helgrind maintains some kind of state machine for the
- memory location in question, hence the "<computeroutput>Old
- state:</computeroutput>" and "<computeroutput>New
- state:</computeroutput>" lines.</para>
+ <listitem>
+ <para>Helgrind shows two stack traces for the error, not one. By
+ definition, a race involves two different threads accessing the
+ same location in such a way that the result depends on the relative
+ speeds of the two threads.</para>
+ <para>
+ The first stack trace follows the text "<computeroutput>Possible
+ data race during read of size 4 ...</computeroutput>" and the
+ second trace follows the text "<computeroutput>This conflicts with
+ a previous write of size 4 ...</computeroutput>". Helgrind is
+ usually able to show both accesses involved in a race. At least
+ one of these will be a write (since two concurrent, unsynchronised
+ reads are harmless), and they will of course be from different
+ threads.</para>
+ <para>By examining your program at the two locations, it should be
+ fairly clear what the root cause of the problem is.</para>
</listitem>
- <listitem><para>Helgrind keeps track of which threads have accessed
- the location: "<computeroutput>threads #1, #2</computeroutput>".
- Before printing the main error message, it prints the creation
- points of these two threads, so you can see which threads it is
- referring to.</para>
+ <listitem>
+ <para>For races which occur on global or stack variables, Helgrind
+ tries to identify the name and defining point of the variable.
+ Hence the text "<computeroutput>Location 0x601038 is 0 bytes inside
+ global var "var" declared at simple_race.c:3</computeroutput>".</para>
+ <para>Showing names of stack and global variables carries no
+ run-time overhead once Helgrind has your program up and running.
+ However, it does require Helgrind to spend considerable extra time
+ and memory at program startup to read the relevant debug info.
+ Hence this facility is disabled by default. To enable it, you need
+ to give the <varname>--read-var-info=yes</varname> flag to
+ Helgrind.</para>
</listitem>
- <listitem><para>Helgrind tries to provide an explanation of why the
- race exists: "<computeroutput>Location 0x601034 has never been
- protected by any lock</computeroutput>".</para>
- </listitem>
</itemizedlist>
-<para>Understanding the memory state machine is central to
-understanding Helgrind's race-detection algorithm. The next three
-subsections explain this.</para>
+<para>The following section explains Helgrind's race detection
+algorithm in more detail.</para>
</sect2>
-<sect2 id="hg-manual.data-races.memstates" xreflabel="Memory States">
-<title>Helgrind's Memory State Machine</title>
-<para>Helgrind tracks the state of every byte of memory used by your
-program. There are a number of states, but only three are
-interesting:</para>
-<itemizedlist>
- <listitem><para>Exclusive: memory in this state is regarded as owned
- exclusively by one particular thread. That thread may read and
- write it without a lock. Even in highly threaded programs, the
- majority of locations never leave the Exclusive state, since most
- data is thread-private.</para>
- </listitem>
- <listitem><para>Shared-Readonly: memory in this state is regarded as
- shared by multiple threads. In this state, any thread may read the
- memory without a lock, reflecting the fact that readonly data may
- safely be shared between threads without locking.</para>
- </listitem>
- <listitem><para>Shared-Modified: memory in this state is regarded as
- shared by multiple threads, at least one of which has written to it.
- All participating threads must hold at least one lock in common when
- accessing the memory. If no such lock exists, Helgrind reports a
- race error.</para>
- </listitem>
-</itemizedlist>
-<para>Let's review the simple example above with this in mind. When
-the program starts, <computeroutput>var</computeroutput> is not in any
-of these states. Either the parent or child thread gets to its
-<computeroutput>var++</computeroutput> first, and thereby
-thereby gets Exclusive ownership of the location.</para>
-<para>The later-running thread now arrives at
-its <computeroutput>var++</computeroutput> statement. It first reads
-the existing value from memory.
-Because <computeroutput>var</computeroutput> is currently marked as
-owned exclusively by the other thread, its state is changed to
-shared-readonly by both threads.</para>
-<para>This same thread adds one to the value it has and stores it back
-in <computeroutput>var</computeroutput>. This causes another state
-change, this time to the shared-modified state. Because Helgrind has
-also been tracking which threads hold which locks, it can see that
-<computeroutput>var</computeroutput> is in shared-modified state but
-no lock has been used to consistently protect it. Hence a race is
-reported exactly at the transition from shared-readonly to
-shared-modified.</para>
-<para>The essence of the algorithm is this. Helgrind keeps track of
-each memory location that has been accessed by more than one thread.
-For each such location it incrementally infers the set of locks which
-have consistently been used to protect that location. If the
-location's lockset becomes empty, and at some point one of the threads
-attempts to write to it, a race is then reported.</para>
-<para>This technique is known as "lockset inference" and was
-introduced in: "Eraser: A Dynamic Data Race Detector for Multithreaded
-Programs" (Stefan Savage, Michael Burrows, Greg Nelson, Patrick
-Sobalvarro and Thomas Anderson, ACM Transactions on Computer Systems,
-15(4):391-411, November 1997).</para>
-<para>Lockset inference has since been widely implemented, studied and
-extended. Helgrind incorporates several refinements aimed at avoiding
-the high false error rate that naive versions of the algorithm suffer
-from. A
-<link linkend="hg-manual.data-races.summary">summary of the complete
-algorithm used by Helgrind</link> is presented below. First, however,
-it is important to understand details of transitions pertaining to the
-Exclusive-ownership state.</para>
-</sect2>
-<sect2 id="hg-manual.data-races.exclusive" xreflabel="Excl Transfers">
-<title>Transfers of Exclusive Ownership Between Threads</title>
+<sect2 id="hg-manual.data-races.algorithm" xreflabel="DR Algorithm">
+<title>Helgrind's Race Detection Algorithm</title>
-<para>As presented, the algorithm is far too strict. It reports many
-errors in perfectly correct, widely used parallel programming
-constructions, for example, using child worker threads and worker
-thread pools.</para>
+<para>Most programmers think about threaded programming in terms of
+the abstractions provided by the threading library (POSIX Pthreads):
+thread creation, thread joining, locks, condition variables and
+barriers.</para>
-<para>To avoid these false errors, we must refine the algorithm so
-that it keeps memory in an Exclusive ownership state in cases where it
-would otherwise decay into a shared-readonly or shared-modified state.
-Recall that Exclusive ownership is special in that it grants the
-owning thread the right to access memory without use of any locks. In
-order to support worker-thread and worker-thread-pool idioms, we will
-allow threads to steal exclusive ownership of memory from other
-threads under certain circumstances.</para>
+<para>The effect of using locks, barriers, etc, is to impose on a
+threaded program, constraints upon the order in which memory accesses
+can happen. This implied ordering is generally known as the
+"happens-before relationship". Once you understand the happens-before
+relationship, it is easy to see how Helgrind finds races in your code.
+Fortunately, the happens-before relationship is itself easy to
+understand, and, additionally, is by itself a useful tool for
+reasoning about the behaviour of parallel programs. We now introduce
+it using a simple example.</para>
-<para>Here's an example. Imagine a parent thread creates child
-threads to do units of work. For each unit of work, the parent
-allocates a work buffer, fills it in, and creates the child thread,
-handing it a pointer to the buffer. The child reads/writes the buffer
-and eventually exits, and the waiting parent then extracts the results
-from the buffer:</para>
+<para>Consider first the following buggy program:</para>
<programlisting><![CDATA[
-typedef ... Buffer;
+ int var;
-pthread_t child;
-Buffer buf;
+ create child
+
+ var = 20; var = 10;
+ exit
-/* ---- Parent ---- */ /* ---- Child ---- */
-
-/* parent writes workload into buf */
-pthread_create( &child, child_fn, &buf );
-
-/* parent does not read */ void child_fn ( Buffer* buf ) {
-/* or write buf */ /* read/write buf */
- }
-
-pthread_join ( child );
-/* parent reads results from buf */
+ wait for child
+ print(var);
]]></programlisting>
-<para>Although <computeroutput>buf</computeroutput> is accessed by
-both threads, neither uses locks, yet the program is race-free. The
-essential observation is that the child's creation and exit create
-synchronisation events between it and the parent. These force the
-child's accesses to <computeroutput>buf</computeroutput> to happen
-after the parent initialises <computeroutput>buf</computeroutput>, and
-before the parent reads the results
-from <computeroutput>buf</computeroutput>.</para>
+<para>The parent thread creates a child. Both then write different
+values to some variable <computeroutput>var</computeroutput>, and the
+parent then waits for the child to exit.</para>
-<para>To model this, Helgrind allows the child to steal, from the
-parent, exclusive ownership of any memory exclusively owned by the
-parent before the pthread_create call. Similarly, once the parent's
-pthread_join call returns, it can steal back ownership of memory
-exclusively owned by the child. In this way ownership
-of <computeroutput>buf</computeroutput> is transferred from parent to
-child and back, so the basic algorithm does not report any races
-despite the absence of any locking.</para>
+<para>What is the value of <computeroutput>var</computeroutput> at the
+end of the program, 10 or 20? We don't know. The program is
+considered buggy (it has a race) because the final value
+of <computeroutput>var</computeroutput> depends on the relative rates
+of progress of the parent and child threads. If the parent is fast
+and the child is slow, then the child's assignment may happen later,
+so the final value will be 10; and vice versa if the child is faster
+than the parent.</para>
-<para>Note that the child may only steal memory owned by the parent
-prior to the pthread_create call. If the child attempts to read or
-write memory which is also accessed by the parent in between the
-pthread_create and pthread_join calls, an error is still
-reported.</para>
+<para>The relative rates of progress of parent vs child is not something
+the programmer can control, and will often change from run to run.
+It depends on factors such as the load on the machine, what else is
+running, the kernel's scheduling strategy, and many other factors.</para>
-<para>This technique was introduced with the name "thread lifetime
-segments" in "Runtime Checking of Multithreaded Applications with
-Visual Threads" (Jerry J. Harrow, Jr, Proceedings of the 7th
-International SPIN Workshop on Model Checking of Software Stanford,
-California, USA, August 2000, LNCS 1885, pp331--342). Helgrind
-implements an extended version of it. Specifically, Helgrind allows
-transfer of exclusive ownership in the following situations:</para>
+<para>The obvious fix is to use a lock to
+protect <computeroutput>var</computeroutput>. It is however
+instructive to consider a somewhat more abstract solution, which is to
+send a message from one thread to the other:</para>
-<itemizedlist>
- <listitem><para>At thread creation: a child can acquire ownership of
- memory held exclusively by the parent prior to the child's
- creation.</para>
- </listitem>
- <listitem><para>At thread joining: the joiner (thread not exiting)
- can acquire ownership of memory held exclusively by the joinee
- (thread that is exiting) at the point it exited.</para>
- </listitem>
- <listitem><para>At condition variable signallings and broadcasts. A
- thread Tw which completes a pthread_cond_wait call as a result of
- a signal or broadcast on the same condition variable by some other
- thread Ts, may acquire ownership of memory held exclusively by
- Ts prior to the pthread_cond_signal/broadcast
- call.</para>
- </listitem>
- <listitem><para>At semaphore posts (sem_post) calls. A thread Tw
- which completes a sem_wait call call as a result of a sem_post call
- on the same semaphore by some other thread Tp, may acquire
- ownership of memory held exclusively by Tp prior to the sem_post
- call.</para>
- </listitem>
-</itemizedlist>
-
-</sect2>
-
-
-
-<sect2 id="hg-manual.data-races.re-excl" xreflabel="Re-Excl Transfers">
-<title>Restoration of Exclusive Ownership</title>
-
-<para>Another common idiom is to partition the lifetime of the program
-as a whole into several distinct phases. In some of those phases, a
-memory location may be accessed by multiple threads and so require
-locking. In other phases only one thread exists and so can access the
-memory without locking. For example:</para>
-
<programlisting><![CDATA[
-int var = 0; /* shared variable */
-pthread_mutex_t mx = PTHREAD_MUTEX_INITIALIZER; /* guard for var */
-pthread_t child;
+ int var;
-/* ---- Parent ---- */ /* ---- Child ---- */
+ create child
+
+ var = 20;
+ send message
+ wait for message
+ var = 10;
+ exit
-var += 1; /* no lock used */
-
-pthread_create( &child, child_fn, NULL );
-
- void child_fn ( void* uu ) {
-pthread_mutex_lock(&mx); pthread_mutex_lock(&mx);
-var += 2; var += 3;
-pthread_mutex_unlock(&mx); pthread_mutex_unlock(&mx);
- }
-
-pthread_join ( child );
-
-var += 4; /* no lock used */
+ wait for child
+ print(var);
]]></programlisting>
-<para>This program is correct, but using only the mechanisms described
-so far, Helgrind would report an error at
-<computeroutput>var += 4</computeroutput>. This is because, by that
-point, <computeroutput>var</computeroutput> is marked as being in the
-state "shared-modified and protected by the
-lock <computeroutput>mx</computeroutput>", but is being accessed
-without locking. Really, what we want is
-for <computeroutput>var</computeroutput> to return to the parent
-thread's exclusive ownership after the child thread has exited.</para>
+<para>Now the program reliably prints "10", regardless of the speed of
+the threads. Why? Because the child's assignment cannot happen until
+after it receives the message. And the message is not sent until
+after the parent's assignment is done.</para>
-<para>To make this possible, for every memory location Helgrind also keeps
-track of all the threads that have accessed that location
--- its threadset. When a thread Tquitter joins back to Tstayer,
-Helgrind examines the locksets of all memory in shared-modified or
-shared-readable state. In each such lockset, if Tquitter is
-mentioned, it is removed and replaced by Tstayer. If, as a result, a
-lockset becomes a singleton set containing Tstayer, then the
-location's state is changed to belongs-exclusively-to-Tstayer.</para>
+<para>The message transmission creates a "happens-before" dependency
+between the two assignments: <computeroutput>var = 20;</computeroutput>
+must now happen-before <computeroutput>var = 10;</computeroutput>.
+And so there is no longer a race
+on <computeroutput>var</computeroutput>.
+</para>
-<para>In our example, the result is exactly as we desire:
-<computeroutput>var</computeroutput> is reacquired exclusively by the
-parent after the child exits.</para>
+<para>Note that it's not significant that the parent sends a message
+to the child. Sending a message from the child (after its assignment)
+to the parent (before its assignment) would also fix the problem, causing
+the program to reliably print "20".</para>
-<para>More generally, when a group of threads merges back to a single
-thread via a cascade of pthread_join calls, any memory shared by the
-group (or a subset of it) ends up being owned exclusively by the sole
-surviving thread. This significantly enhances Helgrind's flexibility,
-since it means that each memory location may make arbitrarily many
-transitions between exclusive and shared ownership. Furthermore, a
-different lock may protect the location during each period of shared
-ownership.</para>
+<para>Helgrind's algorithm is (conceptually) very simple. It monitors all
+accesses to memory locations. If a location -- in this example,
+<computeroutput>var</computeroutput>,
+is accessed by two different threads, Helgrind checks to see if the
+two accesses are ordered by the happens-before relationship. If so,
+that's fine; if not, it reports a race.</para>
-</sect2>
+<para>It is important to understand the the happens-before relationship
+creates only a partial ordering, not a total ordering. An example of
+a total ordering is comparison of numbers: for any two numbers
+<computeroutput>x</computeroutput> and
+<computeroutput>y</computeroutput>, either
+<computeroutput>x</computeroutput> is less than, equal to, or greater
+than
+<computeroutput>y</computeroutput>. A partial ordering is like a
+total ordering, but it can also express the concepts that two elements
+are neither equal, less or greater, but merely unordered with respect
+to each other.</para>
+<para>In the fixed example above, we say that
+<computeroutput>var = 20;</computeroutput> "happens-before"
+<computeroutput>var = 10;</computeroutput>. But in the original
+version, they are unordered: we cannot say that either happens-before
+the other.</para>
+<para>What does it mean to say that two accesses from different
+threads are ordered by the happens-before relationship? It means that
+there is some chain of inter-thread synchronisation operations which
+cause those accesses to happen in a particular order, irrespective of
+the actual rates of progress of the individual threads. This is a
+required property for a reliable threaded program, which is why
+Helgrind checks for it.</para>
-<sect2 id="hg-manual.data-races.summary" xreflabel="Race Det Summary">
-<title>A Summary of the Race Detection Algorithm</title>
+<para>The happens-before relations created by standard threading
+primitives are as follows:</para>
-<para>Helgrind looks for memory locations which are accessed by more
-than one thread. For each such location, Helgrind records which of
-the program's locks were held by the accessing thread at the time of
-each access. The hope is to discover that there is indeed at least
-one lock which is consistently used by all threads to protect that
-location. If no such lock can be found, then there is apparently no
-consistent locking strategy being applied for that location, and so a
-possible data race might result. Helgrind accordingly reports an
-error.</para>
-
-<para>In practice this discipline is far too simplistic, and is
-unusable since it reports many races in some widely used and
-known-correct programming disciplines. Helgrind's checking therefore
-incorporates many refinements to this basic idea, and can be
-summarised as follows:</para>
-
-<para>The following thread events are intercepted and monitored:</para>
-
<itemizedlist>
- <listitem><para>thread creation and exiting (pthread_create,
- pthread_join, pthread_exit)</para>
+ <listitem><para>When a mutex is unlocked by thread T1 and later (or
+ immediately) locked by thread T2, then the memory accesses in T1
+ prior to the unlock must happen-before those in T2 after it acquires
+ the lock.</para>
</listitem>
- <listitem>
- <para>lock acquisition and release (pthread_mutex_lock,
- pthread_mutex_unlock, pthread_rwlock_rdlock,
- pthread_rwlock_wrlock,
- pthread_rwlock_unlock)</para>
+ <listitem><para>The same idea applies to reader-writer locks,
+ although with some complication so as to allow correct handling of
+ reads vs writes.</para>
</listitem>
- <listitem>
- <para>inter-thread event notifications (pthread_cond_wait,
- pthread_cond_signal, pthread_cond_broadcast,
- sem_wait, sem_post)</para>
+ <listitem><para>When a condition variable is signed on by thread T1
+ and some other thread T2 is thereby released from a wait on the same
+ CV, then the memory accesses in T1 prior to the signalling must
+ happen-before those in T2 after it returns from the wait. If no
+ thread was waiting on the CV then there is no
+ effect.</para>
</listitem>
-</itemizedlist>
-
-<para>Memory allocation and deallocation events are intercepted and
-monitored:</para>
-
-<itemizedlist>
- <listitem>
- <para>malloc/new/free/delete and variants</para>
+ <listitem><para>If instead T1 broadcasts on a CV then all of the
+ waiting threads, rather than just one of them, acquire a
+ happens-before dependency on the broadcasting thread at the point it
+ did the broadcast.</para>
</listitem>
- <listitem>
- <para>stack allocation and deallocation</para>
+ <listitem><para>A thread T2 that continues after completing sem_wait
+ on a semaphore that thread T1 posts on, acquires a happens-before
+ dependence on the posting thread, a bit like dependencies caused
+ mutex unlock-lock pairs. However, since a semaphore can be posted
+ on many times, it is unspecified from which of the post calls the
+ wait call gets its happens-before dependency.</para>
</listitem>
-</itemizedlist>
-
-<para>All memory accesses are intercepted and monitored.</para>
-
-<para>By observing the above events, Helgrind can infer certain
-aspects of the program's locking discipline. Programs which adhere to
-the following rules are considered to be acceptable:
-</para>
-
-<itemizedlist>
- <listitem>
- <para>A thread may allocate memory, and write initial values into
- it, without locking. That thread is regarded as owning the memory
- exclusively.</para>
+ <listitem><para>For a group of threads T1 .. Tn which arrive at a
+ barrier and then move on, each thread after the call has a
+ happens-after dependency from all threads before the
+ barrier.</para>
</listitem>
- <listitem>
- <para>A thread may read and write memory which it owns exclusively,
- without locking.</para>
+ <listitem><para>A newly-created child thread acquires an initial
+ happens-after dependency on the point where its parent created it.
+ That is, all memory accesses performed by the parent prior to
+ creating the child are regarded as happening-before all the accesses
+ of the child.</para>
</listitem>
- <listitem>
- <para>Memory which is owned exclusively by one thread may be read by
- that thread and others without locking. However, in this situation
- no thread may do unlocked writes to the memory (except for the owner
- thread's initializing write).</para>
+ <listitem><para>Similarly, when an exiting thread is reaped via a
+ call to pthread_join, once the call returns, the reaping thread
+ acquires a happens-after dependency relative to all memory accesses
+ made by the exiting thread.</para>
</listitem>
- <listitem>
- <para>Memory which is shared between multiple threads, one or more
- of which writes to it, must be protected by a lock which is
- correctly acquired and released by all threads accessing the
- memory.</para>
- </listitem>
</itemizedlist>
-<para>Any violation of this discipline will cause an error to be reported.
-However, two exemptions apply:</para>
+<para>Helgrind intercepts the above listed events, and builds a
+directed acyclic graph represented the collective happens-before
+dependencies. It also monitors all memory accesses.</para>
+<para>If a location is accessed by two different threads, but Helgrind
+cannot find any path through the happens-before graph from one access
+to the other, then it complains of a race.</para>
+
+<para>There are a couple of caveats:</para>
+
<itemizedlist>
- <listitem>
- <para>A thread Y can acquire exclusive ownership of memory
- previously owned exclusively by a different thread X providing
- X's last access and Y's first access are separated by one of the
- following synchronization events:</para>
- <itemizedlist>
- <listitem><para>X creates thread Y</para></listitem>
- <listitem><para>X joins back to Y</para></listitem>
- <listitem><para>X uses a condition-variable to signal at Y, and Y is
- waiting for that event</para></listitem>
- <listitem><para>Y completes a semaphore wait as a result of X signalling
- on that same semaphore</para></listitem>
- </itemizedlist>
- <para>
- This refinement allows Helgrind to correctly track the ownership
- state of inter-thread buffers used in the worker-thread and
- worker-thread-pool concurrent programming idioms (styles).</para>
+ <listitem><para>Helgrind doesn't check in the case where both
+ accesses are reads. That would be silly, since concurrent reads are
+ harmless.</para>
</listitem>
- <listitem>
- <para>Similarly, if thread Y joins back to thread X, memory
- exclusively owned by Y becomes exclusively owned by X instead.
- Also, memory that has been shared only by X and Y becomes
- exclusively owned by X. More generally, memory that has been shared
- by X, Y and some arbitrary other set S of threads is re-marked as
- shared by X and S. Hence, under the right circumstances, memory
- shared amongst multiple threads, all of which join into just one,
- can revert to the exclusive ownership state.</para>
- <para>
- In effect, each memory location may make arbitrarily many
- transitions between exclusive and shared ownership. Furthermore, a
- different lock may protect the location during each period of shared
- ownership. This significantly enhances the flexibility of the
- algorithm.</para>
+ <listitem><para>Two accesses are considered to be ordered by the
+ happens-before dependency even through arbitrarily long chains of
+ synchronisation events. For example, if T1 accesses some location
+ L, and then pthread_cond_signals T2, which later
+ pthread_cond_signals T3, which then accesses L, then a suitable
+ happens-before dependency exists between the first and second
+ accesses, even though it involves two different inter-thread
+ synchronisation events.</para>
</listitem>
</itemizedlist>
-<para>The ownership state, accessing thread-set and related lock-set
-for each memory location are tracked at 8-bit granularity. This means
-the algorithm is precise even for 16- and 8-bit memory
-accesses.</para>
+</sect2>
-<para>Helgrind correctly handles reader-writer locks in this
-framework. Locations shared between multiple threads can be protected
-during reads by locks held in either read-mode or write-mode, but can
-only be protected during writes by locks held in write-mode. Normal
-POSIX mutexes are treated as if they are reader-writer locks which are
-only ever held in write-mode.</para>
-<para>Helgrind correctly handles POSIX mutexes for which recursive
-locking is allowed.</para>
-<para>Helgrind partially correctly handles x86 and amd64 memory access
-instructions preceded by a LOCK prefix. Writes are correctly handled,
-by pretending that the LOCK prefix implies acquisition and release of
-a magic "bus hardware lock" mutex before and after the instruction.
-This unfortunately requires subsequent reads from such locations to
-also use a LOCK prefix, which is not required by the real hardware.
-Helgrind does not offer any equivalent handling for atomic sequences
-on PowerPC/POWER platforms created by the use of lwarx/stwcx
-instructions.</para>
-</sect2>
|
|
From: Bart V. A. <bar...@gm...> - 2008-12-21 18:49:21
|
On Thu, Dec 18, 2008 at 8:48 PM, <sv...@va...> wrote: > Log: > Callgrind: add code pattern for runtime_resolve on OpenSuse11.0/x86 Hello Josef, By compiling Valgrind on ppc64 I found out that the source file callgrind/fn.c triggers a compiler warning on that platform (fn.c:52: warning: 'check_code' defined but not used). Is it intended that the function search_runtime_resolve() only does something for VGP_x86_linux, VGP_ppc32_linux and for VGP_amd64_linux, but not for VGP_ppc64_linux ? Bart. |
|
From: <sv...@va...> - 2008-12-21 17:44:40
|
Author: bart Date: 2008-12-21 17:44:32 +0000 (Sun, 21 Dec 2008) New Revision: 8857 Log: Added prereq clause. Modified: trunk/drd/tests/circular_buffer.vgtest Modified: trunk/drd/tests/circular_buffer.vgtest =================================================================== --- trunk/drd/tests/circular_buffer.vgtest 2008-12-21 17:24:21 UTC (rev 8856) +++ trunk/drd/tests/circular_buffer.vgtest 2008-12-21 17:44:32 UTC (rev 8857) @@ -1,2 +1,3 @@ +prereq: ./supported_libpthread prog: circular_buffer args: -q |
|
From: <sv...@va...> - 2008-12-21 17:24:26
|
Author: bart
Date: 2008-12-21 17:24:21 +0000 (Sun, 21 Dec 2008)
New Revision: 8856
Log:
circular_buffer test now passes on systems with and without built-in support for atomic operations.
Added:
trunk/drd/tests/circular_buffer.stderr.exp-with-atomic-builtins
trunk/drd/tests/circular_buffer.stderr.exp-without-atomic-builtins
Removed:
trunk/drd/tests/circular_buffer.stderr.exp
Modified:
trunk/drd/tests/circular_buffer.c
Modified: trunk/drd/tests/circular_buffer.c
===================================================================
--- trunk/drd/tests/circular_buffer.c 2008-12-21 17:21:05 UTC (rev 8855)
+++ trunk/drd/tests/circular_buffer.c 2008-12-21 17:24:21 UTC (rev 8856)
@@ -196,8 +196,8 @@
int main(int argc, char** argv)
{
fprintf(stderr,
- "This test program has to be compiled with gcc version 4.1.0"
- " or later.\n");
+ "Sorry, but your compiler does not have built-in support for atomic"
+ " operations.\n");
return 0;
}
Deleted: trunk/drd/tests/circular_buffer.stderr.exp
===================================================================
--- trunk/drd/tests/circular_buffer.stderr.exp 2008-12-21 17:21:05 UTC (rev 8855)
+++ trunk/drd/tests/circular_buffer.stderr.exp 2008-12-21 17:24:21 UTC (rev 8856)
@@ -1,3 +0,0 @@
-
-
-ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Copied: trunk/drd/tests/circular_buffer.stderr.exp-with-atomic-builtins (from rev 8855, trunk/drd/tests/circular_buffer.stderr.exp)
===================================================================
--- trunk/drd/tests/circular_buffer.stderr.exp-with-atomic-builtins (rev 0)
+++ trunk/drd/tests/circular_buffer.stderr.exp-with-atomic-builtins 2008-12-21 17:24:21 UTC (rev 8856)
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Property changes on: trunk/drd/tests/circular_buffer.stderr.exp-with-atomic-builtins
___________________________________________________________________
Name: svn:mergeinfo
+
Added: trunk/drd/tests/circular_buffer.stderr.exp-without-atomic-builtins
===================================================================
--- trunk/drd/tests/circular_buffer.stderr.exp-without-atomic-builtins (rev 0)
+++ trunk/drd/tests/circular_buffer.stderr.exp-without-atomic-builtins 2008-12-21 17:24:21 UTC (rev 8856)
@@ -0,0 +1,4 @@
+
+Sorry, but your compiler does not have built-in support for atomic operations.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
|
|
From: <sv...@va...> - 2008-12-21 17:21:09
|
Author: bart
Date: 2008-12-21 17:21:05 +0000 (Sun, 21 Dec 2008)
New Revision: 8855
Log:
Added a suppression pattern for the data races triggered by the glibc function fflush().
Modified:
trunk/glibc-2.X-drd.supp
Modified: trunk/glibc-2.X-drd.supp
===================================================================
--- trunk/glibc-2.X-drd.supp 2008-12-21 17:20:22 UTC (rev 8854)
+++ trunk/glibc-2.X-drd.supp 2008-12-21 17:21:05 UTC (rev 8855)
@@ -78,6 +78,12 @@
fun:vfprintf
}
{
+ libc:stdio
+ drd:ConflictingAccess
+ ...
+ fun:fflush
+}
+{
librt
drd:ConflictingAccess
fun:__librt_enable_asynccancel
|
|
From: <sv...@va...> - 2008-12-21 17:20:27
|
Author: bart
Date: 2008-12-21 17:20:22 +0000 (Sun, 21 Dec 2008)
New Revision: 8854
Log:
Fixed bug in vector clock updating for semaphores with non-zero initial value.
Modified:
trunk/drd/drd_clientobj.h
trunk/drd/drd_semaphore.c
Modified: trunk/drd/drd_clientobj.h
===================================================================
--- trunk/drd/drd_clientobj.h 2008-12-21 17:19:05 UTC (rev 8853)
+++ trunk/drd/drd_clientobj.h 2008-12-21 17:20:22 UTC (rev 8854)
@@ -89,6 +89,7 @@
ObjType type;
void (*cleanup)(union drd_clientobj*);
ExeContext* first_observed_at;
+ UInt initial_value; // Value assigned through 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().
Modified: trunk/drd/drd_semaphore.c
===================================================================
--- trunk/drd/drd_semaphore.c 2008-12-21 17:19:05 UTC (rev 8853)
+++ trunk/drd/drd_semaphore.c 2008-12-21 17:20:22 UTC (rev 8854)
@@ -87,16 +87,16 @@
}
static
-void semaphore_initialize(struct semaphore_info* const p,
- const Addr semaphore, const UWord value)
+void 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->value = value;
- p->waiters = 0;
+ p->cleanup = (void(*)(DrdClientobj*))semaphore_cleanup;
+ p->initial_value = 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*));
@@ -136,7 +136,7 @@
{
tl_assert(offsetof(DrdClientobj, semaphore) == 0);
p = &clientobj_add(semaphore, ClientSemaphore)->semaphore;
- semaphore_initialize(p, semaphore, 0);
+ semaphore_initialize(p, semaphore);
}
return p;
}
@@ -151,7 +151,10 @@
struct semaphore_info* semaphore_init(const Addr semaphore,
const Word pshared, const UInt value)
{
+ unsigned n;
struct semaphore_info* p;
+ Segment* sg;
+ const DrdThreadId drd_tid = thread_get_running_tid();
if (s_trace_semaphore)
{
@@ -172,13 +175,19 @@
VG_(get_IP)(vg_tid),
"Semaphore reinitialization",
&SEI);
+ // Remove all segments from the segment stack.
+ while ((sg = segment_pop(p)))
+ {
+ sg_put(sg);
+ }
}
else
{
p = semaphore_get_or_allocate(semaphore);
}
tl_assert(p);
- p->value = value;
+ p->initial_value = value;
+ p->value = value;
return p;
}
@@ -263,17 +272,23 @@
}
p->value--;
tl_assert((int)p->value >= 0);
- sg = segment_pop(p);
- if (sg)
+ if (p->initial_value > 0)
+ p->initial_value--;
+ else
{
- if (p->last_sem_post_tid != tid
- && p->last_sem_post_tid != DRD_INVALID_THREADID)
+ sg = segment_pop(p);
+ tl_assert(sg);
+ if (sg)
{
- thread_combine_vc2(tid, &sg->vc);
+ if (p->last_sem_post_tid != tid
+ && p->last_sem_post_tid != DRD_INVALID_THREADID)
+ {
+ thread_combine_vc2(tid, &sg->vc);
+ }
+ sg_put(sg);
+ thread_new_segment(tid);
+ s_semaphore_segment_creation_count++;
}
- sg_put(sg);
- thread_new_segment(tid);
- s_semaphore_segment_creation_count++;
}
}
|
|
From: <sv...@va...> - 2008-12-21 17:19:09
|
Author: bart
Date: 2008-12-21 17:19:05 +0000 (Sun, 21 Dec 2008)
New Revision: 8853
Log:
Added command-line option -n, which allows to disable locking.
Modified:
trunk/drd/tests/circular_buffer.c
Modified: trunk/drd/tests/circular_buffer.c
===================================================================
--- trunk/drd/tests/circular_buffer.c 2008-12-21 17:16:03 UTC (rev 8852)
+++ trunk/drd/tests/circular_buffer.c 2008-12-21 17:19:05 UTC (rev 8853)
@@ -42,6 +42,7 @@
} buffer_t;
static int quiet = 0;
+static int use_locking = 1;
static __inline__
int fetch_and_add(int* p, int i)
@@ -65,7 +66,8 @@
{
int out;
sem_wait(&b->data);
- pthread_mutex_lock(&b->mutex_out);
+ if (use_locking)
+ pthread_mutex_lock(&b->mutex_out);
out = fetch_and_add(&b->out, 1);
if (out >= BUFFER_MAX)
{
@@ -73,7 +75,8 @@
out -= BUFFER_MAX;
}
*d = b->buffer[out];
- pthread_mutex_unlock(&b->mutex_out);
+ if (use_locking)
+ pthread_mutex_unlock(&b->mutex_out);
if (! quiet)
{
printf("received %d from buffer[%d]\n", *d, out);
@@ -86,7 +89,8 @@
{
int in;
sem_wait(&b->free);
- pthread_mutex_lock(&b->mutex_in);
+ if (use_locking)
+ pthread_mutex_lock(&b->mutex_in);
in = fetch_and_add(&b->in, 1);
if (in >= BUFFER_MAX)
{
@@ -94,7 +98,8 @@
in -= BUFFER_MAX;
}
b->buffer[in] = *d;
- pthread_mutex_unlock(&b->mutex_in);
+ if (use_locking)
+ pthread_mutex_unlock(&b->mutex_in);
if (! quiet)
{
printf("sent %d to buffer[%d]\n", *d, in);
@@ -145,10 +150,13 @@
int i;
int optchar;
- while ((optchar = getopt(argc, argv, "q")) != EOF)
+ while ((optchar = getopt(argc, argv, "nq")) != EOF)
{
switch (optchar)
{
+ case 'n':
+ use_locking = 0;
+ break;
case 'q':
quiet = 1;
break;
|
|
From: <sv...@va...> - 2008-12-21 17:16:10
|
Author: bart
Date: 2008-12-21 17:16:03 +0000 (Sun, 21 Dec 2008)
New Revision: 8852
Log:
Replaced regular increment by atomic increment.
Modified:
trunk/drd/tests/circular_buffer.c
Modified: trunk/drd/tests/circular_buffer.c
===================================================================
--- trunk/drd/tests/circular_buffer.c 2008-12-21 16:10:36 UTC (rev 8851)
+++ trunk/drd/tests/circular_buffer.c 2008-12-21 17:16:03 UTC (rev 8852)
@@ -12,9 +12,16 @@
#include <time.h>
#include <pthread.h>
#include <semaphore.h>
+#include "../../config.h"
+
+/** gcc versions 4.1.0 and later have support for atomic builtins. */
+#if defined(HAVE_BUILTIN_ATOMIC)
+
+
#define BUFFER_MAX (2)
+
typedef int data_t;
typedef struct {
@@ -23,9 +30,9 @@
/* Counting semaphore representing the number of free elements. */
sem_t free;
/* Position where a new elements should be written. */
- size_t in;
+ int in;
/* Position from where an element can be removed. */
- size_t out;
+ int out;
/* Mutex that protects 'in'. */
pthread_mutex_t mutex_in;
/* Mutex that protects 'out'. */
@@ -36,6 +43,12 @@
static int quiet = 0;
+static __inline__
+int fetch_and_add(int* p, int i)
+{
+ return __sync_fetch_and_add(p, i);
+}
+
void buffer_init(buffer_t * b)
{
sem_init(&b->data, 0, 0);
@@ -48,27 +61,49 @@
b->out = 0;
}
-void buffer_recv(buffer_t * b, data_t * d)
+void buffer_recv(buffer_t* b, data_t* d)
{
+ int out;
sem_wait(&b->data);
pthread_mutex_lock(&b->mutex_out);
- memcpy(d, b->buffer + b->out, sizeof(data_t));
- b->out = (b->out + 1) % BUFFER_MAX;
+ 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];
pthread_mutex_unlock(&b->mutex_out);
+ if (! quiet)
+ {
+ printf("received %d from buffer[%d]\n", *d, out);
+ fflush(stdout);
+ }
sem_post(&b->free);
}
-void buffer_send(buffer_t * b, data_t * d)
+void buffer_send(buffer_t* b, data_t* d)
{
+ int in;
sem_wait(&b->free);
pthread_mutex_lock(&b->mutex_in);
- memcpy(b->buffer + b->in, d, sizeof(data_t));
- b->in = (b->in + 1) % BUFFER_MAX;
+ 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;
pthread_mutex_unlock(&b->mutex_in);
+ if (! quiet)
+ {
+ printf("sent %d to buffer[%d]\n", *d, in);
+ fflush(stdout);
+ }
sem_post(&b->data);
}
-void buffer_destroy(buffer_t * b)
+void buffer_destroy(buffer_t* b)
{
sem_destroy(&b->data);
sem_destroy(&b->free);
@@ -93,7 +128,10 @@
usleep(rand() % MAXSLEEP);
buffer_recv(&b, &d);
if (! quiet)
+ {
printf("%i: %i\n", *id, d);
+ fflush(stdout);
+ }
pthread_exit(NULL);
}
@@ -142,3 +180,18 @@
return 0;
}
+
+
+#else
+
+
+int main(int argc, char** argv)
+{
+ fprintf(stderr,
+ "This test program has to be compiled with gcc version 4.1.0"
+ " or later.\n");
+ return 0;
+}
+
+
+#endif
|
|
From: <sv...@va...> - 2008-12-21 16:10:40
|
Author: bart
Date: 2008-12-21 16:10:36 +0000 (Sun, 21 Dec 2008)
New Revision: 8851
Log:
Made config.h include path consistent with the other regression tests.
Modified:
trunk/drd/tests/atomic_var.c
trunk/drd/tests/atomic_var.stderr.exp-with-atomic-builtins
Modified: trunk/drd/tests/atomic_var.c
===================================================================
--- trunk/drd/tests/atomic_var.c 2008-12-21 16:09:03 UTC (rev 8850)
+++ trunk/drd/tests/atomic_var.c 2008-12-21 16:10:36 UTC (rev 8851)
@@ -8,10 +8,10 @@
#define _GNU_SOURCE
-#include "config.h"
#include <pthread.h>
#include <stdio.h> /* fprintf() */
#include <stdlib.h> /* atoi() */
+#include "../../config.h"
/** Only gcc 4.1.0 and later have atomic builtins. */
Modified: trunk/drd/tests/atomic_var.stderr.exp-with-atomic-builtins
===================================================================
--- trunk/drd/tests/atomic_var.stderr.exp-with-atomic-builtins 2008-12-21 16:09:03 UTC (rev 8850)
+++ trunk/drd/tests/atomic_var.stderr.exp-with-atomic-builtins 2008-12-21 16:10:36 UTC (rev 8851)
@@ -7,7 +7,7 @@
by 0x........: (within libpthread-?.?.so)
by 0x........: clone (in /...libc...)
Location 0x........ is 0 bytes inside local var "s_y"
-declared at atomic_var.c:33, in frame #? of thread 2
+declared at atomic_var.c:39, in frame #? of thread 2
y = 1
Test finished.
|
|
From: <sv...@va...> - 2008-12-21 16:09:09
|
Author: bart Date: 2008-12-21 16:09:03 +0000 (Sun, 21 Dec 2008) New Revision: 8850 Log: Fixed typo: added missing right parentheses. Modified: trunk/configure.in Modified: trunk/configure.in =================================================================== --- trunk/configure.in 2008-12-21 16:08:36 UTC (rev 8849) +++ trunk/configure.in 2008-12-21 16:09:03 UTC (rev 8850) @@ -1165,7 +1165,7 @@ [ int variable = 1; return (__sync_bool_compare_and_swap(&variable, 1, 2) - && __sync_add_and_fetch(&variable, 1) ? 1 : 0 + && __sync_add_and_fetch(&variable, 1) ? 1 : 0) ], [ AC_MSG_RESULT([yes]) |
|
From: <sv...@va...> - 2008-12-21 16:08:45
|
Author: bart Date: 2008-12-21 16:08:36 +0000 (Sun, 21 Dec 2008) New Revision: 8849 Log: Finished renaming of boost_threads into boost_thread. Modified: trunk/drd/tests/boost_thread.vgtest Modified: trunk/drd/tests/boost_thread.vgtest =================================================================== --- trunk/drd/tests/boost_thread.vgtest 2008-12-21 16:08:07 UTC (rev 8848) +++ trunk/drd/tests/boost_thread.vgtest 2008-12-21 16:08:36 UTC (rev 8849) @@ -1,3 +1,3 @@ -prereq: test -e boost_threads +prereq: test -e boost_thread vgopts: --var-info=yes -prog: boost_threads +prog: boost_thread |
|
From: <sv...@va...> - 2008-12-21 16:08:13
|
Author: bart
Date: 2008-12-21 16:08:07 +0000 (Sun, 21 Dec 2008)
New Revision: 8848
Log:
Generalized the glibc _IO_file_xsputn suppression pattern. Added a suppression pattern for Boost.
Modified:
trunk/glibc-2.X-drd.supp
Modified: trunk/glibc-2.X-drd.supp
===================================================================
--- trunk/glibc-2.X-drd.supp 2008-12-21 10:45:55 UTC (rev 8847)
+++ trunk/glibc-2.X-drd.supp 2008-12-21 16:08:07 UTC (rev 8848)
@@ -72,7 +72,10 @@
}
{
libc:stdio
+ drd:ConflictingAccess
+ ...
fun:_IO_file_xsputn*
+ fun:vfprintf
}
{
librt
@@ -317,3 +320,10 @@
fun:_ZN24QAbstractEventDispatcherD2Ev
fun:_ZN20QEventDispatcherGlibD0Ev
}
+{
+ libboost_thread_1
+ drd:ConflictingAccess
+ ...
+ fun:_ZN5boost9call_onceIPFvvEEEvRNS_9once_flagET_
+ fun:_ZN5boost6detail23get_current_thread_dataEv
+}
|
|
From: <sv...@va...> - 2008-12-21 10:45:59
|
Author: sewardj Date: 2008-12-21 10:45:55 +0000 (Sun, 21 Dec 2008) New Revision: 8847 Log: Move description of --read-var-info= from the "debugging options" section to the "uncommon user options" section. Modified: trunk/coregrind/m_main.c Modified: trunk/coregrind/m_main.c =================================================================== --- trunk/coregrind/m_main.c 2008-12-21 10:44:28 UTC (rev 8846) +++ trunk/coregrind/m_main.c 2008-12-21 10:45:55 UTC (rev 8847) @@ -133,6 +133,9 @@ " only for code found in stacks, or all [stack]\n" " --kernel-variant=variant1,variant2,... known variants: bproc [none]\n" " handle non-standard kernel variants\n" +" --read-var-info=yes|no read debug info on stack and global variables\n" +" and use it to print better error messages in\n" +" tools that make use of it (Memcheck, Helgrind)\n" "\n" " user options for Valgrind tools that report errors:\n" " --xml=yes all output is in XML (some tools only)\n" @@ -173,7 +176,6 @@ " --profile-heap=no|yes profile Valgrind's own space use\n" " --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n" " --sym-offsets=yes|no show syms in form 'name+offset' ? [no]\n" -" --read-var-info=yes|no read variable type & location info? [no]\n" " --command-line-only=no|yes only use command line options [no]\n" "\n" " --vex-iropt-verbosity 0 .. 9 [0]\n" |
|
From: <sv...@va...> - 2008-12-21 10:44:38
|
Author: sewardj Date: 2008-12-21 10:44:28 +0000 (Sun, 21 Dec 2008) New Revision: 8846 Log: Following r8845, explicitly enable Dwarf3 variable/type info reading on tests whose output depends on it. --This line, and those below, will be ignored-- M helgrind/tests/tc20_verifywrap.vgtest M helgrind/tests/tc16_byterace.vgtest M helgrind/tests/tc01_simple_race.vgtest M helgrind/tests/rwlock_race.vgtest M helgrind/tests/tc06_two_races.vgtest M helgrind/tests/hg03_inherit.vgtest M helgrind/tests/tc21_pthonce.vgtest M helgrind/tests/tc05_simple_race.vgtest M helgrind/tests/hg04_race.vgtest M helgrind/tests/hg05_race2.vgtest Modified: trunk/helgrind/tests/hg03_inherit.vgtest trunk/helgrind/tests/hg04_race.vgtest trunk/helgrind/tests/hg05_race2.vgtest trunk/helgrind/tests/rwlock_race.vgtest trunk/helgrind/tests/tc01_simple_race.vgtest trunk/helgrind/tests/tc05_simple_race.vgtest trunk/helgrind/tests/tc06_two_races.vgtest trunk/helgrind/tests/tc16_byterace.vgtest trunk/helgrind/tests/tc20_verifywrap.vgtest trunk/helgrind/tests/tc21_pthonce.vgtest Modified: trunk/helgrind/tests/hg03_inherit.vgtest =================================================================== --- trunk/helgrind/tests/hg03_inherit.vgtest 2008-12-21 10:43:10 UTC (rev 8845) +++ trunk/helgrind/tests/hg03_inherit.vgtest 2008-12-21 10:44:28 UTC (rev 8846) @@ -1 +1,2 @@ prog: hg03_inherit +vgopts: --read-var-info=yes Modified: trunk/helgrind/tests/hg04_race.vgtest =================================================================== --- trunk/helgrind/tests/hg04_race.vgtest 2008-12-21 10:43:10 UTC (rev 8845) +++ trunk/helgrind/tests/hg04_race.vgtest 2008-12-21 10:44:28 UTC (rev 8846) @@ -1 +1,2 @@ prog: hg04_race +vgopts: --read-var-info=yes Modified: trunk/helgrind/tests/hg05_race2.vgtest =================================================================== --- trunk/helgrind/tests/hg05_race2.vgtest 2008-12-21 10:43:10 UTC (rev 8845) +++ trunk/helgrind/tests/hg05_race2.vgtest 2008-12-21 10:44:28 UTC (rev 8846) @@ -1 +1,2 @@ prog: hg05_race2 +vgopts: --read-var-info=yes Modified: trunk/helgrind/tests/rwlock_race.vgtest =================================================================== --- trunk/helgrind/tests/rwlock_race.vgtest 2008-12-21 10:43:10 UTC (rev 8845) +++ trunk/helgrind/tests/rwlock_race.vgtest 2008-12-21 10:44:28 UTC (rev 8846) @@ -1 +1,2 @@ prog: rwlock_race +vgopts: --read-var-info=yes Modified: trunk/helgrind/tests/tc01_simple_race.vgtest =================================================================== --- trunk/helgrind/tests/tc01_simple_race.vgtest 2008-12-21 10:43:10 UTC (rev 8845) +++ trunk/helgrind/tests/tc01_simple_race.vgtest 2008-12-21 10:44:28 UTC (rev 8846) @@ -1 +1,2 @@ prog: tc01_simple_race +vgopts: --read-var-info=yes Modified: trunk/helgrind/tests/tc05_simple_race.vgtest =================================================================== --- trunk/helgrind/tests/tc05_simple_race.vgtest 2008-12-21 10:43:10 UTC (rev 8845) +++ trunk/helgrind/tests/tc05_simple_race.vgtest 2008-12-21 10:44:28 UTC (rev 8846) @@ -1 +1,2 @@ prog: tc05_simple_race +vgopts: --read-var-info=yes Modified: trunk/helgrind/tests/tc06_two_races.vgtest =================================================================== --- trunk/helgrind/tests/tc06_two_races.vgtest 2008-12-21 10:43:10 UTC (rev 8845) +++ trunk/helgrind/tests/tc06_two_races.vgtest 2008-12-21 10:44:28 UTC (rev 8846) @@ -1 +1,2 @@ prog: tc06_two_races +vgopts: --read-var-info=yes Modified: trunk/helgrind/tests/tc16_byterace.vgtest =================================================================== --- trunk/helgrind/tests/tc16_byterace.vgtest 2008-12-21 10:43:10 UTC (rev 8845) +++ trunk/helgrind/tests/tc16_byterace.vgtest 2008-12-21 10:44:28 UTC (rev 8846) @@ -1 +1,2 @@ prog: tc16_byterace +vgopts: --read-var-info=yes Modified: trunk/helgrind/tests/tc20_verifywrap.vgtest =================================================================== --- trunk/helgrind/tests/tc20_verifywrap.vgtest 2008-12-21 10:43:10 UTC (rev 8845) +++ trunk/helgrind/tests/tc20_verifywrap.vgtest 2008-12-21 10:44:28 UTC (rev 8846) @@ -1 +1,2 @@ prog: tc20_verifywrap +vgopts: --read-var-info=yes Modified: trunk/helgrind/tests/tc21_pthonce.vgtest =================================================================== --- trunk/helgrind/tests/tc21_pthonce.vgtest 2008-12-21 10:43:10 UTC (rev 8845) +++ trunk/helgrind/tests/tc21_pthonce.vgtest 2008-12-21 10:44:28 UTC (rev 8846) @@ -1 +1,2 @@ prog: tc21_pthonce +vgopts: --read-var-info=yes |
|
From: <sv...@va...> - 2008-12-21 10:43:16
|
Author: sewardj
Date: 2008-12-21 10:43:10 +0000 (Sun, 21 Dec 2008)
New Revision: 8845
Log:
Various changes:
* remove flags --trace-addr= and --trace-level=. These no longer
have any effect, so there's no point in having the associated flags.
* add flag --show-conflicts=no|yes [yes], which makes it possible to
disable the conflicting-access collection machinery. This makes
Helgrind run much faster. Perhaps useful in regression testing,
when it is desired only to find out if a race exists, but not to
collect enough information to easily diagnose it.
* add flag --conflict-cache-size= [1000000], which makes it possible
to control how much memory is used for storage of information about
historical (potentially-conflicting) accesses.
* Update comments on the conflicting-access machinery to more closely
reflect the code. Includes comments on the important aspects of
the value N_OLDREF_ACCS. Increase said constant from 3 to 5.
* Fix bug in event_map_bind: when searching for an OldRef.accs[]
entry that matches the current access, don't forget to also
compare the access sizes. The old code only compared the thread
identity and the read/writeness.
* hg_main.c: disable Dwarf3 variable/type info reading by default.
Mostly this provides little benefit and can cause Helgrind to use
a lot more time and memory at startup.
Modified:
trunk/helgrind/hg_basics.c
trunk/helgrind/hg_basics.h
trunk/helgrind/hg_main.c
trunk/helgrind/libhb_core.c
Modified: trunk/helgrind/hg_basics.c
===================================================================
--- trunk/helgrind/hg_basics.c 2008-12-20 09:20:33 UTC (rev 8844)
+++ trunk/helgrind/hg_basics.c 2008-12-21 10:43:10 UTC (rev 8845)
@@ -70,15 +70,15 @@
/* Description of these flags is in hg_basics.h. */
-Bool HG_(clo_track_lockorders) = True;
+Bool HG_(clo_track_lockorders) = True;
-Bool HG_(clo_cmp_race_err_addrs) = False;
+Bool HG_(clo_cmp_race_err_addrs) = False;
-Addr HG_(clo_trace_addr) = 0;
+Bool HG_(clo_show_conflicts) = True;
-Word HG_(clo_trace_level) = 0;
+UWord HG_(clo_conflict_cache_size) = 1000000;
-Word HG_(clo_sanity_flags) = 0;
+Word HG_(clo_sanity_flags) = 0;
/*--------------------------------------------------------------------*/
Modified: trunk/helgrind/hg_basics.h
===================================================================
--- trunk/helgrind/hg_basics.h 2008-12-20 09:20:33 UTC (rev 8844)
+++ trunk/helgrind/hg_basics.h 2008-12-21 10:43:10 UTC (rev 8845)
@@ -72,12 +72,17 @@
(regtesting) this is sometimes important. */
extern Bool HG_(clo_cmp_race_err_addrs);
-/* Tracing memory accesses, so we can see what's going on.
- clo_trace_addr is the address to monitor. clo_trace_level = 0 for
- no tracing, 1 for summary, 2 for detailed. */
-extern Addr HG_(clo_trace_addr);
-extern Word HG_(clo_trace_level);
+/* Show conflicting accesses? This involves collecting and storing
+ large numbers of call stacks just in case we might need to show
+ them later, and so is expensive (although very useful). Hence
+ allow it to be optionally disabled. */
+extern Bool HG_(clo_show_conflicts);
+/* Size of the conflicting-access cache, measured in terms of
+ maximum possible number of elements in the previous-access map.
+ Must be between 10k amd 10 million. Default is 1 million. */
+extern UWord HG_(clo_conflict_cache_size);
+
/* Sanity check level. This is an or-ing of
SCE_{THREADS,LOCKS,BIGRANGE,ACCESS,LAOG}. */
extern Word HG_(clo_sanity_flags);
Modified: trunk/helgrind/hg_main.c
===================================================================
--- trunk/helgrind/hg_main.c 2008-12-20 09:20:33 UTC (rev 8844)
+++ trunk/helgrind/hg_main.c 2008-12-21 10:43:10 UTC (rev 8845)
@@ -3986,13 +3986,16 @@
else if (VG_CLO_STREQ(arg, "--cmp-race-err-addrs=yes"))
HG_(clo_cmp_race_err_addrs) = True;
- else if (VG_CLO_STREQN(13, arg, "--trace-addr=")) {
- HG_(clo_trace_addr) = VG_(atoll16)(&arg[13]);
- if (HG_(clo_trace_level) == 0)
- HG_(clo_trace_level) = 1;
- }
- else VG_BNUM_CLO(arg, "--trace-level", HG_(clo_trace_level), 0, 2)
+ else if (VG_CLO_STREQ(arg, "--show-conflicts=no"))
+ HG_(clo_show_conflicts) = False;
+ else if (VG_CLO_STREQ(arg, "--show-conflicts=yes"))
+ HG_(clo_show_conflicts) = True;
+ /* If you change the 10k/10mill limits, remember to also change
+ them in assertions at the top of event_map_maybe_GC. */
+ else VG_BNUM_CLO(arg, "--conflict-cache-size",
+ HG_(clo_conflict_cache_size), 10*1000, 10*1000*1000)
+
/* "stuvwx" --> stuvwx (binary) */
else if (VG_CLO_STREQN(18, arg, "--hg-sanity-flags=")) {
Int j;
@@ -4024,9 +4027,9 @@
static void hg_print_usage ( void )
{
VG_(printf)(
-" --track-lockorders=no|yes show lock ordering errors? [yes]\n"
-" --trace-addr=0xXXYYZZ show all state changes for address 0xXXYYZZ\n"
-" --trace-level=0|1|2 verbosity level of --trace-addr [1]\n"
+" --track-lockorders=no|yes show lock ordering errors? [yes]\n"
+" --show-conflicts=no|yes show both stack traces in a race? [yes]\n"
+" --conflict-cache-size=N size of conflict history cache [1000000]\n"
);
VG_(replacement_malloc_print_usage)();
}
@@ -4036,10 +4039,9 @@
VG_(replacement_malloc_print_debug_usage)();
VG_(printf)(" --cmp-race-err-addrs=no|yes are data addresses in "
"race errors significant? [no]\n");
- VG_(printf)(" --hg-sanity-flags=<XXXXXX> sanity check "
+ VG_(printf)(" --hg-sanity-flags=<XXXXXX> sanity check "
" at events (X = 0|1) [000000]\n");
VG_(printf)(" --hg-sanity-flags values:\n");
- VG_(printf)(" 100000 crosscheck happens-before-graph searches\n");
VG_(printf)(" 010000 after changes to "
"lock-order-acquisition-graph\n");
VG_(printf)(" 001000 at memory accesses (NB: not currently used)\n");
@@ -4198,7 +4200,11 @@
hg_cli__realloc,
HG_CLI__MALLOC_REDZONE_SZB );
- VG_(needs_var_info)(); /* optional */
+ /* 21 Dec 08: disabled this; it mostly causes H to start more
+ slowly and use significantly more memory, without very often
+ providing useful results. The user can request to load this
+ information manually with --read-var-info=yes. */
+ if (0) VG_(needs_var_info)(); /* optional */
VG_(track_new_mem_startup) ( evh__new_mem_w_perms );
VG_(track_new_mem_stack_signal)( evh__new_mem_w_tid );
Modified: trunk/helgrind/libhb_core.c
===================================================================
--- trunk/helgrind/libhb_core.c 2008-12-20 09:20:33 UTC (rev 8844)
+++ trunk/helgrind/libhb_core.c 2008-12-21 10:43:10 UTC (rev 8845)
@@ -2666,7 +2666,6 @@
// //
/////////////////////////////////////////////////////////
-#define EVENT_MAP_GC_AT (1 * 1000 * 1000)
#define EVENT_MAP_GC_DISCARD_FRACTION 0.5
/* This is in two parts:
@@ -2678,26 +2677,40 @@
only represent each one once. The set is indexed/searched by
ordering on the stack trace vectors.
- 2. An OSet of OldRefs. These store information about each old ref
- that we need to record. It is indexed by address of the
+ 2. A SparseWA of OldRefs. These store information about each old
+ ref that we need to record. It is indexed by address of the
location for which the information is recorded. For LRU
purposes, each OldRef also contains a generation number,
indicating when it was most recently accessed.
The important part of an OldRef is, however, its accs[] array.
- This is an array of N_OLDREF_ACCS pairs of Thr and a RCEC. This
- allows us to collect the last access-traceback by up to
- N_OLDREF_ACCS different threads for this location. The accs[]
- array is a MTF-array. If a pair falls off the end, that's too
- bad -- we will lose info about that thread's access to this
- location.
+ This is an array of N_OLDREF_ACCS which binds (thread, R/W,
+ size) triples to RCECs. This allows us to collect the last
+ access-traceback by up to N_OLDREF_ACCS different triples for
+ this location. The accs[] array is a MTF-array. If a binding
+ falls off the end, that's too bad -- we will lose info about
+ that triple's access to this location.
- When this OSet becomes too big, we can throw away the entries
+ When the SparseWA becomes too big, we can throw away the OldRefs
whose generation numbers are below some threshold; hence doing
approximate LRU discarding. For each discarded OldRef we must
of course decrement the reference count on the all RCECs it
refers to, in order that entries from (1) eventually get
discarded too.
+
+ A major improvement in reliability of this mechanism would be to
+ have a dynamically sized OldRef.accs[] array, so no entries ever
+ fall off the end. In investigations (Dec 08) it appears that a
+ major cause for the non-availability of conflicting-access traces
+ in race reports is caused by the fixed size of this array. I
+ suspect for most OldRefs, only a few entries are used, but for a
+ minority of cases there is an overflow, leading to info lossage.
+ Investigations also suggest this is very workload and scheduling
+ sensitive. Therefore a dynamic sizing would be better.
+
+ However, dynamic sizing would defeat the use of a GroupAllocator
+ for OldRef structures. And that's important for performance. So
+ it's not straightforward to do.
*/
@@ -2916,7 +2929,7 @@
*/
typedef struct { Thr* thr; RCEC* rcec; } Thr_n_RCEC;
-#define N_OLDREF_ACCS 3
+#define N_OLDREF_ACCS 5
typedef
struct {
@@ -3007,16 +3020,25 @@
if (b) {
/* We already have a record for this address. We now need to
- see if we have a stack trace pertaining to this thread's
- access. */
+ see if we have a stack trace pertaining to this (thread, R/W,
+ size) triple. */
tl_assert(keyW == a);
ref = (OldRef*)valW;
tl_assert(ref->magic == OldRef_MAGIC);
tl_assert(thr);
for (i = 0; i < N_OLDREF_ACCS; i++) {
- if (ref->accs[i].thr == thr)
- break;
+ if (ref->accs[i].thr != thr)
+ continue;
+ /* since .thr encodes both the accessing thread and the
+ read/writeness, we know now that at least those features
+ of the access match this entry. So we just need to check
+ the size indication. Do this by inspecting the lowest 2 bits of
+ .rcec, which contain the encoded size info. */
+ if (ptr_and_UWord(ref->accs[i].rcec,3) != ptr_and_UWord(rcec,3))
+ continue;
+ /* else we have a match, so stop looking. */
+ break;
}
if (i < N_OLDREF_ACCS) {
@@ -3033,13 +3055,16 @@
ref->accs[i].rcec = rcec;
tl_assert(ref->accs[i].thr == thr);
} else {
- /* No entry for this thread. Shuffle all of them down one
- slot, and put the new entry at the start of the array. */
+ /* No entry for this (thread, R/W, size) triple. Shuffle all
+ of them down one slot, and put the new entry at the start
+ of the array. */
if (ref->accs[N_OLDREF_ACCS-1].thr) {
/* the last slot is in use. We must dec the rc on the
associated rcec. */
tl_assert(ref->accs[N_OLDREF_ACCS-1].rcec);
stats__ctxt_rcdec2++;
+ if (0 && 0 == (stats__ctxt_rcdec2 & 0xFFF))
+ VG_(printf)("QQQQ %lu overflows\n",stats__ctxt_rcdec2);
ctxt__rcdec( ptr_and_UWord(ref->accs[N_OLDREF_ACCS-1].rcec, ~3) );
} else {
tl_assert(!ref->accs[N_OLDREF_ACCS-1].rcec);
@@ -3070,9 +3095,9 @@
ref->gen = oldrefGen;
ref->accs[0].rcec = rcec;
ref->accs[0].thr = thr;
- /* thr==NULL is used to signify an empty slot, so we can't
- add a NULL thr. */
- tl_assert(ptr_and_UWord(thr, ~3) != 0);
+ /* thr==NULL is used to signify an empty slot, so we can't add a
+ NULL thr. */
+ tl_assert(ptr_and_UWord(thr, ~3) != 0);
for (j = 1; j < N_OLDREF_ACCS; j++) {
ref->accs[j].thr = NULL;
ref->accs[j].rcec = NULL;
@@ -3305,12 +3330,17 @@
UWord genMap_min = 0;
UWord genMap_size = 0;
- if (LIKELY(oldrefTreeN < EVENT_MAP_GC_AT))
+ if (LIKELY(oldrefTreeN < HG_(clo_conflict_cache_size)))
return;
if (0)
VG_(printf)("libhb: event_map GC at size %lu\n", oldrefTreeN);
+ /* Check for sane command line params. Limit values must match
+ those in hg_process_cmd_line_option. */
+ tl_assert( HG_(clo_conflict_cache_size) >= 10*1000 );
+ tl_assert( HG_(clo_conflict_cache_size) <= 10*1000*1000 );
+
/* Check our counting is sane (expensive) */
if (CHECK_CEM)
tl_assert(oldrefTreeN == VG_(sizeSWA)( oldrefTree ));
@@ -3432,7 +3462,8 @@
tl_assert(keyW >= maxGen);
tl_assert(retained >= valW);
if (retained - valW
- > (UWord)(EVENT_MAP_GC_AT * EVENT_MAP_GC_DISCARD_FRACTION)) {
+ > (UWord)(HG_(clo_conflict_cache_size)
+ * EVENT_MAP_GC_DISCARD_FRACTION)) {
retained -= valW;
maxGen = keyW;
} else {
@@ -3688,7 +3719,7 @@
tl_assert(is_sane_SVal_C(svNew));
}
tl_assert(svNew != SVal_INVALID);
- if (svNew != svOld) {
+ if (svNew != svOld && HG_(clo_show_conflicts)) {
if (SVal__isC(svOld) && SVal__isC(svNew)) {
event_map_bind( acc_addr, szB, False/*!isWrite*/, acc_thr );
stats__msm_read_change++;
@@ -3769,7 +3800,7 @@
tl_assert(is_sane_SVal_C(svNew));
}
tl_assert(svNew != SVal_INVALID);
- if (svNew != svOld) {
+ if (svNew != svOld && HG_(clo_show_conflicts)) {
if (SVal__isC(svOld) && SVal__isC(svNew)) {
event_map_bind( acc_addr, szB, True/*isWrite*/, acc_thr );
stats__msm_write_change++;
|
|
From: Tom H. <th...@cy...> - 2008-12-21 04:10:21
|
Nightly build on alvis ( i686, Red Hat 7.3 ) started at 2008-12-21 03:15:03 GMT Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 375 tests, 93 stderr failures, 1 stdout failure, 29 post failures == drd/tests/circular_buffer (stderr) exp-ptrcheck/tests/bad_percentify (stderr) exp-ptrcheck/tests/base (stderr) exp-ptrcheck/tests/ccc (stderr) exp-ptrcheck/tests/fp (stderr) exp-ptrcheck/tests/globalerr (stderr) exp-ptrcheck/tests/hackedbz2 (stderr) exp-ptrcheck/tests/hp_bounds (stderr) exp-ptrcheck/tests/hp_dangle (stderr) exp-ptrcheck/tests/justify (stderr) exp-ptrcheck/tests/partial_bad (stderr) exp-ptrcheck/tests/partial_good (stderr) exp-ptrcheck/tests/preen_invars (stderr) exp-ptrcheck/tests/pth_create (stderr) exp-ptrcheck/tests/pth_specific (stderr) exp-ptrcheck/tests/realloc (stderr) exp-ptrcheck/tests/stackerr (stderr) exp-ptrcheck/tests/strcpy (stderr) exp-ptrcheck/tests/supp (stderr) exp-ptrcheck/tests/tricky (stderr) exp-ptrcheck/tests/unaligned (stderr) exp-ptrcheck/tests/zero (stderr) helgrind/tests/bar_bad (stderr) helgrind/tests/bar_trivial (stderr) helgrind/tests/hg01_all_ok (stderr) helgrind/tests/hg02_deadlock (stderr) helgrind/tests/hg03_inherit (stderr) helgrind/tests/hg04_race (stderr) helgrind/tests/hg05_race2 (stderr) helgrind/tests/hg06_readshared (stderr) helgrind/tests/pth_barrier1 (stderr) helgrind/tests/pth_barrier2 (stderr) helgrind/tests/pth_barrier3 (stderr) helgrind/tests/rwlock_race (stderr) helgrind/tests/rwlock_test (stderr) helgrind/tests/tc01_simple_race (stderr) helgrind/tests/tc02_simple_tls (stderr) helgrind/tests/tc03_re_excl (stderr) helgrind/tests/tc04_free_lock (stderr) helgrind/tests/tc05_simple_race (stderr) helgrind/tests/tc06_two_races (stderr) helgrind/tests/tc07_hbl1 (stderr) helgrind/tests/tc08_hbl2 (stderr) helgrind/tests/tc09_bad_unlock (stderr) helgrind/tests/tc10_rec_lock (stderr) helgrind/tests/tc11_XCHG (stderr) helgrind/tests/tc12_rwl_trivial (stderr) helgrind/tests/tc13_laog1 (stderr) helgrind/tests/tc14_laog_dinphils (stderr) helgrind/tests/tc15_laog_lockdel (stderr) helgrind/tests/tc16_byterace (stderr) helgrind/tests/tc17_sembar (stderr) helgrind/tests/tc18_semabuse (stderr) helgrind/tests/tc19_shadowmem (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) helgrind/tests/tc23_bogus_condwait (stderr) helgrind/tests/tc24_nonzero_sem (stderr) massif/tests/alloc-fns-A (post) massif/tests/alloc-fns-B (post) massif/tests/basic (post) massif/tests/basic2 (post) massif/tests/big-alloc (post) massif/tests/culling1 (stderr) massif/tests/culling2 (stderr) massif/tests/custom_alloc (post) massif/tests/deep-A (post) massif/tests/deep-B (stderr) massif/tests/deep-B (post) massif/tests/deep-C (stderr) massif/tests/deep-C (post) massif/tests/deep-D (post) massif/tests/ignoring (post) massif/tests/insig (post) massif/tests/long-names (post) massif/tests/long-time (post) massif/tests/new-cpp (post) massif/tests/null (post) massif/tests/one (post) massif/tests/overloaded-new (post) massif/tests/peak (post) massif/tests/peak2 (stderr) massif/tests/peak2 (post) massif/tests/realloc (stderr) massif/tests/realloc (post) massif/tests/thresholds_0_0 (post) massif/tests/thresholds_0_10 (post) massif/tests/thresholds_10_0 (post) massif/tests/thresholds_10_10 (post) massif/tests/thresholds_5_0 (post) massif/tests/thresholds_5_10 (post) massif/tests/zero1 (post) massif/tests/zero2 (post) memcheck/tests/leak-0 (stderr) memcheck/tests/leak-cycle (stderr) memcheck/tests/leak-regroot (stderr) memcheck/tests/leak-tree (stderr) memcheck/tests/long_namespace_xml (stderr) memcheck/tests/malloc_free_fill (stderr) memcheck/tests/mismatches (stderr) memcheck/tests/origin1-yes (stderr) memcheck/tests/origin4-many (stderr) memcheck/tests/origin5-bz2 (stderr) memcheck/tests/pointer-trace (stderr) memcheck/tests/stack_changes (stderr) memcheck/tests/varinfo1 (stderr) memcheck/tests/varinfo2 (stderr) memcheck/tests/varinfo3 (stderr) memcheck/tests/varinfo4 (stderr) memcheck/tests/varinfo5 (stderr) memcheck/tests/varinfo6 (stderr) memcheck/tests/x86/bug152022 (stderr) memcheck/tests/x86/scalar (stderr) memcheck/tests/x86/scalar_supp (stderr) memcheck/tests/x86/xor-undef-x86 (stderr) memcheck/tests/xml1 (stderr) none/tests/blockfault (stderr) none/tests/mremap2 (stdout) none/tests/shell (stderr) none/tests/shell_valid1 (stderr) none/tests/shell_valid2 (stderr) none/tests/shell_valid3 (stderr) |
|
From: Tom H. <th...@cy...> - 2008-12-21 04:08:25
|
Nightly build on lloyd ( x86_64, Fedora 7 ) started at 2008-12-21 03:05:07 GMT Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 472 tests, 26 stderr failures, 0 stdout failures, 0 post failures == exp-ptrcheck/tests/base (stderr) exp-ptrcheck/tests/ccc (stderr) exp-ptrcheck/tests/preen_invars (stderr) exp-ptrcheck/tests/pth_create (stderr) exp-ptrcheck/tests/pth_specific (stderr) helgrind/tests/bar_bad (stderr) helgrind/tests/hg02_deadlock (stderr) helgrind/tests/hg03_inherit (stderr) helgrind/tests/hg04_race (stderr) helgrind/tests/hg05_race2 (stderr) helgrind/tests/pth_barrier1 (stderr) helgrind/tests/pth_barrier2 (stderr) helgrind/tests/pth_barrier3 (stderr) helgrind/tests/rwlock_race (stderr) helgrind/tests/tc01_simple_race (stderr) helgrind/tests/tc05_simple_race (stderr) helgrind/tests/tc06_two_races (stderr) helgrind/tests/tc09_bad_unlock (stderr) helgrind/tests/tc14_laog_dinphils (stderr) helgrind/tests/tc16_byterace (stderr) helgrind/tests/tc19_shadowmem (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) memcheck/tests/x86/scalar (stderr) none/tests/blockfault (stderr) |
|
From: Tom H. <th...@cy...> - 2008-12-21 03:50:21
|
Nightly build on vauxhall ( x86_64, Fedora 10 ) started at 2008-12-21 03:20:04 GMT Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 480 tests, 45 stderr failures, 0 stdout failures, 0 post failures == cachegrind/tests/chdir (stderr) cachegrind/tests/clreq (stderr) cachegrind/tests/dlclose (stderr) cachegrind/tests/wrap5 (stderr) cachegrind/tests/x86/fpu-28-108 (stderr) callgrind/tests/simwork1 (stderr) callgrind/tests/simwork2 (stderr) callgrind/tests/simwork3 (stderr) exp-ptrcheck/tests/base (stderr) exp-ptrcheck/tests/preen_invars (stderr) helgrind/tests/bar_bad (stderr) helgrind/tests/bar_trivial (stderr) helgrind/tests/hg01_all_ok (stderr) helgrind/tests/hg02_deadlock (stderr) helgrind/tests/hg03_inherit (stderr) helgrind/tests/hg04_race (stderr) helgrind/tests/hg05_race2 (stderr) helgrind/tests/hg06_readshared (stderr) helgrind/tests/pth_barrier1 (stderr) helgrind/tests/pth_barrier2 (stderr) helgrind/tests/pth_barrier3 (stderr) helgrind/tests/rwlock_race (stderr) helgrind/tests/rwlock_test (stderr) helgrind/tests/tc01_simple_race (stderr) helgrind/tests/tc02_simple_tls (stderr) helgrind/tests/tc03_re_excl (stderr) helgrind/tests/tc05_simple_race (stderr) helgrind/tests/tc06_two_races (stderr) helgrind/tests/tc07_hbl1 (stderr) helgrind/tests/tc08_hbl2 (stderr) helgrind/tests/tc09_bad_unlock (stderr) helgrind/tests/tc11_XCHG (stderr) helgrind/tests/tc14_laog_dinphils (stderr) helgrind/tests/tc16_byterace (stderr) helgrind/tests/tc17_sembar (stderr) helgrind/tests/tc18_semabuse (stderr) helgrind/tests/tc19_shadowmem (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) helgrind/tests/tc23_bogus_condwait (stderr) helgrind/tests/tc24_nonzero_sem (stderr) memcheck/tests/linux-syscalls-2007 (stderr) memcheck/tests/x86/scalar (stderr) none/tests/blockfault (stderr) |
|
From: Tom H. <th...@cy...> - 2008-12-21 03:48:29
|
Nightly build on trojan ( x86_64, Fedora Core 6 ) started at 2008-12-21 03:25:04 GMT Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 476 tests, 25 stderr failures, 4 stdout failures, 0 post failures == exp-ptrcheck/tests/ccc (stderr) exp-ptrcheck/tests/preen_invars (stderr) exp-ptrcheck/tests/pth_create (stderr) exp-ptrcheck/tests/pth_specific (stderr) helgrind/tests/hg02_deadlock (stderr) helgrind/tests/hg03_inherit (stderr) helgrind/tests/hg04_race (stderr) helgrind/tests/hg05_race2 (stderr) helgrind/tests/pth_barrier1 (stderr) helgrind/tests/pth_barrier2 (stderr) helgrind/tests/pth_barrier3 (stderr) helgrind/tests/rwlock_race (stderr) helgrind/tests/tc01_simple_race (stderr) helgrind/tests/tc05_simple_race (stderr) helgrind/tests/tc06_two_races (stderr) helgrind/tests/tc09_bad_unlock (stderr) helgrind/tests/tc14_laog_dinphils (stderr) helgrind/tests/tc16_byterace (stderr) helgrind/tests/tc19_shadowmem (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) memcheck/tests/x86/bug133694 (stdout) memcheck/tests/x86/bug133694 (stderr) memcheck/tests/x86/scalar (stderr) none/tests/blockfault (stderr) none/tests/cmdline1 (stdout) none/tests/cmdline2 (stdout) none/tests/mremap2 (stdout) |
|
From: Tom H. <th...@cy...> - 2008-12-21 03:32:39
|
Nightly build on mg ( x86_64, Fedora 9 ) started at 2008-12-21 03:10:04 GMT Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 477 tests, 32 stderr failures, 1 stdout failure, 0 post failures == cachegrind/tests/chdir (stderr) cachegrind/tests/clreq (stderr) cachegrind/tests/dlclose (stderr) cachegrind/tests/wrap5 (stderr) cachegrind/tests/x86/fpu-28-108 (stderr) callgrind/tests/simwork1 (stderr) callgrind/tests/simwork2 (stderr) callgrind/tests/simwork3 (stderr) exp-ptrcheck/tests/ccc (stderr) exp-ptrcheck/tests/preen_invars (stderr) exp-ptrcheck/tests/pth_create (stderr) exp-ptrcheck/tests/pth_specific (stderr) helgrind/tests/hg02_deadlock (stderr) helgrind/tests/hg03_inherit (stderr) helgrind/tests/hg04_race (stderr) helgrind/tests/hg05_race2 (stderr) helgrind/tests/pth_barrier1 (stderr) helgrind/tests/pth_barrier2 (stderr) helgrind/tests/pth_barrier3 (stderr) helgrind/tests/rwlock_race (stderr) helgrind/tests/tc01_simple_race (stderr) helgrind/tests/tc05_simple_race (stderr) helgrind/tests/tc06_two_races (stderr) helgrind/tests/tc09_bad_unlock (stderr) helgrind/tests/tc14_laog_dinphils (stderr) helgrind/tests/tc16_byterace (stderr) helgrind/tests/tc19_shadowmem (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) memcheck/tests/x86/scalar (stderr) none/tests/blockfault (stderr) none/tests/mremap2 (stdout) |
|
From: Tom H. <th...@cy...> - 2008-12-21 03:29:36
|
Nightly build on gill ( x86_64, Fedora Core 2 ) started at 2008-12-21 03:00:04 GMT Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 478 tests, 37 stderr failures, 3 stdout failures, 0 post failures == exp-ptrcheck/tests/ccc (stderr) exp-ptrcheck/tests/hackedbz2 (stderr) helgrind/tests/bar_bad (stderr) helgrind/tests/hg01_all_ok (stderr) helgrind/tests/hg02_deadlock (stderr) helgrind/tests/hg03_inherit (stderr) helgrind/tests/hg04_race (stderr) helgrind/tests/hg05_race2 (stderr) helgrind/tests/pth_barrier1 (stderr) helgrind/tests/pth_barrier2 (stderr) helgrind/tests/pth_barrier3 (stderr) helgrind/tests/rwlock_race (stderr) helgrind/tests/rwlock_test (stderr) helgrind/tests/tc01_simple_race (stderr) helgrind/tests/tc05_simple_race (stderr) helgrind/tests/tc06_two_races (stderr) helgrind/tests/tc09_bad_unlock (stderr) helgrind/tests/tc14_laog_dinphils (stderr) helgrind/tests/tc16_byterace (stderr) helgrind/tests/tc17_sembar (stderr) helgrind/tests/tc19_shadowmem (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) helgrind/tests/tc23_bogus_condwait (stderr) memcheck/tests/malloc_free_fill (stderr) memcheck/tests/origin5-bz2 (stderr) memcheck/tests/stack_switch (stderr) memcheck/tests/varinfo6 (stderr) memcheck/tests/x86/scalar (stderr) memcheck/tests/x86/scalar_supp (stderr) none/tests/amd64/insn_ssse3 (stdout) none/tests/amd64/insn_ssse3 (stderr) none/tests/amd64/ssse3_misaligned (stderr) none/tests/blockfault (stderr) none/tests/fdleak_fcntl (stderr) none/tests/mremap2 (stdout) none/tests/x86/insn_ssse3 (stdout) none/tests/x86/insn_ssse3 (stderr) none/tests/x86/ssse3_misaligned (stderr) |