From: Phil L. <plo...@sa...> - 2013-05-14 20:31:43
|
According to the helgrind manual "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". Two possible ways to interpret this: Scenario #1: int shared_value; pthread_mutex_t lock; Thread 1: pthread_mutex_lock(&lock); shared_value = 10; pthread_mutex_unlock(&lock); Thread 2: pthread_mutex_lock(&lock); ... = shared_value; pthread_mutex_unlock(&lock); For this, no data race on shared_value should be reported; Scenario #2: pthread_mutex_t lock; int* shared_ptr; Thread 1: int* my_ptr = new int; *my_ptr = 10; pthread_mutex_lock(&lock); shared_ptr = my_ptr; pthread_mutex_unlock(&lock); Thread 2: pthread_mutex_lock(&lock); int* my_ptr = shared_ptr; pthread_mutex_unlock(&lock); ... = *my_ptr; In this case, there should be no data race on shared_ptr, similar to scenario #1. Will helgrind report a data race on the memory shared_ptr points to, or is memory only deemed to be safe while a semaphore is locked. Phil ----- Phil Longstaff Senior Software Engineer x2904 |
From: David F. <fa...@kd...> - 2013-05-16 18:29:38
|
On Tuesday 14 May 2013 20:18:44 Phil Longstaff wrote: > int* my_ptr = new int; > *my_ptr = 10; > pthread_mutex_lock(&lock); > shared_ptr = my_ptr; > pthread_mutex_unlock(&lock); > > Thread 2: > pthread_mutex_lock(&lock); > int* my_ptr = shared_ptr; > pthread_mutex_unlock(&lock); > ... = *my_ptr; You're reading a region of memory outside mutex protection, and that region of memory was written to, outside mutex protection. That's the basic definition of a data race. Getting the address of that region of memory within the mutex doesn't change that. You see it as non-racy because "how could *my_ptr ever be something else than 10" ... but if you think about a multi-processor system, the write of the value 10 might not get propagated to the cache of the other processor where the read happens, since the system had no reason to perform that synchronisation. -- David Faure, fa...@kd..., http://www.davidfaure.fr Working on KDE, in particular KDE Frameworks 5 |
From: Phil L. <plo...@sa...> - 2013-05-22 15:52:38
|
We discussed this internally, and think that the pthread_mutex_unlock() call will provide the memory barrier to force synchronization. " Yes, pthread_mutex_unlock is a memory barrier (it would be quite useless otherwise). Chapter and verse: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_11 The problem with helgrind is that it will have a very hard time proving that the second thread cannot access the shared memory until after the pthread_mutex_unlock() has occurred. Some kind of helgrind annotation for this worker queue case would probably be the easiest way out." -----Original Message----- From: David Faure [mailto:fa...@kd...] Sent: Thursday, May 16, 2013 2:34 PM To: val...@li... Cc: Phil Longstaff Subject: Re: [Valgrind-users] Helgrind data race question On Tuesday 14 May 2013 20:18:44 Phil Longstaff wrote: > int* my_ptr = new int; > *my_ptr = 10; > pthread_mutex_lock(&lock); > shared_ptr = my_ptr; > pthread_mutex_unlock(&lock); > > Thread 2: > pthread_mutex_lock(&lock); > int* my_ptr = shared_ptr; > pthread_mutex_unlock(&lock); > ... = *my_ptr; You're reading a region of memory outside mutex protection, and that region of memory was written to, outside mutex protection. That's the basic definition of a data race. Getting the address of that region of memory within the mutex doesn't change that. You see it as non-racy because "how could *my_ptr ever be something else than 10" ... but if you think about a multi-processor system, the write of the value 10 might not get propagated to the cache of the other processor where the read happens, since the system had no reason to perform that synchronisation. -- David Faure, fa...@kd..., http://www.davidfaure.fr Working on KDE, in particular KDE Frameworks 5 |