+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>
* include/bits/locale_facets.tcc: Tweak the comment preceding
// the GNU General Public License.
#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
{
- 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
__attribute__ ((__unused__))
__exchange_and_add(volatile _Atomic_word* __mem, int __val)
{
-#ifndef __GTHREAD_MUTEX_INIT
- __gthread_once(&__gnu_cxx::_Atomic_add_mutex_once,
- __gnu_cxx::__gthread_atomic_add_mutex_once);
-#endif
-
+ __glibcxx_mutex_lock(__gnu_internal::atomic_mutex);
_Atomic_word __result;
- __gthread_mutex_lock(&__gnu_cxx::_Atomic_add_mutex);
__result = *__mem;
*__mem += __val;
-
- __gthread_mutex_unlock(&__gnu_cxx::_Atomic_add_mutex);
+ __glibcxx_mutex_unlock(__gnu_internal::atomic_mutex);
return __result;
}
_Atomicity_lock<_Inst>::_S_atomicity_lock __attribute__ ((aligned (16))) = 1;
// Because of the lack of weak support when using the hpux som
- // linker, we explicitly instantiate the atomicity lock in
- // src/misc-inst.cc when _GLIBCXX_INST_ATOMICITY_LOCK is defined.
-#ifndef _GLIBCXX_INST_ATOMICITY_LOCK
+ // linker, we explicitly instantiate the atomicity lock.
template volatile int _Atomicity_lock<0>::_S_atomicity_lock;
-#endif
int
__attribute__ ((__unused__))
# __gnu_cxx::__atomic_add
# __gnu_cxx::__exchange_and_add
- _ZN9__gnu_cxx12__atomic_addEPVii;
- _ZN9__gnu_cxx18__exchange_and_addEPVii;
+ _ZN9__gnu_cxx12__atomic_add*;
+ _ZN9__gnu_cxx18__exchange_and_add*;
# DO NOT DELETE THIS LINE. Port-specific symbols, if any, will be here.
#define _LIBUNWIND_STD_ABI 1
#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
with unsatisfied external references even if all of those references
are weak; gthread relies on such unsatisfied references being resolved
// Support for concurrent programing -*- C++ -*-
-// Copyright (C) 2003
+// Copyright (C) 2003, 2004
// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
-#ifndef _CONCURRENCE
-#define _CONCURRENCE 1
+#ifndef _CONCURRENCE_H
+#define _CONCURRENCE_H 1
// GCC's thread abstraction layer
#include "bits/gthr.h"
#if __GTHREADS
+
# ifdef __GTHREAD_MUTEX_INIT
# define __glibcxx_mutex_define_initialized(NAME) \
__gthread_mutex_t NAME = __GTHREAD_MUTEX_INIT
+# define __glibcxx_mutex_lock(NAME) \
+__gthread_mutex_lock(&NAME)
# else
+// Implies __GTHREAD_MUTEX_INIT_FUNCTION
# define __glibcxx_mutex_define_initialized(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
-# 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
+
# define __glibcxx_mutex_define_initialized(NAME)
-# define __glibcxx_mutex_lock(LOCK)
-# define __glibcxx_mutex_unlock(LOCK)
+# define __glibcxx_mutex_lock(NAME)
+# define __glibcxx_mutex_unlock(NAME)
+
#endif
#endif
}
// Setup the bin map for quick lookup of the relevant bin.
- _S_binmap = (binmap_type*)
- ::operator new ((_S_options._M_max_bytes + 1) * sizeof(binmap_type));
+ const size_t n1 = (_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 bin_max_t = 1;
#ifdef __GTHREADS
if (__gthread_active_p())
{
- _S_thread_freelist_first =
- static_cast<thread_record*>(::operator
- new(sizeof(thread_record) * _S_options._M_max_threads));
+ const size_t n2 = sizeof(thread_record) * _S_options._M_max_threads;
+ _S_thread_freelist_first = static_cast<thread_record*>(::operator new(n2));
// NOTE! The first assignable thread id is 1 since the
// global pool uses id 0
*br.mutex = __tmp;
}
#else
- { __GTHREAD_MUTEX_INIT_FUNCTION (br.mutex); }
+ { __GTHREAD_MUTEX_INIT_FUNCTION(br.mutex); }
#endif
}
#endif
template<typename _Tp>
__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
- __mt_alloc<_Tp>::_S_thread_freelist_mutex = __GTHREAD_MUTEX_INIT;
+ __mt_alloc<_Tp>::_S_thread_freelist_mutex = __GTHREAD_MUTEX_INIT;
#else
// XXX
- __mt_alloc<_Tp>::_S_thread_freelist_mutex;
+ __mt_alloc<_Tp>::_S_thread_freelist_mutex;
#endif
#endif
} // namespace __gnu_cxx
extern std::__moneypunct_cache<wchar_t, true> moneypunct_cache_wt;
extern std::__timepunct_cache<wchar_t> timepunct_cache_w;
#endif
+
+ // Mutex objects for locale initialization.
+ __glibcxx_mutex_define_initialized(locale_cons_mutex);
+ __glibcxx_mutex_define_initialized(locale_global_mutex);
} // namespace __gnu_internal
namespace std
locale::locale() throw()
{
_S_initialize();
+ __glibcxx_mutex_lock(__gnu_internal::locale_cons_mutex);
_S_global->_M_add_reference();
_M_impl = _S_global;
+ __glibcxx_mutex_unlock(__gnu_internal::locale_cons_mutex);
}
locale
locale::global(const locale& __other)
{
_S_initialize();
+ __glibcxx_mutex_lock(__gnu_internal::locale_global_mutex);
_Impl* __old = _S_global;
__other._M_impl->_M_add_reference();
_S_global = __other._M_impl;
if (__other.name() != "*")
setlocale(LC_ALL, __other.name().c_str());
+ __glibcxx_mutex_unlock(__gnu_internal::locale_global_mutex);
// Reference count sanity check: one reference removed for the
// subsition of __other locale, one added by return-by-value. Net
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>;
#ifdef _GLIBCXX_USE_WCHAR_T
template class stdio_sync_filebuf<wchar_t>;