From: Bart Van Assche Date: Sat, 11 Oct 2008 18:28:12 +0000 (+0000) Subject: Added paragraph "Using the POSIX Threads API Effectively." X-Git-Tag: svn/VALGRIND_3_4_0~232 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e9a7bafd89be33bfe17bf621632bf9abda8d66bb;p=thirdparty%2Fvalgrind.git Added paragraph "Using the POSIX Threads API Effectively." git-svn-id: svn://svn.valgrind.org/valgrind/trunk@8656 --- diff --git a/drd/docs/drd-manual.xml b/drd/docs/drd-manual.xml index e1874299a6..56e13c72b5 100644 --- a/drd/docs/drd-manual.xml +++ b/drd/docs/drd-manual.xml @@ -993,12 +993,12 @@ are started. This is possible by adding a line similar to the following to your shell startup script: As an example, the test OpenMP test program -drd/scripts/omp_matinv triggers a data race +drd/tests/omp_matinv triggers a data race when the option -r has been specified on the command line. The data race is triggered by the following code: @@ -1046,7 +1046,7 @@ source file name and the line number where the data race has been detected Note: DRD reports errors on the libgomp library -included with gcc 4.2.0 up to and including 4.3.1. This might indicate +included with gcc 4.2.0 up to and including 4.3.2. This might indicate a race condition in the POSIX version of libgomp. @@ -1238,6 +1238,165 @@ The following information may be helpful when using DRD: + +Using the POSIX Threads API Effectively + + +Mutex types + + +The Single UNIX Specification version two defines the following four +mutex types (see also the documentation of pthread_mutexattr_settype()): + + + + normal, which means that no error checking + is performed, and that the mutex is non-recursive. + + + + + error checking, which means that the mutex + is non-recursive and that error checking is performed. + + + + + recursive, which means that a mutex may be + locked recursively. + + + + + default, which means that error checking + behavior is undefined, and that the behavior for recursive + locking is also undefined. Or: portable code must neither + trigger error conditions through the Pthreads API nor attempt to + lock a mutex of default type recursively. + + + + + + +In complex applications it is not always clear from beforehand which +mutex will be locked recursively and which mutex will not be locked +recursively. Attempts lock a non-recursive mutex recursively will +result in race conditions that are very hard to find without a thread +checking tool. So either use the error checking mutex type and +consistently check the return value of Pthread API mutex calls, or use +the recursive mutex type. + + + + + +Condition variables + + +A condition variable allows one thread to wake up one or more other +threads. Condition variables are typically used to notify one or more +threads about state changes of shared data. Unfortunately it is very +easy to introduce race conditions by using condition variables as the +only means of state information propagation. A better approach is to +let threads poll for changes of a state variable that is protected by +a mutex, and to use condition variables only as a thread wakeup +mechanism. See also the source file +drd/tests/monitor_example.cpp for an +example of how to implement this concept in C++. The monitor concept +used in this example is a well known concept in computer science -- +see also Wikipedia for more information about the monitor +concept. + + + + + +pthread_cond_timedwait() and timeouts + + +Historically the function +pthread_cond_timedwait() only allowed the +specification of an absolute timeout, that is a timeout independent of +the time when this function was called. However, almost every call to +this function expresses a relative timeout. This typically happens by +passing the sum of +clock_gettime(CLOCK_REALTIME) and a +relative timeout as the third argument. This approach is incorrect +since forward or backward clock adjustments by e.g. ntpd will affect +the timeout. A more reliable approach is as follows: + + + + When initializing a condition variable through + pthread_cond_init(), specify that the timeout of + pthread_cond_timedwait() will use the clock + CLOCK_MONOTONIC instead of + CLOCK_REALTIME. You can do this via + pthread_condattr_setclock(..., + CLOCK_MONOTONIC). See also + drd/tests/monitor_example.cpp + for an example. + + + + + When calling pthread_cond_timedwait(), pass + the sum of + clock_gettime(CLOCK_MONOTONIC) + and a relative timeout as the third argument. + + + + + + + + +Assigning names to threads + + +Many applications log information about changes in internal or +external state to a file. When analyzing log files of a multithreaded +application it can be very convenient to know which thread logged +which information. One possible approach is to identify threads in +logging output by including the result of +pthread_self() in every log line. However, this approach +has two disadvantages: there is no direct relationship between these +values and the source code and these values can be different in each +run. A better approach is to assign a brief name to each thread and to +include the assigned thread name in each log line. One possible +approach for managing thread names is as follows: + + + + Allocate a key for the pointer to the thread name through + pthread_key_create(). + + + + + Just after thread creation, set the thread name through + pthread_setspecific(). + + + + + In the code that generates the logging information, query the thread + name by calling pthread_getspecific(). + + + + + + + + + + + Limitations