re PR libstdc++/36801 (config/cpu/generic/atomicity_mutex/atomicity.h incorrectly relies on global constructor ordering)

2009-01-07  Benjamin Kosnik  <bkoz@redhat.com>
	    Jonathan Larmour  <jifl@eCosCentric.com>

	PR libstdc++/36801
	* config/cpu/generic/atomicity_mutex/atomicity.h (get_atomic_mutex):
	New.
	(__gnu_cxx::__exchange_and_add): Use it.
	* src/atomic.cc (get_atomic_mutex): New.
	* src/debug.cc (get_safe_base_mutex): New.
	* src/locale.cc (get_locale_cache_mutex): New.
	* src/mt_allocator.cc (get_freelist): New.
	(get_freelist_mutex): New.
	* src/pool_allocator.cc (get_palloc_mutex): New.
	* include/std/mutex (__once_functor_lock): To
	(__get_once_functor_lock): ...this.
	* src/mutex.cc (__once_mutex): Don't export, use
	(get_once_mutex): ...this.
	* config/abi/pre/gnu.ver: Adjust exports.

From-SVN: r143182
This commit is contained in:
Benjamin Kosnik 2009-01-08 03:14:24 +00:00
parent f5651df1ab
commit 9982752346
10 changed files with 136 additions and 57 deletions

View File

@ -1,3 +1,22 @@
2009-01-07 Benjamin Kosnik <bkoz@redhat.com>
Jonathan Larmour <jifl@eCosCentric.com>
PR libstdc++/36801
* config/cpu/generic/atomicity_mutex/atomicity.h (get_atomic_mutex):
New.
(__gnu_cxx::__exchange_and_add): Use it.
* src/atomic.cc (get_atomic_mutex): New.
* src/debug.cc (get_safe_base_mutex): New.
* src/locale.cc (get_locale_cache_mutex): New.
* src/mt_allocator.cc (get_freelist): New.
(get_freelist_mutex): New.
* src/pool_allocator.cc (get_palloc_mutex): New.
* include/std/mutex (__once_functor_lock): To
(__get_once_functor_lock): ...this.
* src/mutex.cc (__once_mutex): Don't export, use
(get_once_mutex): ...this.
* config/abi/pre/gnu.ver: Adjust exports.
2009-01-07 Jakub Jelinek <jakub@redhat.com>
PR libstdc++/38732
@ -53,12 +72,12 @@
PR libstdc++/38384
* crossconfig.m4: Define HAVE_FABSF for hpux crosses.
* configure: Regenerate.
* configure: Regenerate.
2009-01-05 Ben Elliston <bje@au.ibm.com>
* configure.ac (GLIBCXX_CHECK_STANDARD_LAYOUT): Remove invocation.
* configure: Regenerate.
* configure.ac (GLIBCXX_CHECK_STANDARD_LAYOUT): Remove invocation.
* configure: Regenerate.
2009-01-05 Ben Elliston <bje@au.ibm.com>
@ -141,12 +160,12 @@
2008-12-17 Jack Howarth <howarth@bromo.med.uc.edu>
* testsuite/26_numerics/headers/cmath/c99_classification_macros_c.cc:
* testsuite/26_numerics/headers/cmath/c99_classification_macros_c.cc:
Don't xfail test on darwin8 or later.
2008-12-16 Jack Howarth <howarth@bromo.med.uc.edu>
* testsuite/26_numerics/headers/cmath/c99_classification_macros_c.cc:
* testsuite/26_numerics/headers/cmath/c99_classification_macros_c.cc:
Don't xfail excessive errors on darwin8 or later.
2008-12-15 Benjamin Kosnik <bkoz@redhat.com>

View File

