|
From: Jeffrey W. <nol...@gm...> - 2011-08-28 03:44:09
|
Hi All,
I want to use double checked initialization for a program, but I'm
catching some warnings from helgrind. A typical use is shown below.
Its kind of tedious to run --gen-suppressions=yes for to develop
suppressions. Plus, the suppression rules are only applicable to the
current name mangling scheme.
Is there a helgrind friendly way to write the initialization so that I
don't get a warning?
Jeff
=============================
static volatile bool init = false;
static shared_ptr<EntityMap> map;
if(!init)
{
MutexLock lock(getClassMutex());
if(!init)
{
// Perform intialization
...
}
}
|
|
From: Bart V. A. <bva...@ac...> - 2011-08-28 07:58:05
|
On Sun, Aug 28, 2011 at 5:44 AM, Jeffrey Walton <nol...@gm...> wrote:
> I want to use double checked initialization for a program, but I'm
> catching some warnings from helgrind. A typical use is shown below.
>
> Its kind of tedious to run --gen-suppressions=yes for to develop
> suppressions. Plus, the suppression rules are only applicable to the
> current name mangling scheme.
>
> Is there a helgrind friendly way to write the initialization so that I
> don't get a warning?
One option is to implement the ANNOTATE_IGNORE_*_{BEGIN,END} macros in
Helgrind (see also helgrind/helgrind.h), another option is to use a
data race detection tool in which these macros are implemented.
Bart.
|
|
From: Milian W. <ma...@mi...> - 2011-08-28 12:47:03
Attachments:
signature.asc
|
On Saturday 27 August 2011 23:44:02 Jeffrey Walton wrote: > Hi All, > > I want to use double checked initialization for a program, but I'm > catching some warnings from helgrind. A typical use is shown below. > > Its kind of tedious to run --gen-suppressions=yes for to develop > suppressions. Plus, the suppression rules are only applicable to the > current name mangling scheme. > > Is there a helgrind friendly way to write the initialization so that I > don't get a warning? Reading http://en.wikipedia.org/wiki/Double-checked_locking I'd think that the warnings are valid - no? Only MSVC apparently interpretes volatile in a way that would make this a safe pattern in C++. Can you explain why you think it's safe to use anyways, i.e. why you want to ignore the warnings? Thanks -- Milian Wolff ma...@mi... http://milianw.de |
|
From: Bart V. A. <bva...@ac...> - 2011-08-28 12:56:07
|
On Sun, Aug 28, 2011 at 2:32 PM, Milian Wolff <ma...@mi...> wrote: > On Saturday 27 August 2011 23:44:02 Jeffrey Walton wrote: >> I want to use double checked initialization for a program, but I'm >> catching some warnings from helgrind. A typical use is shown below. >> >> Its kind of tedious to run --gen-suppressions=yes for to develop >> suppressions. Plus, the suppression rules are only applicable to the >> current name mangling scheme. >> >> Is there a helgrind friendly way to write the initialization so that I >> don't get a warning? > > Reading http://en.wikipedia.org/wiki/Double-checked_locking I'd think that the > warnings are valid - no? Only MSVC apparently interpretes volatile in a way > that would make this a safe pattern in C++. It depends. If a memory barrier is present between initialization of the allocated structure and assignment to the variable "init", the code posted by Jeffrey should be safe even without "init" having been declared volatile. Bart. |
|
From: Jeffrey W. <nol...@gm...> - 2011-08-28 16:17:03
|
On Sun, Aug 28, 2011 at 8:32 AM, Milian Wolff <ma...@mi...> wrote: > On Saturday 27 August 2011 23:44:02 Jeffrey Walton wrote: >> Hi All, >> >> I want to use double checked initialization for a program, but I'm >> catching some warnings from helgrind. A typical use is shown below. >> >> Its kind of tedious to run --gen-suppressions=yes for to develop >> suppressions. Plus, the suppression rules are only applicable to the >> current name mangling scheme. >> >> Is there a helgrind friendly way to write the initialization so that I >> don't get a warning? > > Reading http://en.wikipedia.org/wiki/Double-checked_locking I'd think that the > warnings are valid - no? Only MSVC apparently interpretes volatile in a way > that would make this a safe pattern in C++. > > Can you explain why you think it's safe to use anyways, i.e. why you want to > ignore the warnings? :) (1) Never trust wikipedia. One of the funniest (I recall) was the message to comp.compression where OP asked Dr. Adler why his reference implementation/RFC 1950 differed from wikipedia. "Need peer review: May have found mistake in Adler-32!", http://groups.google.com/group/comp.compression/browse_thread/thread/5a37a9fcd32786fd/9859a0c61a3fb333. (2) In GCC, I'm compiling with -fthreadsafe-statics (in reality, I'm *not* using -fno-threadsafe-statics). (3) For Visual C++ targets, we're using Visual Studio 2005 and above. (4) Order of initialization: either `init` is constructed first, or `shared_ptr<MyObject>` is constructed first. Either way, `init` is false and `shared_ptr<MyObject>` is nullptr before the first test. (5) `volatile` on `init` ensures the generated code performs a read of the memory, and does not use a cached value. (6) I actually examine the assembled code to verify its doing what I want. Jeff |
|
From: Bart V. A. <bva...@ac...> - 2011-08-28 16:26:54
|
On Sun, Aug 28, 2011 at 6:13 PM, Jeffrey Walton <nol...@gm...> wrote: > (1) Never trust wikipedia. Reading your message makes me wonder whether you are familiar with the reason why memory barriers exist, something the Wikipedia authors of the page about double-checked locking clearly are aware of ? Reading the paper "x86-TSO: a rigorous and usable programmer's model for x86 multiprocessors" might help. It does not only discuss memory models in general but also explains why effects like inter-processor store reordering are observed with certain processor families but not with x86 CPUs. Bart. |
|
From: Jeffrey W. <nol...@gm...> - 2011-08-28 16:55:17
|
Thanks Bart, On Sun, Aug 28, 2011 at 12:26 PM, Bart Van Assche <bva...@ac...> wrote: > On Sun, Aug 28, 2011 at 6:13 PM, Jeffrey Walton <nol...@gm...> wrote: >> (1) Never trust wikipedia. > > Reading your message makes me wonder whether you are familiar with the > reason why memory barriers exist, I'm not aware that GCC will change the semantics of the program under these conditions. I could be wrong, though. > something the Wikipedia authors of > the page about double-checked locking clearly are aware of ? It does not change the fact that I do not trust wikipedia. I've found too many mistakes of the years. > the paper "x86-TSO: a rigorous and usable programmer's model for x86 > multiprocessors" might help. It does not only discuss memory models in > general but also explains why effects like inter-processor store > reordering are observed with certain processor families but not with > x86 CPUs. I've read a few papers (and try to follow relevant online discussions), but I will fetch and read this one. Thanks again, Jeff |
|
From: Bart V. A. <bva...@ac...> - 2011-08-28 17:22:43
|
On Sun, Aug 28, 2011 at 6:55 PM, Jeffrey Walton <nol...@gm...> wrote: > On Sun, Aug 28, 2011 at 12:26 PM, Bart Van Assche <bva...@ac...> wrote: >> On Sun, Aug 28, 2011 at 6:13 PM, Jeffrey Walton <nol...@gm...> wrote: >>> (1) Never trust wikipedia. >> >> Reading your message makes me wonder whether you are familiar with the >> reason why memory barriers exist, > > I'm not aware that GCC will change the semantics of the program under > these conditions. I could be wrong, though. What matters here is that without intervening memory barrier store instructions executed by one CPU may be observed in the opposite order by another CPU. This won't happen with x86 CPUs but can happen with e.g. PowerPC and ARM CPUs. When implementing the double-checked locking pattern, one has not only to be careful about instruction reordering by the compiler but also about reordering by the memory subsystem. >> something the Wikipedia authors of >> the page about double-checked locking clearly are aware of ? > > It does not change the fact that I do not trust wikipedia. I've found > too many mistakes of the years. :-) Bart. |
|
From: Julian S. <js...@ac...> - 2011-08-30 11:00:45
|
Just to add my 2 euro-cents (basically Bart said it all already, tho) My impressions are that: 1. Double checked locking is fundamentally broken: http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html 2. Even if you verify by hand the resulting machine code, you still need to deal with the fact that, in general, CPU implementations may reorder appearance of stores on other CPUs: if CPU 1 writes location A and then location B, it may be that CPU 2 observes the write to B before it observes the write to A. 3. Proving that your application's correctness is not affected, and continues not to be affected in future changes, by (2), is a big correctness and maintenance burden 4. If you stick to x86/x86_64 CPUs then you might not have to grapple with (2), since AIUI they do not allow such store-reordering I'm pretty sure that double checked locking falls into the "undefined semantics; implementation can do whatever it likes" department w.r.t. the recently ratified C++ new revision (C++11 ?) One good thing about the new standard is that it has something to say about these kinds of racy code fragments, so at least we can reason about them instead of getting bogged down in "well, it seems to work" style discussions. J |