From a28836bab78f774c8d95de73f5dd9c4b9d60e80a Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 28 Jun 2008 16:47:22 +0000 Subject: [PATCH] Continued working on the DRD documentation. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@8303 --- exp-drd/docs/drd-manual.xml | 318 +++++++++++++++++++++++++++++++++++- 1 file changed, 313 insertions(+), 5 deletions(-) diff --git a/exp-drd/docs/drd-manual.xml b/exp-drd/docs/drd-manual.xml index 75a546faec..fec377b5ec 100644 --- a/exp-drd/docs/drd-manual.xml +++ b/exp-drd/docs/drd-manual.xml @@ -323,6 +323,29 @@ behavior of the DRD tool itself: + + + + + + + Whether to report calls to + pthread_cond_signal() and + pthread_cond_broadcast()where the mutex + associated with the signal via + pthread_cond_wait() or + pthread_cond_timed_wait()is not locked at + the time the signal is sent. Sending a signal without holding + a lock on the associated mutex is a common programming error + which can cause subtle race conditions and unpredictable + behavior. There exist some uncommon synchronization patterns + however where it is safe to send a signal without holding a + lock on the associated mutex. + + + @@ -482,16 +505,306 @@ process being analyzed with DRD: Data Races + + +DRD prints a message every time it detects a data race. You should be +aware of the following when interpreting DRD's output: + + + + Every thread is assigned two thread ID's: + one thread ID is assigned by the Valgrind core and one thread ID + is assigned by DRD. Both thread ID's start at one. Valgrind + thread ID's are reused when one thread finishes and another + thread is created. DRD does not reuse thread ID's. Thread ID's + are displayed e.g. as follows: 2/3, where the first number is + Valgrind's thread ID and the second number is the thread ID + assigned by DRD. + + + + + The term segment refers to a consecutive + sequence of load, store and synchronization operations, all + issued by the same thread. A segment always starts and ends at a + synchronization operation. Data race analysis is performed + between segments instead of between individual load and store + operations because of performance reasons. + + + + + There are always at least two memory accesses involved in a data + race. Memory accesses involved in a data race are called + conflicting memory accesses. DRD prints a + report for each memory access that conflicts with a past memory + access. + + + + + + +Below you can find an example of a message printed by DRD when it +detects a data race: + + + + +The above report has the following meaning: + + + + The number in the column on the left is the process ID of the + process being analyzed by DRD. + + + + + The first line ("Thread 3") tells you Valgrind's thread ID for + the thread in which context the data race was detected. + + + + + The next line tells which kind of operation was performed (load + or store) and by which thread. Both Valgrind's and DRD's thread + ID's are displayed. On the same line the start address and the + number of bytes involved in the conflicting access are also + displayed. + + + + + Next, the call stack of the conflicting access is displayed. If + your program has been compiled with debug information (-g), this + call stack will include file names and line numbers. The two + bottommost frames in this call stack (clone + and start_thread) show how the NPTL starts a + thread. The third frame (vg_thread_wrapper) + is added by DRD. The fourth frame + (thread_func) is interesting because it + shows the thread entry point, that is the function that has been + passed as the third argument to + pthread_create(). + + + + + Next, the allocation context for the conflicting address is + displayed. For static and stack variables the allocation context + is only shown when the option + --var-info=yes has been + specified. Otherwise DRD will print Allocation + context: unknown for such variables. + + + + + A conflicting access involves at least two memory accesses. For + one of these accesses an exact call stack is displayed, and for + the other accesses an approximate call stack is displayed, + namely the start and the end of the segments of the other + accesses. This information can be interpreted as follows: + + + + Start at the bottom of both call stacks, and count the + number stack frames with identical function name, file + name and line number. In the above example the three + bottommost frames are identical + (clone, + start_thread and + vg_thread_wrapper). + + + + + The next higher stack frame in both call stacks now tells + you between in which source code region the other memory + access happened. The above output tells that the other + memory access involved in the data race happened between + source code lines 28 and 30 in file + rwlock_race.c. + + + + + + + + Lock Contention + + +Threads should be able to make progress without being blocked by other +threads. Unfortunately this is not always true. Sometimes a thread +has to wait until a mutex or reader-writer lock is unlocked by another +thread. This is called lock contention. The more +granular the locks are, the less likely lock contention will +occur. The most unfortunate situation occurs when I/O is performed +while a lock is held. + + + +Lock contention causes delays and hence should be avoided. The two +command line options +--exclusive-threshold=<n> and +--shared-threshold=<n> make it possible to +detect lock contention by making DRD report any lock that is held +longer than the specified threshold. An example: + + + + +The hold_lock test program holds a lock as long as +specified by the -i (interval) argument. The DRD +output reports that the lock acquired at line 51 in source file +hold_lock.c and released at line 55 was held during +503 ms, while a threshold of 10 ms was specified to DRD. + + Misuse of the POSIX threads API + + + DRD is able to detect and report the following misuses of the POSIX + threads API: + + + + Passing the address of one type of synchronization object + (e.g. a mutex) to a POSIX API call that expects a pointer to + another type of synchronization object (e.g. a condition + variable). + + + + + Attempt to unlock a mutex that has not been locked. + + + + + Attempt to unlock a mutex that was locked by another thread. + + + + + Attempt to lock a mutex of type + PTHREAD_MUTEX_NORMAL or a spinlock + recursively. + + + + + Destruction or deallocation of a locked mutex. + + + + + Sending a signal to a condition variable while no lock is held + on the mutex associated with the signal. + + + + + Calling pthread_cond_wait() with a mutex + that is not locked, that is locked by another thread or that + has been locked recursively. + + + + + Associating two different mutexes with a condition variable + via pthread_cond_wait(). + + + + + Destruction or deallocation of a condition variable that is + being waited upon. + + + + + Destruction or deallocation of a locked reader-writer lock. + + + + + Attempt to unlock a reader-writer lock that was not locked by + the calling thread. + + + + + Attempt to recursively lock a reader-writer lock exclusively. + + + + + Reinitialization of a mutex, condition variable, reader-writer + lock, semaphore or barrier. + + + + + Destruction or deallocation of a semaphore or barrier that is + being waited upon. + + + + + Exiting a thread without first unlocking the spinlocks, + mutexes or reader-writer locks that were locked by that + thread. + + + + + @@ -509,11 +822,6 @@ from a client program to the DRD tool. Debugging OpenMP Programs With DRD - -Just as for other Valgrind tools it is possible to pass information -from a client program to the DRD tool. - - For more information about OpenMP, see also openmp.org. -- 2.47.2