This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]