- publishing free software manuals
Valgrind 3.3 - Advanced Debugging and Profiling for GNU/Linux applications
by J. Seward, N. Nethercote, J. Weidendorfer and the Valgrind Development Team
Paperback (6"x9"), 164 pages
ISBN 0954612051
RRP £12.95 ($19.95)

Get a printed copy>>>

9.4.4 Restoration of Exclusive Ownership

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:

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 */

This program is correct, but using only the mechanisms described so far, Helgrind would report an error at ‘var += 4’. This is because, by that point, ‘var’ is marked as being in the state “shared-modified and protected by the lock ‘mx’”, but is being accessed without locking. Really, what we want is for ‘var’ to return to the parent thread's exclusive ownership after the child thread has exited.

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.

In our example, the result is exactly as we desire: ‘var’ is reacquired exclusively by the parent after the child exits.

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.

ISBN 0954612051Valgrind 3.3 - Advanced Debugging and Profiling for GNU/Linux applicationsSee the print edition