On Sunday 26 August 2012 01:30:43 David Faure wrote:
> On Saturday 25 August 2012 22:43:58 Julian Seward wrote:
> > Or maybe Qt really is racey
> 
> Bingo :)

OK, maybe not. Turns out the code runs as intended by the Qt developers.

Marc Mutz said "
The standard says it's racy, but the implementation of 
std::atomic::load(memory_order_acquire) won't look different. Simple reads 
and writes on x86 are already sequentially consistent. Think MESI cache 
coherency. Before a CPU writes to a memory location it needs to acquire 
exclusive ownership (E) of the cache line, the well-known "hardware mutex" on 
a cache line that produces False Sharing, too. This seems to hold for all 
architectures, cf. threads re: "Brief example ..." at 
http://www.decadent.org.uk/pipermail/cpp-threads/2008-December/thread.html
"

I attached a pure C++ testcase of the issue. Compile it with
g++ testcase_atomic_ops_helgrind.cpp -o testcase_atomic_ops_helgrind -lpthread

Thiago expects that helgrind can't autodetect this case and that helgrind-
macros markup is needed in Qt, I'm fine with adding that if you guys agree -- 
after you show me how by modifying the attached example :-)

Thanks.

-- 
David Faure, fa...@kde.org, http://www.davidfaure.fr
Sponsored by Nokia to work on KDE, incl. KDE Frameworks 5
#include <pthread.h>

template <typename T> struct QAtomicOps // qgenericatomic.h
{
    static inline
    T loadAcquire(const T &_q_value)
    {
        T tmp = *static_cast<const volatile T *>(&_q_value);
        return tmp;
    }

    static inline
    void storeRelease(T &_q_value, T newValue)
    {
        *static_cast<volatile T *>(&_q_value) = newValue;
    }
};

class QBasicAtomicInt // qbasicatomic.h
{
public:
    typedef QAtomicOps<int> Ops;
    int _q_value;

    int loadAcquire() const { return Ops::loadAcquire(_q_value); }
    void storeRelease(int newValue) { Ops::storeRelease(_q_value, newValue); }
};

// Modelled after qt_metatype_id()
static int onDemandNumber() {
    static QBasicAtomicInt sharedInt = { 0 };
    if (!sharedInt.loadAcquire()) {
        // some calculation goes here
        sharedInt.storeRelease(42);
    }
    return sharedInt.loadAcquire();
}

void * threadStart(void *)
{
    onDemandNumber();
    onDemandNumber();
    onDemandNumber();
    onDemandNumber();
    return 0;
}


int main( int argc, char** argv ) {
    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;
}




------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Valgrind-users mailing list
Valgrind-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/valgrind-users

Reply via email to