This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: libstdc++ and race detectors
> You didn't get my point: it was about setting _GLIBCXX_EXTERN_TEMPLATE =
> -1 for your things, like debug-mode does.
Yes, I see now. With setting -D_GLIBCXX_EXTERN_TEMPLATE=-1 the
following patch works:
http://codereview.appspot.com/download/issue1800042_7001.diff
Index: include/ext/atomicity.h
===================================================================
--- include/ext/atomicity.h (revision 162071)
+++ include/ext/atomicity.h (working copy)
@@ -34,6 +34,28 @@
#include <bits/gthr.h>
#include <bits/atomic_word.h>
+// These two macros are required to make libstdc++ race-detector-friendly.
+// By using these macros we are letting a race detector know that
+// all events that occurred before _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(x)
+// happen-before (precede) all events that occurred after the following
+// _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(x).
+// See __decrement_reference_count for an example.
+// By default, these two macros are defined empty -- anyone who wants
+// to use a race detector will need to redefine these macros to call
+// appropriate race detector API.
+//
+// In order to work properly w/o rebuilding libstdc++.so these macros should
+// be used together with -D_GLIBCXX_EXTERN_TEMPLATE=-1.
+//
+// TODO(kcc): do we need to add a link to some external documentation
+// or mention the race detection tools by name?
+#ifndef _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE
+# define _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(a)
+#endif
+#ifndef _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER
+# define _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(a)
+#endif
+
_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
// Functions for portable atomic access.
@@ -98,6 +120,20 @@
#endif
}
+ // Decrement the reference counter by 1 atomically and return the old value.
+ // The code is annotated to be race-detector-friendly
+ // (see the definition of _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER).
+ static _Atomic_word
+ __decrement_reference_count(_Atomic_word* __mem)
+ {
+ _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(__mem);
+ _Atomic_word __res = __gnu_cxx::__exchange_and_add_dispatch(__mem, -1);
+ if (__res == 0) {
+ _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(__mem);
+ }
+ return __res;
+ }
+
_GLIBCXX_END_NAMESPACE
// Even if the CPU doesn't need a memory barrier, we need to ensure
Index: include/bits/basic_string.h
===================================================================
--- include/bits/basic_string.h (revision 162071)
+++ include/bits/basic_string.h (working copy)
@@ -232,8 +232,7 @@
#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
if (__builtin_expect(this != &_S_empty_rep(), false))
#endif
- if (__gnu_cxx::__exchange_and_add_dispatch(&this->_M_refcount,
- -1) <= 0)
+ if
(__gnu_cxx::__decrement_reference_count(&this->_M_refcount) <= 0)
_M_destroy(__a);
} // XXX MT
--kcc