Search code examples
c++valgrindatomicspinlock

Helgrind and atomic_flag


I tried the basic example of using atomic_flag at cplusplus.com. Valgrind's Helgrind tool reports

164 errors from 28 contexts (suppressed: 0 from 0)

with examples such as

==4868== Possible data race during read of size 1 at 0x605220 by thread #3
==4868== Locks held: none
==4868==    at 0x401172: test_and_set (atomic_base.h:176)
==4868==    by 0x401172: append_number(int) (helgrind_spinlock.cpp:12)
[output deleted]
==4868== This conflicts with a previous write of size 1 by thread #2
==4868== Locks held: none
==4868==    at 0x4011C9: clear (atomic_base.h:193)
==4868==    by 0x4011C9: append_number(int) (helgrind_spinlock.cpp:14)
[output deleted]

Is the reference in error on proper use of atomic_flag as a spin lock, or is Helgrind giving a false positive here?


Solution

  • These are false positive. Helgrind does not understand 'low level' synchronisation, it only understands posix synchronisation primitives.

    See user manual http://www.valgrind.org/docs/manual/hg-manual.html#hg-manual.effective-use which e.g. says:

    Make sure your application, and all the libraries it uses, use the POSIX threading primitives. Helgrind needs to be able to see all events pertaining to thread creation, exit, locking and other synchronisation events. To do so it intercepts many POSIX pthreads functions.

    Do not roll your own threading primitives (mutexes, etc) from combinations of the Linux futex syscall, atomic counters, etc. These throw Helgrind's internal what's-going-on models way off course and will give bogus results.

    So, waiting for helgrind to understand e.g. c++ atomic flags, you will have to annotate the code with client requests to let helgrind "see" the synchronisation primitives based on atomic flags.