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
(20) |
2
(19) |
3
(7) |
|
4
(13) |
5
(24) |
6
(9) |
7
(12) |
8
(8) |
9
(34) |
10
(28) |
|
11
(20) |
12
(23) |
13
(12) |
14
(10) |
15
(15) |
16
(24) |
17
(26) |
|
18
(17) |
19
(14) |
20
(14) |
21
(8) |
22
(12) |
23
(22) |
24
(10) |
|
25
(21) |
26
(21) |
27
(18) |
28
(8) |
29
(13) |
30
(15) |
|
|
From: <sv...@va...> - 2007-11-03 23:27:01
|
Author: sewardj
Date: 2007-11-03 23:26:57 +0000 (Sat, 03 Nov 2007)
New Revision: 7086
Log:
Write loads more documentation. Is turning into a minor treatise ...
Modified:
branches/THRCHECK/thrcheck/docs/tc-manual.xml
Modified: branches/THRCHECK/thrcheck/docs/tc-manual.xml
===================================================================
--- branches/THRCHECK/thrcheck/docs/tc-manual.xml 2007-11-03 11:16:31 UTC (rev 7085)
+++ branches/THRCHECK/thrcheck/docs/tc-manual.xml 2007-11-03 23:26:57 UTC (rev 7086)
@@ -11,73 +11,547 @@
command line.</para>
+
+
<sect1 id="tc-manual.overview" xreflabel="Overview">
<title>Overview</title>
-<para>Thrcheck is a Valgrind tool for detecting threading errors in C,
-C++ and Fortran programs that use the POSIX Pthreads library.</para>
+<para>Thrcheck is a Valgrind tool for detecting synchronisation errors
+in C, C++ and Fortran programs that use the POSIX pthreads
+threading primitives.</para>
-<para>The main abstractions in POSIX Pthreads are: a set of threads
-sharing a common address space, mutexes (locks), condition variables
-(inter-thread event notifications), thread creation, thread joinage
-and thread exit.</para>
+<para>The main abstractions in POSIX pthreads are: a set of threads
+sharing a common address space, thread creation, thread joinage,
+thread exit, mutexes (locks), condition variables (inter-thread event
+notifications), reader-writer locks, and semaphores.</para>
-<para>Thrcheck can detect three the following three classes of
-errors:</para>
+<para>Thrcheck 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.
+</para>
+<para>Thrcheck can detect three classes of errors, which are discussed
+in detail in the next three sections:</para>
+
<orderedlist>
<listitem>
- <para>Misuses of the POSIX Pthreads API. Because the tool observes all
- significant thread events (creation, joinage, exit, lock, unlock,
- wait, signal, broadcast), it can report various common problems:</para>
- <itemizedlist>
- <listitem><para>unlocking a not-locked mutex</para></listitem>
- <listitem><para>unlocking a mutex held by a different
- thread</para></listitem>
- <listitem><para>recursively locking a non-recursive mutex</para></listitem>
- <listitem><para>waiting for a condition variable without holding
- the associated mutex</para></listitem>
- <listitem><para>inconsistent association of mutex and condition
- variables in pthread_cond_wait</para></listitem>
- <listitem><para>threads which exit while holding locked
- mutexes</para></listitem>
- <listitem><para>deallocation of memory that contains a
- locked mutex</para></listitem>
- </itemizedlist>
+ <para>Section FIXME: Misuses of the POSIX pthreads API.</para>
</listitem>
-
<listitem>
- <para>Potential deadlocks arising from lock ordering problems. If
- threads must acquire more than one lock before accessing some shared
- resource, then all threads must acquire those locks in the same
- order. Not doing so risks deadlock. Detecting such inconsistencies
- is useful because, whilst actual deadlocks are fairly obvious,
- potential deadlocks may never be discovered during testing and could
- later lead to hard-to-diagnose in-service failures.
- </para>
- <para>
- Detecting such problems is a simple matter of keeping track of
- observed lock acquisition orderings and reporting when new
- acquisitions violate the existing ordering.</para>
+ <para>Section FIXME: Potential deadlocks arising from lock ordering
+ problems.</para>
</listitem>
-
<listitem>
- <para>Data races. 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>Section FIXME: Data races -- accessing memory without adequate
+ locking.</para>
</listitem>
</orderedlist>
+<para>Section FIXME contains guidance on how to get the best out of Thrcheck.
+This is really a discussion about debugging strategies and how to
+organise your program to enhance its verifiability.</para>
+
+<para>Section FIXME contains a summary of command-line options.</para>
+
+<para>Finally, Section FIXME contains a brief list of areas in which Thrcheck
+could be improved.</para>
+
</sect1>
+
+
+<sect1 id="tc-manual.api-checks" xreflabel="API Checks">
+<title>Detected errors: Misuses of the POSIX pthreads API</title>
+
+<para>Thrcheck 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 include:</para>
+
+<itemizedlist>
+ <listitem><para>unlocking an invalid mutex</para></listitem>
+ <listitem><para>unlocking a not-locked mutex</para></listitem>
+ <listitem><para>unlocking a mutex held by a different
+ thread</para></listitem>
+ <listitem><para>destroying an invalid or a locked mutex</para></listitem>
+ <listitem><para>recursively locking a non-recursive mutex</para></listitem>
+ <listitem><para>deallocation of memory that contains a
+ locked mutex</para></listitem>
+ <listitem><para>passing mutex arguments to functions expecting
+ reader-writer lock arguments, and vice
+ versa</para></listitem>
+ <listitem><para>when a POSIX pthread function fails with an
+ error code that must be handled</para></listitem>
+</itemizedlist>
+
+<para>Checks pertaining to the validity of mutexes are generally also
+performed for reader-writer locks.</para>
+
+<para>Reported errors always contain a primary stack trace indicating
+where the error was detected. They may also contain auxiliary stack
+traces giving additional information. In particular, most errors
+relating to mutexes will also tell you where that mutex first came to
+Thrcheck's attention (the "<computeroutput>was first observed
+at</computeroutput>" part), so you have a chance of figuring out which
+mutex it is referring to. For example:</para>
+
+<programlisting><![CDATA[
+Thread #1 unlocked a not-locked lock at 0x7FEFFFA90
+ at 0x4C2408D: pthread_mutex_unlock (tc_intercepts.c:492)
+ by 0x40073A: nearly_main (tc09_bad_unlock.c:27)
+ by 0x40079B: main (tc09_bad_unlock.c:50)
+ Lock at 0x7FEFFFA90 was first observed
+ at 0x4C25D01: pthread_mutex_init (tc_intercepts.c:326)
+ by 0x40071F: nearly_main (tc09_bad_unlock.c:23)
+ by 0x40079B: main (tc09_bad_unlock.c:50)
+]]></programlisting>
+
+<para>Thrcheck has a way of summarising thread identities, as
+evidenced here by 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 FIXME
+below for details.</para>
+
+</sect1>
+
+
+
+
+<sect1 id="tc-manual.lock-orders" xreflabel="Lock Orders">
+<title>Detected errors: Inconsistent Lock Orderings</title>
+
+<para>In this section, and in general, to "acquire" a lock simply
+means to lock that lock, and to "release" a lock means to unlock
+it.</para>
+
+<para>Thrcheck monitors the order in which threads acquire locks.
+This allows it to detect potential deadlocks which could arise from
+the formation of cycles of locks. Detecting such inconsistencies is
+useful because, whilst actual deadlocks are fairly obvious, potential
+deadlocks may never be discovered during testing and could later lead
+to hard-to-diagnose in-service failures.</para>
+
+<para>The simplest example of such a problem is as
+follows.</para>
+
+<itemizedlist>
+ <listitem><para>Imagine some shared resource R, which, for whatever
+ reason, is guarded by two locks, L1 and L2, which must both be held
+ when R is accessed.</para>
+ </listitem>
+ <listitem><para>Suppose a thread acquires L1, then L2, and proceeds
+ to access R. The implication of this is that all threads in the
+ program must acquire the two locks in the order first L1 then L2.
+ Not doing so risks deadlock.</para>
+ </listitem>
+ <listitem><para>The deadlock could happen if two threads -- call them
+ T1 and T2 -- both want to access R. Suppose T1 acquires L1 first,
+ and T2 acquires L2 first. Then T1 tries to acquire L2, and T2 tries
+ to acquire L1, but those locks are both already held. So T1 and T2
+ become deadlocked.</para>
+ </listitem>
+</itemizedlist>
+
+<para>Thrcheck builds a directed graph indicating the order in which
+locks have been acquired in the past. When a thread acquires a new
+lock, the graph is updated, and then checked to see if it now contains
+a cycle. Presence of a cycle indicates a potential deadlock involving
+the locks in the cycle.</para>
+
+<para>In simple situations, where the cycle only contains two locks,
+Thrcheck will show where the required order was established:</para>
+
+<programlisting><![CDATA[
+Thread #1: lock order "0x7FEFFFAB0 before 0x7FEFFFA80" violated
+ at 0x4C23C91: pthread_mutex_lock (tc_intercepts.c:388)
+ by 0x40081F: main (tc13_laog1.c:24)
+ Required order was established by acquisition of lock at 0x7FEFFFAB0
+ at 0x4C23C91: pthread_mutex_lock (tc_intercepts.c:388)
+ by 0x400748: main (tc13_laog1.c:17)
+ followed by a later acquisition of lock at 0x7FEFFFA80
+ at 0x4C23C91: pthread_mutex_lock (tc_intercepts.c:388)
+ by 0x400773: main (tc13_laog1.c:18)
+]]></programlisting>
+
+<para>When there are more than two locks in the cycle, the error is
+equally serious. However, at present Thrcheck does not show the locks
+involved, so as to avoid flooding you with information. That could be
+fixed in future. For example, here is a an example involving a cycle
+of five locks from a naive implementation the famous Dining
+Philosophers problem
+(see <computeroutput>thrcheck/tests/tc14_laog_dinphils.c</computeroutput>).
+In this case Thrcheck has detected that all 5 philosophers could
+simultaneously pick up their left fork and then deadlock whilst
+waiting to pick up their right forks.</para>
+
+<programlisting><![CDATA[
+Thread #6: lock order "0x6010C0 before 0x601160" violated
+ at 0x4C23C91: pthread_mutex_lock (tc_intercepts.c:388)
+ by 0x4007C0: dine (tc14_laog_dinphils.c:19)
+ by 0x4C25DF7: mythread_wrapper (tc_intercepts.c:178)
+ by 0x4E2F09D: start_thread (in /lib64/libpthread-2.5.so)
+ by 0x51054CC: clone (in /lib64/libc-2.5.so)
+]]></programlisting>
+
+</sect1>
+
+
+
+
<sect1 id="tc-manual.data-races" xreflabel="Data Races">
-<title>Data Races</title>
+<title>Detected errors: Data Races</title>
-This section describes Thrcheck's data race detection in more detail.
+<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>Reliably detecting races is a difficult problem, and most
+of Thrcheck'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>
+
+
+<sect2 id="tc-manual.data-races.example" xreflabel="Simple Race">
+<title>A simple data race</title>
+
+<para>About the simplest possible example of a race is as follows. In
+this program, it is impossible to know what the value
+of <computeroutput>var</computeroutput> is at the end of the program.
+Is it 2 ? Or 1 ?</para>
+
+<programlisting><![CDATA[
+#include <pthread.h>
+
+int var = 0;
+
+void* child_fn ( void* arg ) {
+ var++; /* Unprotected relative to parent */ /* this is line 6 */
+ return NULL;
+}
+
+int main ( void ) {
+ pthread_t child;
+ pthread_create(&child, NULL, child_fn, NULL);
+ var++; /* Unprotected relative to child */ /* this is line 13 */
+ pthread_join(child, NULL);
+ return 0;
+}
+]]></programlisting>
+
+<para>The problem is there is nothing to
+stop <computeroutput>var</computeroutput> being updated simultaneously
+by both threads. A correct program would
+protect <computeroutput>var</computeroutput> with a lock of type
+<computeroutput>pthread_mutex_t</computeroutput>, which is acquired
+before each access and released afterwards. Thrcheck's output for
+this program is:</para>
+
+<programlisting><![CDATA[
+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@* (tc_intercepts.c:198)
+ by 0x4005F1: 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
+]]></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>
+
+<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 some other interesting details. The
+sections below explain them. Here we merely note their presence:</para>
+
+<itemizedlist>
+ <listitem><para>Thrcheck 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>
+ <listitem><para>Thrcheck 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>
+ <listitem><para>Thrcheck tries to provide an explaination 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 Thrcheck's race-detection algorithm. The next two
+subsections explain this.</para>
+
+</sect2>
+
+
+<sect2 id="tc-manual.data-races.memstates" xreflabel="Memory States">
+<title>Thrcheck's Memory State Machine</title>
+
+<para>Thrcheck 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, Thrcheck 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 Thrcheck 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. Thrcheck 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 FIXME. It has been widely implemented since then.
+Thrcheck incorporates several refinements aimed at reducing the false
+error rate generated by a naive version of the algorithm. In section
+FIXME a summary of the complete algorithm used by Thrcheck is
+presented. First, however, it is important to understand details of
+transitions pertaining to the Exclusive-ownership state.</para>
+
+</sect2>
+
+
+
+<sect2 id="tc-manual.data-races.exclusive" xreflabel="Excl Transfers">
+<title>Transfers of Exclusive Ownership Between Threads</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>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>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>
+
+<programlisting><![CDATA[
+typedef ... Buffer;
+
+pthread_t child;
+Buffer buf;
+
+/* ---- 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 */
+]]></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>To model this, Thrcheck 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>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>This technique was introduced in FIXME with the name Thread
+Lifetime Segments. Thrcheck implements an extended version of it.
+Specifically, Thrcheck allows transfer of exclusive ownership in the
+following situations:</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 Twait which completes a pthread_cond_wait call as a result of
+ a signal or broadcast on the same condition variable by some other
+ thread Tsig, may acquire ownership of memory held exclusively by
+ Tsig prior to the pthread_cond_signal/broadcast
+ call.</para>
+ </listitem>
+ <listitem><para>At semaphore posts (sem_post) calls. A thread Twait
+ which completes a sem_wait call call as a result of a sem_post call
+ on the same semaphore by some other thread Tpost, may acquire
+ ownership of memory held exclusively by Tpost prior to the sem_post
+ call.</para>
+ </listitem>
+</itemizedlist>
+
+
+
+</sect2>
+
+<sect2 id="tc-manual.data-races.re-excl" xreflabel="Re-Excl Transfers">
+<title>Reacquisition of Exclusive States</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;
+
+/* ---- Parent ---- */ /* ---- Child ---- */
+
+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 */
+]]></programlisting>
+
+<para>This program is correct, but using only the mechanisms described
+so far, Thrcheck 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 with a singleton
+lockset <computeroutput>{mx}</computeroutput>". 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>To make this possible, for every memory location Thrcheck also keeps
+track of all the threads that have accessed that location
+-- its threadset. When a thread Tquitter joins back to Tstayer,
+Thrcheck 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>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>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 Thrcheck's flexibility,
+since it means that memory can transition arbitrarily many times
+between exclusive and shared states over the lifetime of the program.
+Moreover, locations may be protected by different locks during
+different phases of shared ownership.</para>
+
+
+
+
+
+</sect2>
+
+<para>-------------------------------------------------</para>
+
<para>In short, what Thrcheck does is to look for memory locations
which are accessed by more than one thread. For each such location,
Thrcheck records which of the program's (pthread_mutex_)locks were
@@ -199,6 +673,26 @@
</sect1>
+
+<sect1 id="tc-manual.effective-use" xreflabel="Thrcheck Effective Use">
+<title>Hints and Tips for Effective Use of Thrcheck</title>
+
+
+<para>Thrcheck can be very helpful in finding and resolving
+threading-related problems. Like all sophisticated tools, it is most
+effective when you have some level of understanding of what the tool
+is doing. Thrcheck will be less effective when you merely throw an
+existing threaded program at it and try to make sense of any reported
+errors. It will be more effective if you design threaded programs
+from the start in a way that helps Thrcheck verify correctness. The
+same is true for finding memory errors with Memcheck, but applies more
+here, because thread checking is a harder problem.</para>
+
+</sect1>
+
+
+
+
<sect1 id="tc-manual.options" xreflabel="Thrcheck Options">
<title>Thrcheck Options</title>
@@ -276,6 +770,13 @@
</para></listitem>
</itemizedlist>
+Inconsistent cv/mx associations
+Thread exiting whilst holding locks
+
+waiting for a condition variable without holding
+ the associated mutex
+
+better printing of lock cycles
</sect1>
</chapter>
|
|
From: <sv...@va...> - 2007-11-03 11:16:32
|
Author: sewardj
Date: 2007-11-03 11:16:31 +0000 (Sat, 03 Nov 2007)
New Revision: 7085
Log:
Fix gcc-2.96 build failures.
Modified:
trunk/massif/tests/long-time.c
trunk/massif/tests/new-cpp.cpp
trunk/massif/tests/overloaded-new.cpp
Modified: trunk/massif/tests/long-time.c
===================================================================
--- trunk/massif/tests/long-time.c 2007-11-02 21:44:02 UTC (rev 7084)
+++ trunk/massif/tests/long-time.c 2007-11-03 11:16:31 UTC (rev 7085)
@@ -7,15 +7,15 @@
int main(void)
{
- int i;
+ int i, *x1, *x2, *x3, *x4;
for (i = 0; i < 1500; i++) {
- int* x1 = malloc( 800 * 1000);
- int* x2 = malloc(1100 * 1000);
+ x1 = malloc( 800 * 1000);
+ x2 = malloc(1100 * 1000);
free(x1);
- int* x3 = malloc(1200 * 1000);
+ x3 = malloc(1200 * 1000);
free(x2);
free(x3);
- int* x4 = malloc( 900 * 1000);
+ x4 = malloc( 900 * 1000);
free(x4);
}
return 0;
Modified: trunk/massif/tests/new-cpp.cpp
===================================================================
--- trunk/massif/tests/new-cpp.cpp 2007-11-02 21:44:02 UTC (rev 7084)
+++ trunk/massif/tests/new-cpp.cpp 2007-11-03 11:16:31 UTC (rev 7085)
@@ -10,14 +10,14 @@
using std::nothrow_t;
// A big structure. Its details don't matter.
-struct s {
- int array[1000];
-};
+typedef struct {
+ int array[1000];
+ } s;
int main(void)
{
- struct s* p1 = new struct s;
- struct s* p2 = new (std::nothrow) struct s;
+ s* p1 = new s;
+ s* p2 = new (std::nothrow) s;
char* c1 = new char[2000];
char* c2 = new (std::nothrow) char[2000];
delete p1;
Modified: trunk/massif/tests/overloaded-new.cpp
===================================================================
--- trunk/massif/tests/overloaded-new.cpp 2007-11-02 21:44:02 UTC (rev 7084)
+++ trunk/massif/tests/overloaded-new.cpp 2007-11-03 11:16:31 UTC (rev 7085)
@@ -10,9 +10,9 @@
using std::nothrow_t;
// A big structure. Its details don't matter.
-struct s {
- int array[1000];
-};
+typedef struct {
+ int array[1000];
+ } s;
void* operator new (std::size_t n) throw (std::bad_alloc)
{
@@ -46,8 +46,8 @@
int main(void)
{
- struct s* p1 = new struct s;
- struct s* p2 = new (std::nothrow) struct s;
+ s* p1 = new s;
+ s* p2 = new (std::nothrow) s;
char* c1 = new char[2000];
char* c2 = new (std::nothrow) char[2000];
delete p1;
|
|
From: Tom H. <th...@cy...> - 2007-11-03 03:23:38
|
Nightly build on dellow ( x86_64, Fedora 7 ) started at 2007-11-03 03:10:03 GMT Results differ from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 320 tests, 4 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/scalar (stderr) memcheck/tests/xml1 (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) ================================================= == Results from 24 hours ago == ================================================= Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 320 tests, 5 stderr failures, 4 stdout failures, 8 post failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/scalar (stderr) memcheck/tests/xml1 (stderr) massif/tests/basic (post) massif/tests/custom_alloc (post) massif/tests/deep-D (post) massif/tests/ignoring (post) massif/tests/new-cpp (post) massif/tests/overloaded-new (post) massif/tests/peak (post) massif/tests/peak2 (stderr) massif/tests/peak2 (post) none/tests/mremap (stderr) none/tests/mremap2 (stdout) none/tests/pth_cvsimple (stdout) none/tests/pth_detached (stdout) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Sat Nov 3 03:16:55 2007 --- new.short Sat Nov 3 03:23:38 2007 *************** *** 8,10 **** ! == 320 tests, 5 stderr failures, 4 stdout failures, 8 post failures == memcheck/tests/pointer-trace (stderr) --- 8,10 ---- ! == 320 tests, 4 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) *************** *** 13,27 **** memcheck/tests/xml1 (stderr) - massif/tests/basic (post) - massif/tests/custom_alloc (post) - massif/tests/deep-D (post) - massif/tests/ignoring (post) - massif/tests/new-cpp (post) - massif/tests/overloaded-new (post) - massif/tests/peak (post) - massif/tests/peak2 (stderr) - massif/tests/peak2 (post) none/tests/mremap (stderr) none/tests/mremap2 (stdout) - none/tests/pth_cvsimple (stdout) - none/tests/pth_detached (stdout) --- 13,16 ---- |
|
From: Tom H. <th...@cy...> - 2007-11-03 03:23:17
|
Nightly build on lloyd ( x86_64, Fedora 7 ) started at 2007-11-03 03:05:06 GMT Results differ from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 320 tests, 4 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/scalar (stderr) memcheck/tests/xml1 (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) ================================================= == Results from 24 hours ago == ================================================= Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 320 tests, 5 stderr failures, 2 stdout failures, 8 post failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/scalar (stderr) memcheck/tests/xml1 (stderr) massif/tests/basic (post) massif/tests/custom_alloc (post) massif/tests/deep-D (post) massif/tests/ignoring (post) massif/tests/new-cpp (post) massif/tests/overloaded-new (post) massif/tests/peak (post) massif/tests/peak2 (stderr) massif/tests/peak2 (post) none/tests/mremap (stderr) none/tests/mremap2 (stdout) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Sat Nov 3 03:13:02 2007 --- new.short Sat Nov 3 03:23:16 2007 *************** *** 8,10 **** ! == 320 tests, 5 stderr failures, 2 stdout failures, 8 post failures == memcheck/tests/pointer-trace (stderr) --- 8,10 ---- ! == 320 tests, 4 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) *************** *** 13,23 **** memcheck/tests/xml1 (stderr) - massif/tests/basic (post) - massif/tests/custom_alloc (post) - massif/tests/deep-D (post) - massif/tests/ignoring (post) - massif/tests/new-cpp (post) - massif/tests/overloaded-new (post) - massif/tests/peak (post) - massif/tests/peak2 (stderr) - massif/tests/peak2 (post) none/tests/mremap (stderr) --- 13,14 ---- |
|
From: Tom H. <th...@cy...> - 2007-11-03 03:21:22
|
Nightly build on alvis ( i686, Red Hat 7.3 ) started at 2007-11-03 03:15:02 GMT
Results differ from 24 hours ago
Checking out valgrind source tree ... done
Configuring valgrind ... done
Building valgrind ... done
Running regression tests ... failed
Last 20 lines of verbose log follow echo
fi
gcc -Winline -Wall -Wshadow -g -m32 -Wno-long-long -o long-time long-time.o
if g++ -DHAVE_CONFIG_H -I. -I. -I../.. -I../.. -I../../include -I../../coregrind -I../../include -I../../VEX/pub -g -O2 -MT new-cpp.o -MD -MP -MF ".deps/new-cpp.Tpo" \
-c -o new-cpp.o `test -f 'new-cpp.cpp' || echo './'`new-cpp.cpp; \
then mv -f ".deps/new-cpp.Tpo" ".deps/new-cpp.Po"; \
else rm -f ".deps/new-cpp.Tpo"; exit 1; \
fi
new-cpp.cpp: In function `int main()':
new-cpp.cpp:20: invalid use of undefined type `struct main()::s'
new-cpp.cpp:20: forward declaration of `struct main()::s'
new-cpp.cpp:20: ISO C++ forbids defining types within new
make[4]: *** [new-cpp.o] Error 1
make[4]: Leaving directory `/tmp/vgtest/2007-11-03/valgrind/massif/tests'
make[3]: *** [check-am] Error 2
make[3]: Leaving directory `/tmp/vgtest/2007-11-03/valgrind/massif/tests'
make[2]: *** [check-recursive] Error 1
make[2]: Leaving directory `/tmp/vgtest/2007-11-03/valgrind/massif'
make[1]: *** [check-recursive] Error 1
make[1]: Leaving directory `/tmp/vgtest/2007-11-03/valgrind'
make: *** [check] Error 2
=================================================
== Results from 24 hours ago ==
=================================================
Checking out valgrind source tree ... done
Configuring valgrind ... failed
Last 20 lines of verbose log follow echo
A valgrind/VEX/quote.txt
A valgrind/VEX/Makefile
A valgrind/VEX/LICENSE.README
U valgrind/VEX
Checked out external at revision 1791.
Checked out revision 7079.
Configuring valgrind ... cd valgrind && ./autogen.sh && ./configure --prefix=/tmp/vgtest/2007-11-03/Inst
running: aclocal
running: autoheader
running: automake -a
configure.in: installing `./install-sh'
configure.in: installing `./mkinstalldirs'
configure.in: installing `./missing'
configure.in:116: installing `./config.guess'
configure.in:116: installing `./config.sub'
auxprogs/Makefile.am: installing `./compile'
auxprogs/Makefile.am: installing `./depcomp'
EXTRA_DIST: variable `noinst_SCRIPTS' is used but `noinst_SCRIPTS' is undefined
error: while running 'automake -a'
=================================================
== Difference between 24 hours ago and now ==
=================================================
*** old.short Sat Nov 3 03:16:11 2007
--- new.short Sat Nov 3 03:21:22 2007
***************
*** 2,25 ****
Checking out valgrind source tree ... done
! Configuring valgrind ... failed
Last 20 lines of verbose log follow echo
! A valgrind/VEX/quote.txt
! A valgrind/VEX/Makefile
! A valgrind/VEX/LICENSE.README
! U valgrind/VEX
! Checked out external at revision 1791.
!
! Checked out revision 7079.
! Configuring valgrind ... cd valgrind && ./autogen.sh && ./configure --prefix=/tmp/vgtest/2007-11-03/Inst
! running: aclocal
! running: autoheader
! running: automake -a
! configure.in: installing `./install-sh'
! configure.in: installing `./mkinstalldirs'
! configure.in: installing `./missing'
! configure.in:116: installing `./config.guess'
! configure.in:116: installing `./config.sub'
! auxprogs/Makefile.am: installing `./compile'
! auxprogs/Makefile.am: installing `./depcomp'
! EXTRA_DIST: variable `noinst_SCRIPTS' is used but `noinst_SCRIPTS' is undefined
! error: while running 'automake -a'
--- 2,27 ----
Checking out valgrind source tree ... done
! Configuring valgrind ... done
! Building valgrind ... done
! Running regression tests ... failed
Last 20 lines of verbose log follow echo
! fi
! gcc -Winline -Wall -Wshadow -g -m32 -Wno-long-long -o long-time long-time.o
! if g++ -DHAVE_CONFIG_H -I. -I. -I../.. -I../.. -I../../include -I../../coregrind -I../../include -I../../VEX/pub -g -O2 -MT new-cpp.o -MD -MP -MF ".deps/new-cpp.Tpo" \
! -c -o new-cpp.o `test -f 'new-cpp.cpp' || echo './'`new-cpp.cpp; \
! then mv -f ".deps/new-cpp.Tpo" ".deps/new-cpp.Po"; \
! else rm -f ".deps/new-cpp.Tpo"; exit 1; \
! fi
! new-cpp.cpp: In function `int main()':
! new-cpp.cpp:20: invalid use of undefined type `struct main()::s'
! new-cpp.cpp:20: forward declaration of `struct main()::s'
! new-cpp.cpp:20: ISO C++ forbids defining types within new
! make[4]: *** [new-cpp.o] Error 1
! make[4]: Leaving directory `/tmp/vgtest/2007-11-03/valgrind/massif/tests'
! make[3]: *** [check-am] Error 2
! make[3]: Leaving directory `/tmp/vgtest/2007-11-03/valgrind/massif/tests'
! make[2]: *** [check-recursive] Error 1
! make[2]: Leaving directory `/tmp/vgtest/2007-11-03/valgrind/massif'
! make[1]: *** [check-recursive] Error 1
! make[1]: Leaving directory `/tmp/vgtest/2007-11-03/valgrind'
! make: *** [check] Error 2
|
|
From: Tom H. <th...@cy...> - 2007-11-03 03:05:04
|
Nightly build on gill ( x86_64, Fedora Core 2 ) started at 2007-11-03 03:00:03 GMT Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Last 20 lines of verbose log follow echo then mv -f ".deps/long-time.Tpo" ".deps/long-time.Po"; else rm -f ".deps/long-time.Tpo"; exit 1; fi long-time.c: In function `main': long-time.c:15: warning: ISO C90 forbids mixed declarations and code long-time.c:18: warning: ISO C90 forbids mixed declarations and code gcc -Winline -Wall -Wshadow -g -m64 -Wno-long-long -Wdeclaration-after-statement -o long-time long-time.o if g++ -DHAVE_CONFIG_H -I. -I. -I../.. -I../.. -I../../include -I../../coregrind -I../../include -I../../VEX/pub -g -O2 -MT new-cpp.o -MD -MP -MF ".deps/new-cpp.Tpo" -c -o new-cpp.o new-cpp.cpp; \ then mv -f ".deps/new-cpp.Tpo" ".deps/new-cpp.Po"; else rm -f ".deps/new-cpp.Tpo"; exit 1; fi new-cpp.cpp: In function `int main()': new-cpp.cpp:20: error: invalid use of undefined type `struct main()::s' new-cpp.cpp:20: error: forward declaration of `struct main()::s' new-cpp.cpp:20: error: ISO C++ forbids defining types within new make[4]: *** [new-cpp.o] Error 1 make[4]: Leaving directory `/tmp/vgtest/2007-11-03/valgrind/massif/tests' make[3]: *** [check-am] Error 2 make[3]: Leaving directory `/tmp/vgtest/2007-11-03/valgrind/massif/tests' make[2]: *** [check-recursive] Error 1 make[2]: Leaving directory `/tmp/vgtest/2007-11-03/valgrind/massif' make[1]: *** [check-recursive] Error 1 make[1]: Leaving directory `/tmp/vgtest/2007-11-03/valgrind' make: *** [check] Error 2 |
|
From: <js...@ac...> - 2007-11-03 01:17:50
|
Nightly build on g5 ( SuSE 10.1, ppc970 ) started at 2007-11-03 02:00:01 CET Results differ from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 255 tests, 11 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/deep_templates (stdout) memcheck/tests/leak-cycle (stderr) memcheck/tests/leak-tree (stderr) memcheck/tests/pointer-trace (stderr) massif/tests/culling1 (stderr) massif/tests/culling2 (stderr) massif/tests/deep-C (stderr) massif/tests/peak2 (stderr) massif/tests/realloc (stderr) none/tests/faultstatus (stderr) none/tests/fdleak_cmsg (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) ================================================= == Results from 24 hours ago == ================================================= Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 255 tests, 11 stderr failures, 2 stdout failures, 6 post failures == memcheck/tests/deep_templates (stdout) memcheck/tests/leak-cycle (stderr) memcheck/tests/leak-tree (stderr) memcheck/tests/pointer-trace (stderr) massif/tests/basic (post) massif/tests/culling1 (stderr) massif/tests/culling2 (stderr) massif/tests/custom_alloc (post) massif/tests/deep-C (stderr) massif/tests/deep-D (post) massif/tests/ignoring (post) massif/tests/peak (post) massif/tests/peak2 (stderr) massif/tests/peak2 (post) massif/tests/realloc (stderr) none/tests/faultstatus (stderr) none/tests/fdleak_cmsg (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Sat Nov 3 02:08:30 2007 --- new.short Sat Nov 3 02:17:48 2007 *************** *** 8,10 **** ! == 255 tests, 11 stderr failures, 2 stdout failures, 6 post failures == memcheck/tests/deep_templates (stdout) --- 8,10 ---- ! == 255 tests, 11 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/deep_templates (stdout) *************** *** 13,24 **** memcheck/tests/pointer-trace (stderr) - massif/tests/basic (post) massif/tests/culling1 (stderr) massif/tests/culling2 (stderr) - massif/tests/custom_alloc (post) massif/tests/deep-C (stderr) - massif/tests/deep-D (post) - massif/tests/ignoring (post) - massif/tests/peak (post) massif/tests/peak2 (stderr) - massif/tests/peak2 (post) massif/tests/realloc (stderr) --- 13,18 ---- |