diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 225440b05f3..40ad5f1b2c4 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,20 @@ +2004-06-24 Benjamin Kosnik + + * include/bits/concurrence.h (__gnu_cxx::lock): New. + * include/ext/pool_allocator.h (__pool_base::_Lock::_S_lock): Remove. + (__pool_base::_M_get_mutex): New. + * include/bits/allocator.h: Tweak. + * src/allocator.cc (__pool_base::_M_get_free_list): Correct offset. + * config/linker-map.gnu: Remove __pool_base::_Lock::_S_lock. + * include/bits/stl_threads.h: Remove. + * include/Makefile.am: Also here. + * include/Makefile.in: Regenerate. + + * src/locale_init.cc: Use __gnu_cxx::lock. + + * src/allocator.cc: Move all instantiations... + * src/allocator-inst.cc: ...here. + 2004-06-23 Andrew Pinski * linkage.m4: Remove check for libmx. diff --git a/libstdc++-v3/config/linker-map.gnu b/libstdc++-v3/config/linker-map.gnu index 5016b43cae7..e6a861b78f3 100644 --- a/libstdc++-v3/config/linker-map.gnu +++ b/libstdc++-v3/config/linker-map.gnu @@ -143,7 +143,6 @@ GLIBCXX_3.4 { _ZNSt12__basic_fileIcE6xsputn*; _ZNSt12__basic_fileIcE7seekoff*; _ZNSt12__basic_fileIcE8sys_openE*St13_Ios_Openmode; - _ZNSt12__basic_fileIcE8sys_openEiSt13_Ios_Openmode; _ZNSt12__basic_fileIcE8xsputn_2*; _ZNSt12__basic_fileIcE9showmanycEv; _ZNSt12__basic_fileIcEC*; @@ -257,10 +256,10 @@ GLIBCXX_3.4.1 { GLIBCXX_3.4.2 { - _ZN9__gnu_cxx11__pool_base5_Lock7_S_lockE; - _ZN9__gnu_cxx11__pool_base9_M_refillEj; - _ZN9__gnu_cxx11__pool_base16_M_get_free_listEj; - + _ZN9__gnu_cxx11__pool_base9_M_refillE[jm]; + _ZN9__gnu_cxx11__pool_base16_M_get_free_listE[jm]; + _ZN9__gnu_cxx11__pool_base12_M_get_mutexEv; + } GLIBCXX_3.4.1; # Symbols in the support library (libsupc++) have their own tag. diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index 34e20338ae6..bed615eaecf 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -145,7 +145,6 @@ bits_headers = \ ${bits_srcdir}/stl_set.h \ ${bits_srcdir}/stl_stack.h \ ${bits_srcdir}/stl_tempbuf.h \ - ${bits_srcdir}/stl_threads.h \ ${bits_srcdir}/stl_tree.h \ ${bits_srcdir}/stl_uninitialized.h \ ${bits_srcdir}/stl_vector.h \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index 9b904e19dc1..51a1718f795 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -357,7 +357,6 @@ bits_headers = \ ${bits_srcdir}/stl_set.h \ ${bits_srcdir}/stl_stack.h \ ${bits_srcdir}/stl_tempbuf.h \ - ${bits_srcdir}/stl_threads.h \ ${bits_srcdir}/stl_tree.h \ ${bits_srcdir}/stl_uninitialized.h \ ${bits_srcdir}/stl_vector.h \ diff --git a/libstdc++-v3/include/bits/allocator.h b/libstdc++-v3/include/bits/allocator.h index c9200ecd994..a744b5ff894 100644 --- a/libstdc++-v3/include/bits/allocator.h +++ b/libstdc++-v3/include/bits/allocator.h @@ -94,8 +94,8 @@ namespace std allocator() throw() { } - allocator(const allocator& a) throw() - : ___glibcxx_base_allocator<_Tp>(a) { } + allocator(const allocator& __a) throw() + : ___glibcxx_base_allocator<_Tp>(__a) { } template allocator(const allocator<_Tp1>&) throw() { } diff --git a/libstdc++-v3/include/bits/concurrence.h b/libstdc++-v3/include/bits/concurrence.h index ea99e56e7ef..81f6216d931 100644 --- a/libstdc++-v3/include/bits/concurrence.h +++ b/libstdc++-v3/include/bits/concurrence.h @@ -62,4 +62,26 @@ __gthread_mutex_lock(&NAME) #endif +namespace __gnu_cxx +{ + class lock + { + // Externally defined and initialized. + __gthread_mutex_t* device; + + public: + // Acquire the mutex here with a constructor call. This ensures + // that it is released in exit or during stack unwinding. + explicit lock(__gthread_mutex_t& name) : device(&name) + { __glibcxx_mutex_lock(*device); } + + ~lock() throw() + { __glibcxx_mutex_unlock(*device); } + + private: + lock(const lock&); + lock& operator=(const lock&); + }; +} + #endif diff --git a/libstdc++-v3/include/bits/stl_threads.h b/libstdc++-v3/include/bits/stl_threads.h deleted file mode 100644 index 04baf0a08f9..00000000000 --- a/libstdc++-v3/include/bits/stl_threads.h +++ /dev/null @@ -1,150 +0,0 @@ -// Threading support -*- C++ -*- - -// Copyright (C) 2001, 2002, 2003, 2004 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 -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 2, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License along -// with this library; see the file COPYING. If not, write to the Free -// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, -// USA. - -// As a special exception, you may use this file as part of a free software -// library without restriction. Specifically, if other files instantiate -// templates or use macros or inline functions from this file, or you compile -// this file and link it with other files to produce an executable, this -// file does not by itself cause the resulting executable to be covered by -// the GNU General Public License. This exception does not however -// invalidate any other reasons why the executable file might be covered by -// the GNU General Public License. - -/* - * Copyright (c) 1997-1999 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file stl_threads.h - * This is an internal header file, included by other library headers. - * You should not attempt to use it directly. - */ - -#ifndef _STL_THREADS_H -#define _STL_THREADS_H 1 - -#include - -// The only supported threading model is GCC's own gthr.h abstraction -// layer. -#include "bits/gthr.h" - -namespace __gnu_internal -{ -#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) - extern __gthread_mutex_t _GLIBCXX_mutex; - extern __gthread_mutex_t *_GLIBCXX_mutex_address; - extern __gthread_once_t _GLIBCXX_once; - extern void _GLIBCXX_mutex_init(void); - extern void _GLIBCXX_mutex_address_init(void); -#endif -} // namespace __gnu_internal - -namespace __gnu_cxx -{ - // Locking class. Note that this class *does not have a - // constructor*. It must be initialized either statically, with - // __STL_MUTEX_INITIALIZER, or dynamically, by explicitly calling - // the _M_initialize member function. (This is similar to the ways - // that a pthreads mutex can be initialized.) There are explicit - // member functions for acquiring and releasing the lock. - - // There is no constructor because static initialization is - // essential for some uses, and only a class aggregate (see section - // 8.5.1 of the C++ standard) can be initialized that way. That - // means we must have no constructors, no base classes, no virtual - // functions, and no private or protected members. - struct _STL_mutex_lock - { - // The class must be statically initialized with __STL_MUTEX_INITIALIZER. -#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) - volatile int _M_init_flag; - __gthread_once_t _M_once; -#endif - __gthread_mutex_t _M_lock; - - void - _M_initialize() - { -#ifdef __GTHREAD_MUTEX_INIT - // There should be no code in this path given the usage rules above. -#elif defined(__GTHREAD_MUTEX_INIT_FUNCTION) - if (_M_init_flag) return; - if (__gthread_once(&__gnu_internal::_GLIBCXX_once, - __gnu_internal::_GLIBCXX_mutex_init) != 0 - && __gthread_active_p()) - abort (); - __gthread_mutex_lock(&__gnu_internal::_GLIBCXX_mutex); - if (!_M_init_flag) - { - // Even though we have a global lock, we use __gthread_once to be - // absolutely certain the _M_lock mutex is only initialized once on - // multiprocessor systems. - __gnu_internal::_GLIBCXX_mutex_address = &_M_lock; - if (__gthread_once(&_M_once, - __gnu_internal::_GLIBCXX_mutex_address_init) != 0 - && __gthread_active_p()) - abort(); - _M_init_flag = 1; - } - __gthread_mutex_unlock(&__gnu_internal::_GLIBCXX_mutex); -#endif - } - - void - _M_acquire_lock() - { -#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) - if (!_M_init_flag) _M_initialize(); -#endif - __gthread_mutex_lock(&_M_lock); - } - - void - _M_release_lock() - { -#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) - if (!_M_init_flag) _M_initialize(); -#endif - __gthread_mutex_unlock(&_M_lock); - } - }; - -#ifdef __GTHREAD_MUTEX_INIT -#define __STL_MUTEX_INITIALIZER = { __GTHREAD_MUTEX_INIT } -#elif defined(__GTHREAD_MUTEX_INIT_FUNCTION) -#ifdef __GTHREAD_MUTEX_INIT_DEFAULT -#define __STL_MUTEX_INITIALIZER \ - = { 0, __GTHREAD_ONCE_INIT, __GTHREAD_MUTEX_INIT_DEFAULT } -#else -#define __STL_MUTEX_INITIALIZER = { 0, __GTHREAD_ONCE_INIT } -#endif -#endif -} // namespace __gnu_cxx - -#endif diff --git a/libstdc++-v3/include/ext/pool_allocator.h b/libstdc++-v3/include/ext/pool_allocator.h index e5efac36f5b..de6299be8cf 100644 --- a/libstdc++-v3/include/ext/pool_allocator.h +++ b/libstdc++-v3/include/ext/pool_allocator.h @@ -50,8 +50,8 @@ #include #include #include -#include #include +#include namespace __gnu_cxx { @@ -80,15 +80,6 @@ namespace __gnu_cxx enum { _S_max_bytes = 128 }; enum { _S_free_list_size = _S_max_bytes / _S_align }; - // It would be nice to use _STL_auto_lock here. But we need a - // test whether threads are in use. - struct _Lock - { - static _STL_mutex_lock _S_lock; - _Lock() { _S_lock._M_acquire_lock(); } - ~_Lock() { _S_lock._M_release_lock(); } - }; - union _Obj { union _Obj* _M_free_list_link; @@ -96,7 +87,7 @@ namespace __gnu_cxx }; static _Obj* volatile _S_free_list[_S_free_list_size]; - + // Chunk allocation state. static char* _S_start_free; static char* _S_end_free; @@ -109,6 +100,9 @@ namespace __gnu_cxx _Obj* volatile* _M_get_free_list(size_t __bytes); + __gthread_mutex_t& + _M_get_mutex(); + // Returns an object of size __n, and optionally adds to size __n // free list. void* @@ -216,10 +210,7 @@ namespace __gnu_cxx { _Obj* volatile* __free_list = _M_get_free_list(__bytes); - // Acquire the lock here with a constructor call. This - // ensures that it is released in exit or during stack - // unwinding. - _Lock __lock_instance; + lock sentry(_M_get_mutex()); _Obj* __restrict__ __result = *__free_list; if (__builtin_expect(__result == 0, 0)) __ret = static_cast<_Tp*>(_M_refill(_M_round_up(__bytes))); @@ -252,10 +243,7 @@ namespace __gnu_cxx _Obj* volatile* __free_list = _M_get_free_list(__bytes); _Obj* __q = reinterpret_cast<_Obj*>(__p); - // Acquire the lock here with a constructor call. This - // ensures that it is released in exit or during stack - // unwinding. - _Lock __lock_instance; + lock sentry(_M_get_mutex()); __q ->_M_free_list_link = *__free_list; *__free_list = __q; } diff --git a/libstdc++-v3/src/allocator-inst.cc b/libstdc++-v3/src/allocator-inst.cc index 3fcbb608098..40d7049cddd 100644 --- a/libstdc++-v3/src/allocator-inst.cc +++ b/libstdc++-v3/src/allocator-inst.cc @@ -31,11 +31,21 @@ // ISO C++ 14882: // -#include #include +#include +#include namespace std { template class allocator; template class allocator; } // namespace std + +namespace __gnu_cxx +{ + template class __mt_alloc; + template class __mt_alloc; + + template class __pool_alloc; + template class __pool_alloc; +} // namespace __gnu_cxx diff --git a/libstdc++-v3/src/allocator.cc b/libstdc++-v3/src/allocator.cc index d4928735848..af5de4d2cb9 100644 --- a/libstdc++-v3/src/allocator.cc +++ b/libstdc++-v3/src/allocator.cc @@ -36,20 +36,25 @@ #include #include +namespace __gnu_internal +{ + __glibcxx_mutex_define_initialized(palloc_init_mutex); +} + namespace __gnu_cxx { - // Instantiations for __mt_alloc. - template class __mt_alloc; - template class __mt_alloc; - - // Definitions and instantiations for __pool_alloc and base class. + // Definitions for __pool_alloc_base. __pool_base::_Obj* volatile* __pool_base::_M_get_free_list(size_t __bytes) { size_t __i = ((__bytes + (size_t)_S_align - 1) / (size_t)_S_align - 1); - return _S_free_list + __i - 1; + return _S_free_list + __i; } + __gthread_mutex_t& + __pool_base::_M_get_mutex() + { return __gnu_internal::palloc_init_mutex; } + // Allocate memory in large chunks in order to avoid fragmenting the // heap too much. Assume that __n is properly aligned. We hold the // allocation lock. @@ -89,21 +94,17 @@ namespace __gnu_cxx _S_start_free = static_cast(::operator new(__bytes_to_get)); if (_S_start_free == 0) { - size_t __i; - _Obj* volatile* __free_list; - _Obj* __p; - // Try to make do with what we have. That can't hurt. We // do not try smaller requests, since that tends to result // in disaster on multi-process machines. - __i = __n; + size_t __i = __n; for (; __i <= (size_t) _S_max_bytes; __i += (size_t) _S_align) { - __free_list = _M_get_free_list(__i); - __p = *__free_list; + _Obj* volatile* __free_list = _M_get_free_list(__i); + _Obj* __p = *__free_list; if (__p != 0) { - *__free_list = __p -> _M_free_list_link; + *__free_list = __p->_M_free_list_link; _S_start_free = (char*)__p; _S_end_free = _S_start_free + __i; return _M_allocate_chunk(__n, __nobjs); @@ -112,9 +113,10 @@ namespace __gnu_cxx } } _S_end_free = 0; // In case of exception. - _S_start_free = static_cast(::operator new(__bytes_to_get)); + // This should either throw an exception or remedy the situation. // Thus we assume it succeeded. + _S_start_free = static_cast(::operator new(__bytes_to_get)); } _S_heap_size += __bytes_to_get; _S_end_free = _S_start_free + __bytes_to_get; @@ -134,26 +136,25 @@ namespace __gnu_cxx _Obj* __result; _Obj* __current_obj; _Obj* __next_obj; - int __i; - if (1 == __nobjs) + if (__nobjs == 1) return __chunk; __free_list = _M_get_free_list(__n); // Build free list in chunk. __result = (_Obj*)(void*)__chunk; *__free_list = __next_obj = (_Obj*)(void*)(__chunk + __n); - for (__i = 1; ; __i++) + for (int __i = 1; ; __i++) { __current_obj = __next_obj; __next_obj = (_Obj*)(void*)((char*)__next_obj + __n); if (__nobjs - 1 == __i) { - __current_obj -> _M_free_list_link = 0; + __current_obj->_M_free_list_link = 0; break; } else - __current_obj -> _M_free_list_link = __next_obj; + __current_obj->_M_free_list_link = __next_obj; } return __result; } @@ -165,9 +166,4 @@ namespace __gnu_cxx char* __pool_base::_S_end_free = 0; size_t __pool_base::_S_heap_size = 0; - - _STL_mutex_lock __pool_base::_Lock::_S_lock __STL_MUTEX_INITIALIZER; - - template class __pool_alloc; - template class __pool_alloc; } // namespace __gnu_cxx diff --git a/libstdc++-v3/src/locale_init.cc b/libstdc++-v3/src/locale_init.cc index 8383c2fb8ec..35dc3611a4b 100644 --- a/libstdc++-v3/src/locale_init.cc +++ b/libstdc++-v3/src/locale_init.cc @@ -100,25 +100,26 @@ namespace std locale::locale() throw() : _M_impl(0) { - _S_initialize(); - __glibcxx_mutex_lock(__gnu_internal::locale_cons_mutex); + _S_initialize(); + __gnu_cxx::lock sentry(__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; - const string __other_name = __other.name(); - if (__other_name != "*") - setlocale(LC_ALL, __other_name.c_str()); - __glibcxx_mutex_unlock(__gnu_internal::locale_global_mutex); + _Impl* __old; + { + __gnu_cxx::lock sentry(__gnu_internal::locale_global_mutex); + __old = _S_global; + __other._M_impl->_M_add_reference(); + _S_global = __other._M_impl; + const string __other_name = __other.name(); + if (__other_name != "*") + setlocale(LC_ALL, __other_name.c_str()); + } // Reference count sanity check: one reference removed for the // subsition of __other locale, one added by return-by-value. Net