This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: libstdc++ and race detectors
>>
>> The shared_ptr refcounts in bits/boost_sp_counted_base.h should be
>> able to use the same approach for _M_release and _M_weak_release,
>
> Looks like. Let me test this too...
Yes, tr1_impl/boost_sp_counted_base.h requires the same annotations.
===================================================================
--- tr1_impl/boost_sp_counted_base.h (revision 162071)
+++ tr1_impl/boost_sp_counted_base.h (working copy)
@@ -139,8 +139,10 @@
void
_M_release() // nothrow
{
+ _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count);
if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
{
+ _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count);
_M_dispose();
// There must be a memory barrier between dispose() and destroy()
// to ensure that the effects of dispose() are observed in the
@@ -152,8 +154,10 @@
_GLIBCXX_WRITE_MEM_BARRIER;
}
+ _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
-1) == 1)
+ _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
_M_destroy();
}
}
@@ -165,8 +169,10 @@
void
_M_weak_release() // nothrow
{
+ _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
{
+ _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
if (_Mutex_base<_Lp>::_S_need_barriers)
{
// See _M_release(),
I just tested this with the following test:
% cat shared_ptr_test.cc
#define _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(a) ANNOTATE_HAPPENS_BEFORE(a)
#define _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(a) ANNOTATE_HAPPENS_AFTER(a)
#include "dynamic_annotations.h"
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <assert.h>
#include <memory>
using namespace std;
shared_ptr<int> *s;
pthread_mutex_t mu;
pthread_cond_t cv;
int done = 0;
void *Thread(void*) {
shared_ptr<int> x(*s);
pthread_mutex_lock(&mu);
done++;
pthread_cond_signal(&cv);
pthread_mutex_unlock(&mu);
assert(*x == 7);
// x is destructed
}
const int kNThreads = 3;
int main() {
s = new shared_ptr<int>(new int (7));
pthread_t t[kNThreads];
pthread_mutex_init(&mu, 0);
pthread_cond_init(&cv, 0);
// start threads.
for (int i = 0; i < kNThreads; i++) {
pthread_create(&t[i], 0, Thread, 0);
}
// wait for threads to copy 's', but don't wait for threads to exit.
pthread_mutex_lock(&mu);
while (done != kNThreads)
pthread_cond_wait(&cv, &mu);
pthread_mutex_unlock(&mu);
delete s;
}
W/o defining the annotations there is a race report:
$ g++ -g -std=c++0x -pthread shared_ptr_test.cc && tsan ./a.out
With the annotations the tool is silent.
--kcc