@ -1,6 +1,6 @@
## Linker script for GNU versioning (GNU ld 2.13.91+ only.)
##
## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
## Free Software Foundation, Inc.
##
## This file is part of the GNU ISO C++ Library. This library is free
@ -884,9 +884,7 @@ GLIBCXX_3.4.11 {
_ZSt11__once_call;
_ZSt15__once_callable;
_ZSt14__once_functor;
_ZSt19__once_functor_lock;
_ZSt11__once_lock;
_ZSt12__once_mutex;
_ZSt23__get_once_functor_lockv;
__once_proxy;
# condition_variable

View File

@ -1,6 +1,6 @@
// Low-level functions for atomic operations: Generic version -*- C++ -*-
// Copyright (C) 1999, 2001, 2002, 2003, 2004, 2005, 2006
// Copyright (C) 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2009
// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
@ -37,7 +37,12 @@
namespace
{
__gnu_cxx::__mutex atomic_mutex;
__gnu_cxx::__mutex&
get_atomic_mutex()
{
static __gnu_cxx::__mutex atomic_mutex;
return atomic_mutex;
}
} // anonymous namespace
_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
@ -46,7 +51,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
__attribute__ ((__unused__))
__exchange_and_add(volatile _Atomic_word* __mem, int __val)
{
__gnu_cxx::__scoped_lock sentry(atomic_mutex);
__gnu_cxx::__scoped_lock sentry(get_atomic_mutex());
_Atomic_word __result;
__result = *__mem;
*__mem += __val;

View File

@ -1,6 +1,6 @@
// <mutex> -*- C++ -*-
// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
@ -709,13 +709,16 @@ namespace std
extern __thread void (*__once_call)();
template<typename _Callable>
void __once_call_impl()
inline void
__once_call_impl()
{
(*(_Callable*)__once_callable)();
}
#else
extern function<void()> __once_functor;
extern unique_lock<mutex> __once_functor_lock;
extern unique_lock<mutex>&
__get_once_functor_lock();
#endif
extern "C" void __once_proxy();
@ -729,15 +732,16 @@ namespace std
__once_callable = &__bound_functor;
__once_call = &__once_call_impl<decltype(__bound_functor)>;
#else
__once_functor_lock.lock();
unique_lock<mutex>& __functor_lock = __get_once_functor_lock();
__functor_lock.lock();
__once_functor = bind(__f, __args...);
#endif
int __e = __gthread_once(&(__once._M_once), &__once_proxy);
#ifndef _GLIBCXX_HAVE_TLS
if (__once_functor_lock)
__once_functor_lock.unlock();
if (__functor_lock)
__functor_lock.unlock();
#endif
if (__e)

View File

@ -1,6 +1,6 @@
// Support for atomic operations -*- C++ -*-
// Copyright (C) 2008
// Copyright (C) 2008, 2009
// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
@ -37,7 +37,12 @@
namespace
{
#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
std::mutex atomic_mutex;
std::mutex&
get_atomic_mutex()
{
static std::mutex atomic_mutex;
return atomic_mutex;
}
#endif
std::__atomic_flag_base volatile flag_table[ 1 << LOGSIZE ] =
@ -57,7 +62,7 @@ namespace std
atomic_flag::test_and_set(memory_order) volatile
{
#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
lock_guard<mutex> __lock(atomic_mutex);
lock_guard<mutex> __lock(get_atomic_mutex());
#endif
bool result = _M_i;
_M_i = true;
@ -68,7 +73,7 @@ namespace std
atomic_flag::clear(memory_order) volatile
{
#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
lock_guard<mutex> __lock(atomic_mutex);
lock_guard<mutex> __lock(get_atomic_mutex());
#endif
_M_i = false;
}

View File

@ -1,6 +1,6 @@
// Debugging mode support code -*- C++ -*-
// Copyright (C) 2003, 2004, 2005, 2006, 2007
// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009
// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
@ -42,7 +42,12 @@ using namespace std;
namespace
{
__gnu_cxx::__mutex safe_base_mutex;
__gnu_cxx::__mutex&
get_safe_base_mutex()
{
static __gnu_cxx::__mutex safe_base_mutex;
return safe_base_mutex;
}
} // anonymous namespace
namespace __gnu_debug
@ -112,7 +117,7 @@ namespace __gnu_debug
_Safe_sequence_base::
_M_detach_all()
{
__gnu_cxx::__scoped_lock sentry(safe_base_mutex);
__gnu_cxx::__scoped_lock sentry(_M_get_mutex());
for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
{
_Safe_iterator_base* __old = __iter;
@ -132,7 +137,7 @@ namespace __gnu_debug
_Safe_sequence_base::
_M_detach_singular()
{
__gnu_cxx::__scoped_lock sentry(safe_base_mutex);
__gnu_cxx::__scoped_lock sentry(_M_get_mutex());
for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
{
_Safe_iterator_base* __old = __iter;
@ -154,7 +159,7 @@ namespace __gnu_debug
_Safe_sequence_base::
_M_revalidate_singular()
{
__gnu_cxx::__scoped_lock sentry(safe_base_mutex);
__gnu_cxx::__scoped_lock sentry(_M_get_mutex());
for (_Safe_iterator_base* __iter = _M_iterators; __iter;
__iter = __iter->_M_next)
__iter->_M_version = _M_version;
@ -168,7 +173,7 @@ namespace __gnu_debug
_Safe_sequence_base::
_M_swap(_Safe_sequence_base& __x)
{
__gnu_cxx::__scoped_lock sentry(safe_base_mutex);
__gnu_cxx::__scoped_lock sentry(_M_get_mutex());
swap(_M_iterators, __x._M_iterators);
swap(_M_const_iterators, __x._M_const_iterators);
swap(_M_version, __x._M_version);
@ -186,13 +191,13 @@ namespace __gnu_debug
__gnu_cxx::__mutex&
_Safe_sequence_base::
_M_get_mutex()
{ return safe_base_mutex; }
{ return get_safe_base_mutex(); }
void
_Safe_iterator_base::
_M_attach(_Safe_sequence_base* __seq, bool __constant)
{
__gnu_cxx::__scoped_lock sentry(safe_base_mutex);
__gnu_cxx::__scoped_lock sentry(_M_get_mutex());
_M_attach_single(__seq, __constant);
}
@ -229,7 +234,7 @@ namespace __gnu_debug
_Safe_iterator_base::
_M_detach()
{
__gnu_cxx::__scoped_lock sentry(safe_base_mutex);
__gnu_cxx::__scoped_lock sentry(_M_get_mutex());
_M_detach_single();
}
@ -273,7 +278,7 @@ namespace __gnu_debug
__gnu_cxx::__mutex&
_Safe_iterator_base::
_M_get_mutex()
{ return safe_base_mutex; }
{ return get_safe_base_mutex(); }
void
_Error_formatter::_Parameter::

View File

@ -1,4 +1,5 @@
// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
// 2009
// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
@ -36,7 +37,12 @@
namespace
{
__gnu_cxx::__mutex locale_cache_mutex;
__gnu_cxx::__mutex&
get_locale_cache_mutex()
{
static __gnu_cxx::__mutex locale_cache_mutex;
return locale_cache_mutex;
}
} // anonymous namespace
// XXX GLIBCXX_ABI Deprecated
@ -389,7 +395,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
locale::_Impl::
_M_install_cache(const facet* __cache, size_t __index)
{
__gnu_cxx::__scoped_lock sentry(locale_cache_mutex);
__gnu_cxx::__scoped_lock sentry(get_locale_cache_mutex());
if (_M_caches[__index] != 0)
{
// Some other thread got in first.

View File

@ -1,6 +1,6 @@
// Allocator details.
// Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
// Copyright (C) 2004, 2005, 2006, 2009 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@ -57,21 +57,34 @@ namespace
}
};
// Ensure freelist is constructed first.
static __freelist freelist;
__gnu_cxx::__mutex freelist_mutex;
__freelist&
get_freelist()
{
static __freelist freelist;
return freelist;
}
__gnu_cxx::__mutex&
get_freelist_mutex()
{
static __gnu_cxx::__mutex freelist_mutex;
return freelist_mutex;
}
static void
_M_destroy_thread_key(void* __id)
{
// Return this thread id record to the front of thread_freelist.
__gnu_cxx::__scoped_lock sentry(freelist_mutex);
size_t _M_id = reinterpret_cast<size_t>(__id);
typedef __gnu_cxx::__pool<true>::_Thread_record _Thread_record;
_Thread_record* __tr = &freelist._M_thread_freelist_array[_M_id - 1];
__tr->_M_next = freelist._M_thread_freelist;
freelist._M_thread_freelist = __tr;
__freelist& freelist = get_freelist();
{
__gnu_cxx::__scoped_lock sentry(get_freelist_mutex());
size_t _M_id = reinterpret_cast<size_t>(__id);
typedef __gnu_cxx::__pool<true>::_Thread_record _Thread_record;
_Thread_record* __tr = &freelist._M_thread_freelist_array[_M_id - 1];
__tr->_M_next = freelist._M_thread_freelist;
freelist._M_thread_freelist = __tr;
}
}
#endif
} // anonymous namespace
@ -496,8 +509,9 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
// directly and have no need for this.
if (__gthread_active_p())
{
__freelist& freelist = get_freelist();
{
__gnu_cxx::__scoped_lock sentry(freelist_mutex);
__gnu_cxx::__scoped_lock sentry(get_freelist_mutex());
if (!freelist._M_thread_freelist_array
|| freelist._M_max_threads < _M_options._M_max_threads)
@ -613,12 +627,13 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
// returns its id.
if (__gthread_active_p())
{
__freelist& freelist = get_freelist();
void* v = __gthread_getspecific(freelist._M_key);
size_t _M_id = (size_t)v;
if (_M_id == 0)
{
{
__gnu_cxx::__scoped_lock sentry(freelist_mutex);
__gnu_cxx::__scoped_lock sentry(get_freelist_mutex());
if (freelist._M_thread_freelist)
{
_M_id = freelist._M_thread_freelist->_M_id;
@ -689,8 +704,9 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
// directly and have no need for this.
if (__gthread_active_p())
{
__freelist& freelist = get_freelist();
{
__gnu_cxx::__scoped_lock sentry(freelist_mutex);
__gnu_cxx::__scoped_lock sentry(get_freelist_mutex());
if (!freelist._M_thread_freelist_array
|| freelist._M_max_threads < _M_options._M_max_threads)

View File

@ -1,6 +1,6 @@
// mutex -*- C++ -*-
// Copyright (C) 2008 Free Software Foundation, Inc.
// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@ -30,6 +30,17 @@
#include <mutex>
#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
#ifndef _GLIBCXX_HAVE_TLS
namespace
{
std::mutex&
get_once_mutex()
{
static std::mutex once_mutex;
return once_mutex;
}
}
#endif
namespace std
{
@ -45,11 +56,16 @@ namespace std
__thread void* __once_callable;
__thread void (*__once_call)();
#else
// explicit instantiation due to -fno-implicit-instantiation
// Explicit instantiation due to -fno-implicit-instantiation.
template class function<void()>;
function<void()> __once_functor;
mutex __once_mutex;
unique_lock<mutex> __once_functor_lock(__once_mutex, defer_lock);
unique_lock<mutex>&
__get_once_functor_lock()
{
static unique_lock<mutex> once_functor_lock(get_once_mutex(), defer_lock);
return once_functor_lock;
}
#endif
extern "C"
@ -58,7 +74,7 @@ namespace std
{
#ifndef _GLIBCXX_HAVE_TLS
function<void()> __once_call = std::move(__once_functor);
__once_functor_lock.unlock();
__get_once_functor_lock().unlock();
#endif
__once_call();
}

View File

@ -1,6 +1,6 @@
// Allocator details.
// Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
// Copyright (C) 2004, 2005, 2006, 2009 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@ -37,7 +37,12 @@
namespace
{
__gnu_cxx::__mutex palloc_init_mutex;
__gnu_cxx::__mutex&
get_palloc_mutex()
{
static __gnu_cxx::__mutex palloc_mutex;
return palloc_mutex;
}
} // anonymous namespace
_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
@ -52,7 +57,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
__mutex&
__pool_alloc_base::_M_get_mutex()
{ return palloc_init_mutex; }
{ return get_palloc_mutex(); }
// Allocate memory in large chunks in order to avoid fragmenting the
// heap too much. Assume that __n is properly aligned. We hold the