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