On Tuesday 19 August 2014 21:57:02 Philippe Waroquiers wrote:
> On Tue, 2014-08-19 at 21:44 +0200, David Faure wrote:
> > On Tuesday 19 August 2014 21:00:58 Philippe Waroquiers wrote:
> > > On Tue, 2014-08-19 at 16:46 +0200, Roland Mainz wrote:
> > > > > ThreadSanitizer won't comprehend the fence instructions inserted by
> > > > > urcu.
> > > > > I believe even Helgrind won't, because these instructions do not
> > > > > imply
> > > > > any happens-before relation.
> > > > 
> > > > Is there any opensource or commercial tool which might help in such
> > > > situations (e.g. problems with memory barriers) ?
> > > 
> > > helgrind or drd or ThreadSanitizer could still be used for race
> > > condition detection but you would have to annotate either the rcu
> > > library or the calling code to describe the happens before
> > > relationships.
> > 
> > Are such annotations documented somewhere?
> 
> http://www.valgrind.org/docs/manual/hg-manual.html#hg-manual.client-requests
> gives a list of such annotations, and points to helgrind.h for more
> information.

Thanks.

> > I'm still trying to find a way to annotate threadsafe-statics so that
> > helgrind doesn't complain about them.
> 
> What is a threadsafe-static ?

See older mail to this list, attached.

It doesn't use __thread anywhere, but rather lets gcc take care of ensuring 
thread-safety on static objects (like C++11 mandates, but it has been doing so 
for a long time already).

Is that related to nptl (I'm not sure what that is exactly)?

-- 
David Faure, fa...@kde.org, http://www.davidfaure.fr
Working on KDE Frameworks 5
--- Begin Message ---
Hello,

I'm using helgrind quite a lot these days, and I love it.

However I wonder if it doesn't give me false positives for the case of reading 
a value from a static object, which was set in the constructor.

Given that gcc does indeed implement "threadsafe statics" as per C++11 (but 
even before C++11 came out), one can assume that gcc does "something like" a 
mutex around the creation of the object, and therefore that there is a 
"happens before" relation between the end of the constructor and the use of 
this object later on, right?

In that case it would seem that helgrind needs to learn that, to avoid many 
false positives.

Testcase attached.

The assembly code says
        call    __cxa_guard_acquire
        testl   %eax, %eax
        je      .L3
        .loc 1 16 0 discriminator 2
        movl    $_ZZ11threadStartPvE9singleton, %edi
        call    _ZN9SingletonC1Ev
        movl    $_ZGVZ11threadStartPvE9singleton, %edi
        call    __cxa_guard_release
.L3:

IIRC __cxa_guard_acquire/release is the protection around the static, but I'm 
not sure exactly what this means. Is there an actual happens-before relation 
here?

helgrind log:

==31469== Possible data race during read of size 4 at 0x602068 by thread #3
==31469== Locks held: none
==31469==    at 0x400ADF: threadStart(void*) (testcase_local_static.cpp:17)
==31469==    by 0x4C2D151: mythread_wrapper (hg_intercepts.c:233)
==31469==    by 0x4E3C0DA: start_thread (pthread_create.c:309)
==31469==    by 0x595B90C: clone (clone.S:111)
==31469== 
==31469== This conflicts with a previous write of size 4 by thread #2
==31469== Locks held: none
==31469==    at 0x400BC6: Singleton::Singleton() (testcase_local_static.cpp:9)
==31469==    by 0x400AD4: threadStart(void*) (testcase_local_static.cpp:16)
==31469==    by 0x4C2D151: mythread_wrapper (hg_intercepts.c:233)
==31469==    by 0x4E3C0DA: start_thread (pthread_create.c:309)
==31469==    by 0x595B90C: clone (clone.S:111)


-- 
David Faure, fa...@kde.org, http://www.davidfaure.fr
Working on KDE Frameworks 5
#include <pthread.h>
#include <stdio.h>

// gcc is supposed to have threadsafe statics

class Singleton
{
public:
    Singleton() : value(42) {}

    int value;
};

void * threadStart(void *)
{
    static Singleton singleton;
    printf("%d\n", singleton.value);
    printf("%d\n", singleton.value);
    printf("%d\n", singleton.value);
    printf("%d\n", singleton.value);
    printf("%d\n", singleton.value);
    return 0;
}

int main( int , char** ) {
    pthread_t thread1;
    if ( pthread_create(&thread1, 0, threadStart, 0) )
        return 1;
    pthread_t thread2;
    if ( pthread_create(&thread2, 0, threadStart, 0) )
        return 1;

    void* v;
    pthread_join(thread1, &v);
    pthread_join(thread2, &v);
    return 0;
}


--- End Message ---
------------------------------------------------------------------------------
_______________________________________________
Valgrind-users mailing list
Valgrind-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/valgrind-users

Reply via email to