re PR libstdc++/29496 (_M_invalidate function is not thread-safe in GLIBCXX_DEBUG mode)
2006-11-11 Paolo Carlini <pcarlini@suse.de> PR libstdc++/29496 * include/debug/safe_base.h (_Safe_sequence_base::_M_get_mutex, _Safe_iterator_base::_M_get_mutex, _M_attach_single, _M_detach_single): New. * src/debug.cc: Define the latter. (_Safe_sequence_base::_M_detach_all, _M_detach_singular, _M_revalidate_singular, _M_swap): Use the mutex. (_Safe_iterator_base::_M_attach, _M_detach): Adjust, forward to the *_single version. * include/debug/safe_iterator.h (_Safe_iterator<>::_M_attach_single, _M_invalidate_single): New. * include/debug/safe_iterator.tcc: Define. (_Safe_iterator<>::_M_invalidate): Adjust, forward to _M_invalidate_single. * include/debug/safe_sequence.h (_Safe_sequence<>::_M_invalidate_if, _M_transfer_iter): Use the mutex, adjust, forward to the *_single versions of _M_invalidate and _M_attach. * config/abi/pre/gnu.ver (_Safe_sequence_base::_M_get_mutex, _Safe_iterator_base::_M_get_mutex, _M_attach_single, _M_detach_single): Add @GLIBCXX_3.4.10; adjust. * configure.ac (libtool_VERSION): To 6:10:0. * testsuite/util/testsuite_abi.cc (check_version): Add GLIBCXX_3.4.10. * configure: Regenerate. From-SVN: r118701
This commit is contained in:
parent
bc0a33d315
commit
eebbe2c70e
@ -1,3 +1,29 @@
|
||||
2006-11-11 Paolo Carlini <pcarlini@suse.de>
|
||||
|
||||
PR libstdc++/29496
|
||||
* include/debug/safe_base.h (_Safe_sequence_base::_M_get_mutex,
|
||||
_Safe_iterator_base::_M_get_mutex, _M_attach_single, _M_detach_single):
|
||||
New.
|
||||
* src/debug.cc: Define the latter.
|
||||
(_Safe_sequence_base::_M_detach_all, _M_detach_singular,
|
||||
_M_revalidate_singular, _M_swap): Use the mutex.
|
||||
(_Safe_iterator_base::_M_attach, _M_detach): Adjust, forward to the
|
||||
*_single version.
|
||||
* include/debug/safe_iterator.h (_Safe_iterator<>::_M_attach_single,
|
||||
_M_invalidate_single): New.
|
||||
* include/debug/safe_iterator.tcc: Define.
|
||||
(_Safe_iterator<>::_M_invalidate): Adjust, forward to
|
||||
_M_invalidate_single.
|
||||
* include/debug/safe_sequence.h (_Safe_sequence<>::_M_invalidate_if,
|
||||
_M_transfer_iter): Use the mutex, adjust, forward to the *_single
|
||||
versions of _M_invalidate and _M_attach.
|
||||
* config/abi/pre/gnu.ver (_Safe_sequence_base::_M_get_mutex,
|
||||
_Safe_iterator_base::_M_get_mutex, _M_attach_single, _M_detach_single):
|
||||
Add @GLIBCXX_3.4.10; adjust.
|
||||
* configure.ac (libtool_VERSION): To 6:10:0.
|
||||
* testsuite/util/testsuite_abi.cc (check_version): Add GLIBCXX_3.4.10.
|
||||
* configure: Regenerate.
|
||||
|
||||
2006-11-10 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* config/locale/gnu/c_locale.cc (__convert_to_v): Prefer
|
||||
|
@ -120,13 +120,21 @@ GLIBCXX_3.4 {
|
||||
std::__moneypunct_cache*;
|
||||
std::__numpunct_cache*;
|
||||
std::__timepunct_cache*;
|
||||
__gnu_debug::_Safe_iterator_base*;
|
||||
__gnu_debug::_Safe_sequence_base*;
|
||||
__gnu_debug::_Error_formatter*
|
||||
};
|
||||
|
||||
# Names not in an 'extern' block are mangled names.
|
||||
|
||||
# __gnu_debug::_Safe_sequence_base and _Safe_iterator_base
|
||||
_ZN11__gnu_debug19_Safe_sequence_base13_M_detach_allEv;
|
||||
_ZN11__gnu_debug19_Safe_sequence_base18_M_detach_singularEv;
|
||||
_ZN11__gnu_debug19_Safe_sequence_base22_M_revalidate_singularEv;
|
||||
_ZN11__gnu_debug19_Safe_sequence_base7_M_swapERS0_;
|
||||
_ZN11__gnu_debug19_Safe_iterator_base9_M_attachEPNS_19_Safe_sequence_baseEb;
|
||||
_ZN11__gnu_debug19_Safe_iterator_base9_M_detachEv;
|
||||
_ZNK11__gnu_debug19_Safe_iterator_base11_M_singularEv;
|
||||
_ZNK11__gnu_debug19_Safe_iterator_base14_M_can_compareERKS0_;
|
||||
|
||||
# std::string
|
||||
_ZNSsC*;
|
||||
_ZNSsD*;
|
||||
@ -662,8 +670,17 @@ GLIBCXX_3.4.9 {
|
||||
|
||||
_ZNSo9_M_insertEPKc[il];
|
||||
_ZNSt13basic_ostreamIwSt11char_traitsIwEE9_M_insertEPKw[il];
|
||||
|
||||
} GLIBCXX_3.4.8;
|
||||
|
||||
GLIBCXX_3.4.10 {
|
||||
|
||||
_ZN11__gnu_debug19_Safe_sequence_base12_M_get_mutexEv;
|
||||
_ZN11__gnu_debug19_Safe_iterator_base16_M_attach_singleEPNS_19_Safe_sequence_baseEb;
|
||||
_ZN11__gnu_debug19_Safe_iterator_base16_M_detach_singleEv;
|
||||
_ZN11__gnu_debug19_Safe_iterator_base12_M_get_mutexEv;
|
||||
|
||||
} GLIBCXX_3.4.9;
|
||||
|
||||
# Symbols in the support library (libsupc++) have their own tag.
|
||||
CXXABI_1.3 {
|
||||
|
2
libstdc++-v3/configure
vendored
2
libstdc++-v3/configure
vendored
@ -1378,7 +1378,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
### am handles this now? ORIGINAL_LD_FOR_MULTILIBS=$LD
|
||||
|
||||
# For libtool versioning info, format is CURRENT:REVISION:AGE
|
||||
libtool_VERSION=6:9:0
|
||||
libtool_VERSION=6:10:0
|
||||
|
||||
|
||||
# Find the rest of the source tree framework.
|
||||
|
@ -12,7 +12,7 @@ AC_CONFIG_HEADER(config.h)
|
||||
### am handles this now? ORIGINAL_LD_FOR_MULTILIBS=$LD
|
||||
|
||||
# For libtool versioning info, format is CURRENT:REVISION:AGE
|
||||
libtool_VERSION=6:9:0
|
||||
libtool_VERSION=6:10:0
|
||||
AC_SUBST(libtool_VERSION)
|
||||
|
||||
# Find the rest of the source tree framework.
|
||||
|
@ -31,6 +31,8 @@
|
||||
#ifndef _GLIBCXX_DEBUG_SAFE_BASE_H
|
||||
#define _GLIBCXX_DEBUG_SAFE_BASE_H 1
|
||||
|
||||
#include <ext/concurrence.h>
|
||||
|
||||
namespace __gnu_debug
|
||||
{
|
||||
class _Safe_sequence_base;
|
||||
@ -103,6 +105,9 @@ namespace __gnu_debug
|
||||
|
||||
~_Safe_iterator_base() { this->_M_detach(); }
|
||||
|
||||
/** For use in _Safe_iterator. */
|
||||
__gnu_cxx::__mutex& _M_get_mutex();
|
||||
|
||||
public:
|
||||
/** Attaches this iterator to the given sequence, detaching it
|
||||
* from whatever sequence it was attached to originally. If the
|
||||
@ -111,11 +116,17 @@ namespace __gnu_debug
|
||||
*/
|
||||
void _M_attach(_Safe_sequence_base* __seq, bool __constant);
|
||||
|
||||
/** Likewise, but not thread-safe. */
|
||||
void _M_attach_single(_Safe_sequence_base* __seq, bool __constant);
|
||||
|
||||
/** Detach the iterator for whatever sequence it is attached to,
|
||||
* if any.
|
||||
*/
|
||||
void _M_detach();
|
||||
|
||||
/** Likewise, but not thread-safe. */
|
||||
void _M_detach_single();
|
||||
|
||||
/** Determines if we are attached to the given sequence. */
|
||||
bool _M_attached_to(const _Safe_sequence_base* __seq) const
|
||||
{ return _M_sequence == __seq; }
|
||||
@ -196,6 +207,9 @@ namespace __gnu_debug
|
||||
void
|
||||
_M_swap(_Safe_sequence_base& __x);
|
||||
|
||||
/** For use in _Safe_sequence. */
|
||||
__gnu_cxx::__mutex& _M_get_mutex();
|
||||
|
||||
public:
|
||||
/** Invalidates all iterators. */
|
||||
void
|
||||
|
@ -321,10 +321,22 @@ namespace __gnu_debug
|
||||
_M_constant());
|
||||
}
|
||||
|
||||
/** Likewise, but not thread-safe. */
|
||||
void
|
||||
_M_attach_single(const _Sequence* __seq)
|
||||
{
|
||||
_Safe_iterator_base::_M_attach_single(const_cast<_Sequence*>(__seq),
|
||||
_M_constant());
|
||||
}
|
||||
|
||||
/** Invalidate the iterator, making it singular. */
|
||||
void
|
||||
_M_invalidate();
|
||||
|
||||
/** Likewise, but not thread-safe. */
|
||||
void
|
||||
_M_invalidate_single();
|
||||
|
||||
/// Is the iterator dereferenceable?
|
||||
bool
|
||||
_M_dereferenceable() const
|
||||
|
@ -110,24 +110,33 @@ namespace __gnu_debug
|
||||
void
|
||||
_Safe_iterator<_Iterator, _Sequence>::
|
||||
_M_invalidate()
|
||||
{
|
||||
__gnu_cxx::__scoped_lock sentry(this->_M_get_mutex());
|
||||
_M_invalidate_single();
|
||||
}
|
||||
|
||||
template<typename _Iterator, typename _Sequence>
|
||||
void
|
||||
_Safe_iterator<_Iterator, _Sequence>::
|
||||
_M_invalidate_single()
|
||||
{
|
||||
typedef typename _Sequence::iterator iterator;
|
||||
typedef typename _Sequence::const_iterator const_iterator;
|
||||
|
||||
if (!this->_M_singular())
|
||||
{
|
||||
for (_Safe_iterator_base* iter = _M_sequence->_M_iterators; iter;)
|
||||
for (_Safe_iterator_base* __iter = _M_sequence->_M_iterators;
|
||||
__iter; __iter = __iter->_M_next)
|
||||
{
|
||||
iterator* __victim = static_cast<iterator*>(iter);
|
||||
iter = iter->_M_next;
|
||||
iterator* __victim = static_cast<iterator*>(__iter);
|
||||
if (this->base() == __victim->base())
|
||||
__victim->_M_version = 0;
|
||||
}
|
||||
for (_Safe_iterator_base* iter = _M_sequence->_M_const_iterators;
|
||||
iter;)
|
||||
|
||||
for (_Safe_iterator_base* __iter2 = _M_sequence->_M_const_iterators;
|
||||
__iter2; __iter2 = __iter2->_M_next)
|
||||
{
|
||||
const_iterator* __victim = static_cast<const_iterator*>(iter);
|
||||
iter = iter->_M_next;
|
||||
const_iterator* __victim = static_cast<const_iterator*>(__iter2);
|
||||
if (__victim->base() == this->base())
|
||||
__victim->_M_version = 0;
|
||||
}
|
||||
|
@ -124,27 +124,28 @@ namespace __gnu_debug
|
||||
typedef typename _Sequence::iterator iterator;
|
||||
typedef typename _Sequence::const_iterator const_iterator;
|
||||
|
||||
for (_Safe_iterator_base* __iter = _M_iterators; __iter; )
|
||||
{
|
||||
iterator* __victim = static_cast<iterator*>(__iter);
|
||||
__iter = __iter->_M_next;
|
||||
if (!__victim->_M_singular())
|
||||
{
|
||||
if (__pred(__victim->base()))
|
||||
__victim->_M_invalidate();
|
||||
}
|
||||
}
|
||||
__gnu_cxx::__scoped_lock sentry(this->_M_get_mutex());
|
||||
for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
|
||||
{
|
||||
iterator* __victim = static_cast<iterator*>(__iter);
|
||||
__iter = __iter->_M_next;
|
||||
if (!__victim->_M_singular())
|
||||
{
|
||||
if (__pred(__victim->base()))
|
||||
__victim->_M_invalidate_single();
|
||||
}
|
||||
}
|
||||
|
||||
for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2; )
|
||||
{
|
||||
const_iterator* __victim = static_cast<const_iterator*>(__iter2);
|
||||
__iter2 = __iter2->_M_next;
|
||||
if (!__victim->_M_singular())
|
||||
{
|
||||
if (__pred(__victim->base()))
|
||||
__victim->_M_invalidate();
|
||||
}
|
||||
}
|
||||
for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
|
||||
{
|
||||
const_iterator* __victim = static_cast<const_iterator*>(__iter2);
|
||||
__iter2 = __iter2->_M_next;
|
||||
if (!__victim->_M_singular())
|
||||
{
|
||||
if (__pred(__victim->base()))
|
||||
__victim->_M_invalidate_single();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Sequence>
|
||||
@ -160,22 +161,23 @@ namespace __gnu_debug
|
||||
typedef typename _Sequence::iterator iterator;
|
||||
typedef typename _Sequence::const_iterator const_iterator;
|
||||
|
||||
for (_Safe_iterator_base* __iter = __from->_M_iterators; __iter; )
|
||||
{
|
||||
iterator* __victim = static_cast<iterator*>(__iter);
|
||||
__iter = __iter->_M_next;
|
||||
if (!__victim->_M_singular() && __victim->base() == __x.base())
|
||||
__victim->_M_attach(static_cast<_Sequence*>(this));
|
||||
}
|
||||
__gnu_cxx::__scoped_lock sentry(this->_M_get_mutex());
|
||||
for (_Safe_iterator_base* __iter = __from->_M_iterators; __iter;)
|
||||
{
|
||||
iterator* __victim = static_cast<iterator*>(__iter);
|
||||
__iter = __iter->_M_next;
|
||||
if (!__victim->_M_singular() && __victim->base() == __x.base())
|
||||
__victim->_M_attach_single(static_cast<_Sequence*>(this));
|
||||
}
|
||||
|
||||
for (_Safe_iterator_base* __iter2 = __from->_M_const_iterators;
|
||||
__iter2;)
|
||||
{
|
||||
const_iterator* __victim = static_cast<const_iterator*>(__iter2);
|
||||
__iter2 = __iter2->_M_next;
|
||||
if (!__victim->_M_singular() && __victim->base() == __x.base())
|
||||
__victim->_M_attach(static_cast<_Sequence*>(this));
|
||||
}
|
||||
{
|
||||
const_iterator* __victim = static_cast<const_iterator*>(__iter2);
|
||||
__iter2 = __iter2->_M_next;
|
||||
if (!__victim->_M_singular() && __victim->base() == __x.base())
|
||||
__victim->_M_attach_single(static_cast<_Sequence*>(this));
|
||||
}
|
||||
}
|
||||
} // namespace __gnu_debug
|
||||
|
||||
|
@ -35,13 +35,12 @@
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
#include <ext/concurrence.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace
|
||||
{
|
||||
__gnu_cxx::__mutex iterator_base_mutex;
|
||||
__gnu_cxx::__mutex safe_base_mutex;
|
||||
} // anonymous namespace
|
||||
|
||||
namespace __gnu_debug
|
||||
@ -107,43 +106,45 @@ namespace __gnu_debug
|
||||
"attempt to increment an end-of-stream istreambuf_iterator"
|
||||
};
|
||||
|
||||
void
|
||||
void
|
||||
_Safe_sequence_base::
|
||||
_M_detach_all()
|
||||
{
|
||||
for (_Safe_iterator_base* __iter = _M_iterators; __iter; )
|
||||
__gnu_cxx::__scoped_lock sentry(safe_base_mutex);
|
||||
for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
|
||||
{
|
||||
_Safe_iterator_base* __old = __iter;
|
||||
__iter = __iter->_M_next;
|
||||
__old->_M_attach(0, false);
|
||||
__old->_M_detach_single();
|
||||
}
|
||||
|
||||
for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2; )
|
||||
for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
|
||||
{
|
||||
_Safe_iterator_base* __old = __iter2;
|
||||
__iter2 = __iter2->_M_next;
|
||||
__old->_M_attach(0, true);
|
||||
__old->_M_detach_single();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
_Safe_sequence_base::
|
||||
_M_detach_singular()
|
||||
{
|
||||
for (_Safe_iterator_base* __iter = _M_iterators; __iter; )
|
||||
__gnu_cxx::__scoped_lock sentry(safe_base_mutex);
|
||||
for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
|
||||
{
|
||||
_Safe_iterator_base* __old = __iter;
|
||||
__iter = __iter->_M_next;
|
||||
if (__old->_M_singular())
|
||||
__old->_M_attach(0, false);
|
||||
__old->_M_detach_single();
|
||||
}
|
||||
|
||||
for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2; )
|
||||
for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
|
||||
{
|
||||
_Safe_iterator_base* __old = __iter2;
|
||||
__iter2 = __iter2->_M_next;
|
||||
if (__old->_M_singular())
|
||||
__old->_M_attach(0, true);
|
||||
__old->_M_detach_single();
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,6 +152,7 @@ namespace __gnu_debug
|
||||
_Safe_sequence_base::
|
||||
_M_revalidate_singular()
|
||||
{
|
||||
__gnu_cxx::__scoped_lock sentry(safe_base_mutex);
|
||||
for (_Safe_iterator_base* __iter = _M_iterators; __iter;
|
||||
__iter = __iter->_M_next)
|
||||
__iter->_M_version = _M_version;
|
||||
@ -160,10 +162,11 @@ namespace __gnu_debug
|
||||
__iter2->_M_version = _M_version;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
_Safe_sequence_base::
|
||||
_M_swap(_Safe_sequence_base& __x)
|
||||
{
|
||||
__gnu_cxx::__scoped_lock sentry(safe_base_mutex);
|
||||
swap(_M_iterators, __x._M_iterators);
|
||||
swap(_M_const_iterators, __x._M_const_iterators);
|
||||
swap(_M_version, __x._M_version);
|
||||
@ -177,17 +180,29 @@ namespace __gnu_debug
|
||||
for (__iter = __x._M_const_iterators; __iter; __iter = __iter->_M_next)
|
||||
__iter->_M_sequence = &__x;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
__gnu_cxx::__mutex&
|
||||
_Safe_sequence_base::
|
||||
_M_get_mutex()
|
||||
{ return safe_base_mutex; }
|
||||
|
||||
void
|
||||
_Safe_iterator_base::
|
||||
_M_attach(_Safe_sequence_base* __seq, bool __constant)
|
||||
{
|
||||
_M_detach();
|
||||
__gnu_cxx::__scoped_lock sentry(safe_base_mutex);
|
||||
_M_attach_single(__seq, __constant);
|
||||
}
|
||||
|
||||
void
|
||||
_Safe_iterator_base::
|
||||
_M_attach_single(_Safe_sequence_base* __seq, bool __constant)
|
||||
{
|
||||
_M_detach_single();
|
||||
|
||||
// Attach to the new sequence (if there is one)
|
||||
if (__seq)
|
||||
{
|
||||
__gnu_cxx::__scoped_lock sentry(iterator_base_mutex);
|
||||
_M_sequence = __seq;
|
||||
_M_version = _M_sequence->_M_version;
|
||||
_M_prior = 0;
|
||||
@ -208,11 +223,18 @@ namespace __gnu_debug
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
_Safe_iterator_base::
|
||||
_M_detach()
|
||||
{
|
||||
__gnu_cxx::__scoped_lock sentry(iterator_base_mutex);
|
||||
__gnu_cxx::__scoped_lock sentry(safe_base_mutex);
|
||||
_M_detach_single();
|
||||
}
|
||||
|
||||
void
|
||||
_Safe_iterator_base::
|
||||
_M_detach_single()
|
||||
{
|
||||
if (_M_sequence)
|
||||
{
|
||||
// Remove us from this sequence's list
|
||||
@ -232,7 +254,7 @@ namespace __gnu_debug
|
||||
_M_prior = 0;
|
||||
_M_next = 0;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
_Safe_iterator_base::
|
||||
_M_singular() const
|
||||
@ -246,6 +268,11 @@ namespace __gnu_debug
|
||||
&& !__x._M_singular() && _M_sequence == __x._M_sequence);
|
||||
}
|
||||
|
||||
__gnu_cxx::__mutex&
|
||||
_Safe_iterator_base::
|
||||
_M_get_mutex()
|
||||
{ return safe_base_mutex; }
|
||||
|
||||
void
|
||||
_Error_formatter::_Parameter::
|
||||
_M_print_field(const _Error_formatter* __formatter, const char* __name) const
|
||||
|
@ -188,6 +188,7 @@ check_version(symbol& test, bool added)
|
||||
known_versions.push_back("GLIBCXX_3.4.7");
|
||||
known_versions.push_back("GLIBCXX_3.4.8");
|
||||
known_versions.push_back("GLIBCXX_3.4.9");
|
||||
known_versions.push_back("GLIBCXX_3.4.10");
|
||||
known_versions.push_back("GLIBCXX_LDBL_3.4");
|
||||
known_versions.push_back("GLIBCXX_LDBL_3.4.7");
|
||||
known_versions.push_back("CXXABI_1.3");
|
||||
|
Loading…
Reference in New Issue
Block a user