Commit f83295ba by Benjamin Kosnik Committed by Benjamin Kosnik

re PR libstdc++/12658 (Thread safety problems in locale::global() and locale::locale())


2004-03-06  Benjamin Kosnik  <bkoz@redhat.com>

	PR libstdc++/12658
	* src/locale_init.cc (locale::locale): Lock critical regions with
	external mutexes.
	(locale::global): Same.
	* include/bits/concurrence.h (__glibcxx_mutex_define_initialized):
	Add in once bits for cases without __GTHREAD_MUTEX_INIT.
	(__glibcxx_mutex_lock): Same.

	* config/cpu/generic/atomicity.h: Remove
	_GLIBCXX_NEED_GENERIC_MUTEX, use concurrence.h.
	* src/misc-inst.cc: Move all locking bits out of this file.

	* config/os/hpux/os_defines.h: Remove _GLIBCXX_INST_ATOMICITY_LOCK.
	* src/misc-inst.cc: Same.
	* config/cpu/hppa/atomicity.h: Same.

	* config/linker-map.gnu: Remove types in the signature of atomic
	exports, as they may vary.

From-SVN: r79043
parent 018e1b3b
2004-03-06 Benjamin Kosnik <bkoz@redhat.com>
PR libstdc++/12658
* src/locale_init.cc (locale::locale): Lock critical regions with
external mutexes.
(locale::global): Same.
* include/bits/concurrence.h (__glibcxx_mutex_define_initialized):
Add in once bits for cases without __GTHREAD_MUTEX_INIT.
(__glibcxx_mutex_lock): Same.
* config/cpu/generic/atomicity.h: Remove
_GLIBCXX_NEED_GENERIC_MUTEX, use concurrence.h.
* src/misc-inst.cc: Move all locking bits out of this file.
* config/os/hpux/os_defines.h: Remove _GLIBCXX_INST_ATOMICITY_LOCK.
* src/misc-inst.cc: Same.
* config/cpu/hppa/atomicity.h: Same.
* config/linker-map.gnu: Remove types in the signature of atomic
exports, as they may vary.
2004-03-06 Paolo Carlini <pcarlini@suse.de> 2004-03-06 Paolo Carlini <pcarlini@suse.de>
* include/bits/locale_facets.tcc: Tweak the comment preceding * include/bits/locale_facets.tcc: Tweak the comment preceding
......
...@@ -28,34 +28,24 @@ ...@@ -28,34 +28,24 @@
// the GNU General Public License. // the GNU General Public License.
#include <bits/atomicity.h> #include <bits/atomicity.h>
#include <bits/gthr.h> #include <bits/concurrence.h>
#define _GLIBCXX_NEED_GENERIC_MUTEX namespace __gnu_internal
{
__glibcxx_mutex_define_initialized(atomic_mutex);
} // namespace __gnu_internal
namespace __gnu_cxx namespace __gnu_cxx
{ {
extern __gthread_mutex_t _Atomic_add_mutex;
#ifndef __GTHREAD_MUTEX_INIT
extern __gthread_once_t _Atomic_add_mutex_once;
extern void __gthread_atomic_add_mutex_once();
#endif
_Atomic_word _Atomic_word
__attribute__ ((__unused__)) __attribute__ ((__unused__))
__exchange_and_add(volatile _Atomic_word* __mem, int __val) __exchange_and_add(volatile _Atomic_word* __mem, int __val)
{ {
#ifndef __GTHREAD_MUTEX_INIT __glibcxx_mutex_lock(__gnu_internal::atomic_mutex);
__gthread_once(&__gnu_cxx::_Atomic_add_mutex_once,
__gnu_cxx::__gthread_atomic_add_mutex_once);
#endif
_Atomic_word __result; _Atomic_word __result;
__gthread_mutex_lock(&__gnu_cxx::_Atomic_add_mutex);
__result = *__mem; __result = *__mem;
*__mem += __val; *__mem += __val;
__glibcxx_mutex_unlock(__gnu_internal::atomic_mutex);
__gthread_mutex_unlock(&__gnu_cxx::_Atomic_add_mutex);
return __result; return __result;
} }
......
...@@ -43,11 +43,8 @@ namespace __gnu_cxx ...@@ -43,11 +43,8 @@ namespace __gnu_cxx
_Atomicity_lock<_Inst>::_S_atomicity_lock __attribute__ ((aligned (16))) = 1; _Atomicity_lock<_Inst>::_S_atomicity_lock __attribute__ ((aligned (16))) = 1;
// Because of the lack of weak support when using the hpux som // Because of the lack of weak support when using the hpux som
// linker, we explicitly instantiate the atomicity lock in // linker, we explicitly instantiate the atomicity lock.
// src/misc-inst.cc when _GLIBCXX_INST_ATOMICITY_LOCK is defined.
#ifndef _GLIBCXX_INST_ATOMICITY_LOCK
template volatile int _Atomicity_lock<0>::_S_atomicity_lock; template volatile int _Atomicity_lock<0>::_S_atomicity_lock;
#endif
int int
__attribute__ ((__unused__)) __attribute__ ((__unused__))
......
...@@ -216,8 +216,8 @@ GLIBCXX_3.4 { ...@@ -216,8 +216,8 @@ GLIBCXX_3.4 {
# __gnu_cxx::__atomic_add # __gnu_cxx::__atomic_add
# __gnu_cxx::__exchange_and_add # __gnu_cxx::__exchange_and_add
_ZN9__gnu_cxx12__atomic_addEPVii; _ZN9__gnu_cxx12__atomic_add*;
_ZN9__gnu_cxx18__exchange_and_addEPVii; _ZN9__gnu_cxx18__exchange_and_add*;
# DO NOT DELETE THIS LINE. Port-specific symbols, if any, will be here. # DO NOT DELETE THIS LINE. Port-specific symbols, if any, will be here.
......
...@@ -91,12 +91,6 @@ typedef long int __padding_type; ...@@ -91,12 +91,6 @@ typedef long int __padding_type;
#define _LIBUNWIND_STD_ABI 1 #define _LIBUNWIND_STD_ABI 1
#endif #endif
/* We need explicit instantiation of the atomicity lock on HPPA if
there is no weak support. */
#if !__GXX_WEAK__ && defined (__hppa__)
#define _GLIBCXX_INST_ATOMICITY_LOCK 1
#endif
/* Don't use pragma weak in gthread headers. HP-UX rejects programs /* Don't use pragma weak in gthread headers. HP-UX rejects programs
with unsatisfied external references even if all of those references with unsatisfied external references even if all of those references
are weak; gthread relies on such unsatisfied references being resolved are weak; gthread relies on such unsatisfied references being resolved
......
// Support for concurrent programing -*- C++ -*- // Support for concurrent programing -*- C++ -*-
// Copyright (C) 2003 // Copyright (C) 2003, 2004
// Free Software Foundation, Inc. // Free Software Foundation, Inc.
// //
// This file is part of the GNU ISO C++ Library. This library is free // This file is part of the GNU ISO C++ Library. This library is free
...@@ -28,27 +28,38 @@ ...@@ -28,27 +28,38 @@
// invalidate any other reasons why the executable file might be covered by // invalidate any other reasons why the executable file might be covered by
// the GNU General Public License. // the GNU General Public License.
#ifndef _CONCURRENCE #ifndef _CONCURRENCE_H
#define _CONCURRENCE 1 #define _CONCURRENCE_H 1
// GCC's thread abstraction layer // GCC's thread abstraction layer
#include "bits/gthr.h" #include "bits/gthr.h"
#if __GTHREADS #if __GTHREADS
# ifdef __GTHREAD_MUTEX_INIT # ifdef __GTHREAD_MUTEX_INIT
# define __glibcxx_mutex_define_initialized(NAME) \ # define __glibcxx_mutex_define_initialized(NAME) \
__gthread_mutex_t NAME = __GTHREAD_MUTEX_INIT __gthread_mutex_t NAME = __GTHREAD_MUTEX_INIT
# define __glibcxx_mutex_lock(NAME) \
__gthread_mutex_lock(&NAME)
# else # else
// Implies __GTHREAD_MUTEX_INIT_FUNCTION
# define __glibcxx_mutex_define_initialized(NAME) \ # define __glibcxx_mutex_define_initialized(NAME) \
__gthread_mutex_t NAME; \ __gthread_mutex_t NAME; \
__GTHREAD_MUTEX_INIT_FUNCTION(&NAME) __gthread_once_t NAME ## _once = __GTHREAD_ONCE_INIT; \
void NAME ## _init() { __GTHREAD_MUTEX_INIT_FUNCTION(&NAME); }
# define __glibcxx_mutex_lock(NAME) \
__gthread_once(&NAME ## _once, NAME ## _init); \
__gthread_mutex_lock(&NAME)
# endif # endif
# define __glibcxx_mutex_lock(LOCK) __gthread_mutex_lock(&LOCK)
# define __glibcxx_mutex_unlock(LOCK) __gthread_mutex_unlock(&LOCK) # define __glibcxx_mutex_unlock(NAME) __gthread_mutex_unlock(&NAME)
#else #else
# define __glibcxx_mutex_define_initialized(NAME) # define __glibcxx_mutex_define_initialized(NAME)
# define __glibcxx_mutex_lock(LOCK) # define __glibcxx_mutex_lock(NAME)
# define __glibcxx_mutex_unlock(LOCK) # define __glibcxx_mutex_unlock(NAME)
#endif #endif
#endif #endif
...@@ -559,8 +559,8 @@ namespace __gnu_cxx ...@@ -559,8 +559,8 @@ namespace __gnu_cxx
} }
// Setup the bin map for quick lookup of the relevant bin. // Setup the bin map for quick lookup of the relevant bin.
_S_binmap = (binmap_type*) const size_t n1 = (_S_options._M_max_bytes + 1) * sizeof(binmap_type);
::operator new ((_S_options._M_max_bytes + 1) * sizeof(binmap_type)); _S_binmap = static_cast<binmap_type*>(::operator new(n1));
binmap_type* bp_t = _S_binmap; binmap_type* bp_t = _S_binmap;
binmap_type bin_max_t = 1; binmap_type bin_max_t = 1;
...@@ -581,9 +581,8 @@ namespace __gnu_cxx ...@@ -581,9 +581,8 @@ namespace __gnu_cxx
#ifdef __GTHREADS #ifdef __GTHREADS
if (__gthread_active_p()) if (__gthread_active_p())
{ {
_S_thread_freelist_first = const size_t n2 = sizeof(thread_record) * _S_options._M_max_threads;
static_cast<thread_record*>(::operator _S_thread_freelist_first = static_cast<thread_record*>(::operator new(n2));
new(sizeof(thread_record) * _S_options._M_max_threads));
// NOTE! The first assignable thread id is 1 since the // NOTE! The first assignable thread id is 1 since the
// global pool uses id 0 // global pool uses id 0
...@@ -637,7 +636,7 @@ namespace __gnu_cxx ...@@ -637,7 +636,7 @@ namespace __gnu_cxx
*br.mutex = __tmp; *br.mutex = __tmp;
} }
#else #else
{ __GTHREAD_MUTEX_INIT_FUNCTION (br.mutex); } { __GTHREAD_MUTEX_INIT_FUNCTION(br.mutex); }
#endif #endif
} }
#endif #endif
...@@ -741,7 +740,8 @@ namespace __gnu_cxx ...@@ -741,7 +740,8 @@ namespace __gnu_cxx
template<typename _Tp> template<typename _Tp>
__gthread_key_t __mt_alloc<_Tp>::_S_thread_key; __gthread_key_t __mt_alloc<_Tp>::_S_thread_key;
template<typename _Tp> __gthread_mutex_t template<typename _Tp>
__gthread_mutex_t
#ifdef __GTHREAD_MUTEX_INIT #ifdef __GTHREAD_MUTEX_INIT
__mt_alloc<_Tp>::_S_thread_freelist_mutex = __GTHREAD_MUTEX_INIT; __mt_alloc<_Tp>::_S_thread_freelist_mutex = __GTHREAD_MUTEX_INIT;
#else #else
......
...@@ -88,6 +88,10 @@ namespace __gnu_internal ...@@ -88,6 +88,10 @@ namespace __gnu_internal
extern std::__moneypunct_cache<wchar_t, true> moneypunct_cache_wt; extern std::__moneypunct_cache<wchar_t, true> moneypunct_cache_wt;
extern std::__timepunct_cache<wchar_t> timepunct_cache_w; extern std::__timepunct_cache<wchar_t> timepunct_cache_w;
#endif #endif
// Mutex objects for locale initialization.
__glibcxx_mutex_define_initialized(locale_cons_mutex);
__glibcxx_mutex_define_initialized(locale_global_mutex);
} // namespace __gnu_internal } // namespace __gnu_internal
namespace std namespace std
...@@ -97,19 +101,23 @@ namespace std ...@@ -97,19 +101,23 @@ namespace std
locale::locale() throw() locale::locale() throw()
{ {
_S_initialize(); _S_initialize();
__glibcxx_mutex_lock(__gnu_internal::locale_cons_mutex);
_S_global->_M_add_reference(); _S_global->_M_add_reference();
_M_impl = _S_global; _M_impl = _S_global;
__glibcxx_mutex_unlock(__gnu_internal::locale_cons_mutex);
} }
locale locale
locale::global(const locale& __other) locale::global(const locale& __other)
{ {
_S_initialize(); _S_initialize();
__glibcxx_mutex_lock(__gnu_internal::locale_global_mutex);
_Impl* __old = _S_global; _Impl* __old = _S_global;
__other._M_impl->_M_add_reference(); __other._M_impl->_M_add_reference();
_S_global = __other._M_impl; _S_global = __other._M_impl;
if (__other.name() != "*") if (__other.name() != "*")
setlocale(LC_ALL, __other.name().c_str()); setlocale(LC_ALL, __other.name().c_str());
__glibcxx_mutex_unlock(__gnu_internal::locale_global_mutex);
// Reference count sanity check: one reference removed for the // Reference count sanity check: one reference removed for the
// subsition of __other locale, one added by return-by-value. Net // subsition of __other locale, one added by return-by-value. Net
......
...@@ -73,24 +73,6 @@ namespace std ...@@ -73,24 +73,6 @@ namespace std
namespace __gnu_cxx namespace __gnu_cxx
{ {
#ifdef _GLIBCXX_INST_ATOMICITY_LOCK
template volatile int _Atomicity_lock<0>::_S_atomicity_lock;
#endif
#ifdef _GLIBCXX_NEED_GENERIC_MUTEX
#ifdef __GTHREAD_MUTEX_INIT
__gthread_mutex_t _Atomic_add_mutex = __GTHREAD_MUTEX_INIT;
#else
// generic atomicity.h without static initialization
__gthread_mutex_t _Atomic_add_mutex;
__gthread_once_t _Atomic_add_mutex_once = __GTHREAD_ONCE_INIT;
void __gthread_atomic_add_mutex_once()
{
__GTHREAD_MUTEX_INIT_FUNCTION (&_Atomic_add_mutex);
}
#endif
#endif // _GLIBCXX_NEED_GLOBAL_MUTEX
template class stdio_sync_filebuf<char>; template class stdio_sync_filebuf<char>;
#ifdef _GLIBCXX_USE_WCHAR_T #ifdef _GLIBCXX_USE_WCHAR_T
template class stdio_sync_filebuf<wchar_t>; template class stdio_sync_filebuf<wchar_t>;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment