GCC Bugzilla – Attachment 9700 Details for
Bug 22309
mt allocator doesn't pthread_key_delete its keys
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
patch for mainline/gcc-4_0-branch
p.20050909-2 (text/plain), 39.12 KB, created by
Benjamin Kosnik
on 2005-09-09 09:04:26 UTC
(
hide
)
Description:
patch for mainline/gcc-4_0-branch
Filename:
MIME Type:
Creator:
Benjamin Kosnik
Created:
2005-09-09 09:04:26 UTC
Size:
39.12 KB
patch
obsolete
>2005-09-08 Benjamin Kosnik <bkoz@redhat.com> > > PR libstdc++/19265 > PR libstdc++/22309 > * include/ext/mt_allocator.h > (__gnu_cxx::__destroy_handler): Remove. > (__gnu_cxx::__create_handler): Remove. > (__pool<true>::_M_destroy_thread_key): Compatibility only. > (__pool<true>::_M_initialize(__destroy): Same. > (__pool<true>::_M_initialize): New. > (__pool<true>::_M_initialize_once): Nothing fancy. > (__pool<true>::_M_once): Remove. > (__common_pool): New. > (__common_pool_base): New. > (__per_type_pool): New. > (__per_type_pool_base): New. > * src/mt_allocator.cc: Same. > * config/linker-map.gnu (__pool<true>::_M_initialize()): Add. > >2005-09-07 Jakub Jelinek <jakub@redhat.com> > > PR libstdc++/19265 > PR libstdc++/22309 > * src/mt_allocator.cc (__gnu_internal::freelist_mutex): Make static. > (__gnu_internal::__freelist): New type. > (__gnu_internal::freelist): New variable. > (__gnu_internal::_M_destroy_thread_key): New function. > (__gnu_cxx::__pool<true>::_M_destroy): Don't delete > _M_thread_freelist_initial. > (__gnu_cxx::__pool<true>::_M_initialize): Make argument nameless. > Don't use _M_thread_freelist and _M_thread_freelist_initial > __pool<true> fields, instead use __gnu_internal::freelist fields, call > gthread_key_create just once. Use > __gnu_internal::_M_destroy_thread_key as key destructor. > (__gnu_cxx::__pool<true>::_M_get_thread_id): Store size_t id > rather than _Thread_record* in the thread specific value. Don't > use _M_thread_freelist __pool<true> field, instead use > __gnu_internal::freelist fields. > (__gnu_cxx::__pool<true>::_M_destroy_thread_key): Do nothing. > >2005-09-06 Benjamin Kosnik <bkoz@redhat.com> > Jakub Jelinek <jakub@redhat.com> > > PR libstdc++/19265 > PR libstdc++/22309 > * testsuite/testsuite_shared.cc: New. > * testsuite/ext/mt_allocator/22309_thread.cc: New. > * testsuite/lib/libstdc++.exp (proc v3-build_support): Build > shared objects. > >Index: config/linker-map.gnu >=================================================================== >RCS file: /cvs/gcc/gcc/libstdc++-v3/config/linker-map.gnu,v >retrieving revision 1.84 >diff -c -p -r1.84 linker-map.gnu >*** config/linker-map.gnu 26 Aug 2005 21:10:58 -0000 1.84 >--- config/linker-map.gnu 9 Sep 2005 08:58:48 -0000 >*************** GLIBCXX_3.4.3 { >*** 515,522 **** > } GLIBCXX_3.4.2; > > GLIBCXX_3.4.4 { >! >! _ZN9__gnu_cxx6__poolILb0EE13_M_initializeEv; > _ZN9__gnu_cxx6__poolILb1EE13_M_initializeEPFvPvE; > _ZN9__gnu_cxx6__poolILb1EE21_M_destroy_thread_keyEPv; > _ZN9__gnu_cxx6__poolILb1EE16_M_get_thread_idEv; >--- 515,522 ---- > } GLIBCXX_3.4.2; > > GLIBCXX_3.4.4 { >! >! _ZN9__gnu_cxx6__poolILb0EE13_M_initializeEv; > _ZN9__gnu_cxx6__poolILb1EE13_M_initializeEPFvPvE; > _ZN9__gnu_cxx6__poolILb1EE21_M_destroy_thread_keyEPv; > _ZN9__gnu_cxx6__poolILb1EE16_M_get_thread_idEv; >*************** GLIBCXX_3.4.6 { >*** 571,576 **** >--- 571,578 ---- > > _ZNKSt15basic_stringbufIwSt11char_traitsIwESaIwEE3strEv; > >+ _ZN9__gnu_cxx6__poolILb1EE13_M_initializeEv; >+ > } GLIBCXX_3.4.5; > > # Symbols in the support library (libsupc++) have their own tag. >Index: include/ext/mt_allocator.h >=================================================================== >RCS file: /cvs/gcc/gcc/libstdc++-v3/include/ext/mt_allocator.h,v >retrieving revision 1.47 >diff -c -p -r1.47 mt_allocator.h >*** include/ext/mt_allocator.h 17 Aug 2005 02:13:19 -0000 1.47 >--- include/ext/mt_allocator.h 9 Sep 2005 08:58:50 -0000 >*************** >*** 43,49 **** > namespace __gnu_cxx > { > typedef void (*__destroy_handler)(void*); >- typedef void (*__create_handler)(void); > > /// @brief Base class for pool object. > struct __pool_base >--- 43,48 ---- >*************** namespace __gnu_cxx >*** 185,196 **** > template<bool _Thread> > class __pool; > >- template<> >- class __pool<true>; >- >- template<> >- class __pool<false>; >- > /// Specialization for single thread. > template<> > class __pool<false> : public __pool_base >--- 184,189 ---- >*************** namespace __gnu_cxx >*** 313,336 **** > __gthread_mutex_t* _M_mutex; > }; > > void >! _M_initialize(__destroy_handler __d); > > void >! _M_initialize_once(__create_handler __c) > { >- // Although the test in __gthread_once() would suffice, we >- // wrap test of the once condition in our own unlocked >- // check. This saves one function call to pthread_once() >- // (which itself only tests for the once value unlocked anyway >- // and immediately returns if set) > if (__builtin_expect(_M_init == false, false)) >! { >! if (__gthread_active_p()) >! __gthread_once(&_M_once, __c); >! if (!_M_init) >! __c(); >! } > } > > void >--- 306,320 ---- > __gthread_mutex_t* _M_mutex; > }; > >+ // XXX GLIBCXX_ABI Deprecated > void >! _M_initialize(__destroy_handler); > > void >! _M_initialize_once() > { > if (__builtin_expect(_M_init == false, false)) >! _M_initialize(); > } > > void >*************** namespace __gnu_cxx >*** 358,385 **** > } > } > > void >! _M_destroy_thread_key(void* __freelist_pos); > > size_t > _M_get_thread_id(); > > explicit __pool() > : _M_bin(NULL), _M_bin_size(1), _M_thread_freelist(NULL) >! { >! // On some platforms, __gthread_once_t is an aggregate. >! __gthread_once_t __tmp = __GTHREAD_ONCE_INIT; >! _M_once = __tmp; >! } > > explicit __pool(const __pool_base::_Tune& __tune) > : __pool_base(__tune), _M_bin(NULL), _M_bin_size(1), > _M_thread_freelist(NULL) >! { >! // On some platforms, __gthread_once_t is an aggregate. >! __gthread_once_t __tmp = __GTHREAD_ONCE_INIT; >! _M_once = __tmp; >! } > > private: > // An "array" of bin_records each of which represents a specific >--- 342,362 ---- > } > } > >+ // XXX GLIBCXX_ABI Deprecated > void >! _M_destroy_thread_key(void*); > > size_t > _M_get_thread_id(); > > explicit __pool() > : _M_bin(NULL), _M_bin_size(1), _M_thread_freelist(NULL) >! { } > > explicit __pool(const __pool_base::_Tune& __tune) > : __pool_base(__tune), _M_bin(NULL), _M_bin_size(1), > _M_thread_freelist(NULL) >! { } > > private: > // An "array" of bin_records each of which represents a specific >*************** namespace __gnu_cxx >*** 390,428 **** > // Actual value calculated in _M_initialize(). > size_t _M_bin_size; > >- __gthread_once_t _M_once; >- > _Thread_record* _M_thread_freelist; > void* _M_thread_freelist_initial; > }; > #endif > >- >- /// @brief Policy for shared __pool objects. > template<template <bool> class _PoolTp, bool _Thread> >! struct __common_pool_policy; >! >! /// Partial specialization for single thread. >! template<template <bool> class _PoolTp> >! struct __common_pool_policy<_PoolTp, false> > { >! typedef _PoolTp<false> pool_type; > >- template<typename _Tp1, template <bool> class _PoolTp1 = _PoolTp, >- bool _Thread1 = false> >- struct _M_rebind >- { typedef __common_pool_policy<_PoolTp1, _Thread1> other; }; >- > static pool_type& > _S_get_pool() > { > static pool_type _S_pool; > return _S_pool; > } > > static void >! _S_initialize_once() >! { > static bool __init; > if (__builtin_expect(__init == false, false)) > { >--- 367,405 ---- > // Actual value calculated in _M_initialize(). > size_t _M_bin_size; > > _Thread_record* _M_thread_freelist; > void* _M_thread_freelist_initial; >+ >+ void >+ _M_initialize(); > }; > #endif > > template<template <bool> class _PoolTp, bool _Thread> >! struct __common_pool > { >! typedef _PoolTp<_Thread> pool_type; > > static pool_type& > _S_get_pool() > { > static pool_type _S_pool; > return _S_pool; > } >+ }; >+ >+ template<template <bool> class _PoolTp, bool _Thread> >+ struct __common_pool_base; >+ >+ template<template <bool> class _PoolTp> >+ struct __common_pool_base<_PoolTp, false> >+ : public __common_pool<_PoolTp, false> >+ { >+ using __common_pool<_PoolTp, false>::_S_get_pool; > > static void >! _S_initialize_once() >! { > static bool __init; > if (__builtin_expect(__init == false, false)) > { >*************** namespace __gnu_cxx >*** 433,508 **** > }; > > #ifdef __GTHREADS >- /// Partial specialization for thread enabled, via gthreads.h. > template<template <bool> class _PoolTp> >! struct __common_pool_policy<_PoolTp, true> > { >! typedef _PoolTp<true> pool_type; > >! template<typename _Tp1, template <bool> class _PoolTp1 = _PoolTp, >! bool _Thread1 = true> >! struct _M_rebind >! { typedef __common_pool_policy<_PoolTp1, _Thread1> other; }; >! >! static pool_type& >! _S_get_pool() >! { >! static pool_type _S_pool; >! return _S_pool; >! } > > static void >! _S_initialize_once() > { > static bool __init; > if (__builtin_expect(__init == false, false)) > { >! _S_get_pool()._M_initialize_once(_S_initialize); > __init = true; > } > } >! >! private: >! static void >! _S_destroy_thread_key(void* __freelist_pos) >! { _S_get_pool()._M_destroy_thread_key(__freelist_pos); } >! >! static void >! _S_initialize() >! { _S_get_pool()._M_initialize(_S_destroy_thread_key); } >! }; > #endif > >! >! /// @brief Policy for individual __pool objects. >! template<typename _Tp, template <bool> class _PoolTp, bool _Thread> >! struct __per_type_pool_policy; >! >! /// Partial specialization for single thread. >! template<typename _Tp, template <bool> class _PoolTp> >! struct __per_type_pool_policy<_Tp, _PoolTp, false> > { >- typedef _Tp value_type; >- typedef _PoolTp<false> pool_type; >- > template<typename _Tp1, template <bool> class _PoolTp1 = _PoolTp, >! bool _Thread1 = false> > struct _M_rebind >! { typedef __per_type_pool_policy<_Tp1, _PoolTp1, _Thread1> other; }; > > static pool_type& > _S_get_pool() > { > // Sane defaults for the _PoolTp. > typedef typename pool_type::_Block_record _Block_record; >! const static size_t __align = (__alignof__(_Tp) >= sizeof(_Block_record) >! ? __alignof__(_Tp) >! : sizeof(_Block_record)); > > typedef typename __pool_base::_Tune _Tune; >! static _Tune _S_tune(__align, sizeof(_Tp) * 64, >! sizeof(_Tp) * 2 >= __align ? sizeof(_Tp) * 2 >! : __align, > sizeof(_Tp) * size_t(_Tune::_S_chunk_size), > _Tune::_S_max_threads, > _Tune::_S_freelist_headroom, >--- 410,476 ---- > }; > > #ifdef __GTHREADS > template<template <bool> class _PoolTp> >! struct __common_pool_base<_PoolTp, true> >! : public __common_pool<_PoolTp, true> > { >! using __common_pool<_PoolTp, true>::_S_get_pool; > >! static void >! _S_initialize() >! { _S_get_pool()._M_initialize_once(); } > > static void >! _S_initialize_once() > { > static bool __init; > if (__builtin_expect(__init == false, false)) > { >! if (__gthread_active_p()) >! { >! // On some platforms, __gthread_once_t is an aggregate. >! static __gthread_once_t __once = __GTHREAD_ONCE_INIT; >! __gthread_once(&__once, _S_initialize); >! } >! else >! _S_get_pool()._M_initialize_once(); > __init = true; > } > } >! }; > #endif > >! /// @brief Policy for shared __pool objects. >! template<template <bool> class _PoolTp, bool _Thread> >! struct __common_pool_policy : public __common_pool_base<_PoolTp, _Thread> > { > template<typename _Tp1, template <bool> class _PoolTp1 = _PoolTp, >! bool _Thread1 = _Thread> > struct _M_rebind >! { typedef __common_pool_policy<_PoolTp1, _Thread1> other; }; > >+ using __common_pool_base<_PoolTp, _Thread>::_S_get_pool; >+ using __common_pool_base<_PoolTp, _Thread>::_S_initialize_once; >+ }; >+ >+ >+ template<typename _Tp, template <bool> class _PoolTp, bool _Thread> >+ struct __per_type_pool >+ { >+ typedef _Tp value_type; >+ typedef _PoolTp<_Thread> pool_type; >+ > static pool_type& > _S_get_pool() > { > // Sane defaults for the _PoolTp. > typedef typename pool_type::_Block_record _Block_record; >! const static size_t __a = (__alignof__(_Tp) >= sizeof(_Block_record) >! ? __alignof__(_Tp) : sizeof(_Block_record)); > > typedef typename __pool_base::_Tune _Tune; >! static _Tune _S_tune(__a, sizeof(_Tp) * 64, >! sizeof(_Tp) * 2 >= __a ? sizeof(_Tp) * 2 : __a, > sizeof(_Tp) * size_t(_Tune::_S_chunk_size), > _Tune::_S_max_threads, > _Tune::_S_freelist_headroom, >*************** namespace __gnu_cxx >*** 510,519 **** > static pool_type _S_pool(_S_tune); > return _S_pool; > } > > static void > _S_initialize_once() >! { > static bool __init; > if (__builtin_expect(__init == false, false)) > { >--- 478,497 ---- > static pool_type _S_pool(_S_tune); > return _S_pool; > } >+ }; >+ >+ template<typename _Tp, template <bool> class _PoolTp, bool _Thread> >+ struct __per_type_pool_base; >+ >+ template<typename _Tp, template <bool> class _PoolTp> >+ struct __per_type_pool_base<_Tp, _PoolTp, false> >+ : public __per_type_pool<_Tp, _PoolTp, false> >+ { >+ using __per_type_pool<_Tp, _PoolTp, false>::_S_get_pool; > > static void > _S_initialize_once() >! { > static bool __init; > if (__builtin_expect(__init == false, false)) > { >*************** namespace __gnu_cxx >*** 523,561 **** > } > }; > >! #ifdef __GTHREADS >! /// Partial specialization for thread enabled, via gthreads.h. >! template<typename _Tp, template <bool> class _PoolTp> >! struct __per_type_pool_policy<_Tp, _PoolTp, true> > { >! typedef _Tp value_type; >! typedef _PoolTp<true> pool_type; > >! template<typename _Tp1, template <bool> class _PoolTp1 = _PoolTp, >! bool _Thread1 = true> >! struct _M_rebind >! { typedef __per_type_pool_policy<_Tp1, _PoolTp1, _Thread1> other; }; >! >! static pool_type& >! _S_get_pool() >! { >! // Sane defaults for the _PoolTp. >! typedef typename pool_type::_Block_record _Block_record; >! const static size_t __align = (__alignof__(_Tp) >= sizeof(_Block_record) >! ? __alignof__(_Tp) >! : sizeof(_Block_record)); >! >! typedef typename __pool_base::_Tune _Tune; >! static _Tune _S_tune(__align, sizeof(_Tp) * 64, >! sizeof(_Tp) * 2 >= __align ? sizeof(_Tp) * 2 >! : __align, >! sizeof(_Tp) * size_t(_Tune::_S_chunk_size), >! _Tune::_S_max_threads, >! _Tune::_S_freelist_headroom, >! getenv("GLIBCXX_FORCE_NEW") ? true : false); >! static pool_type _S_pool(_S_tune); >! return _S_pool; >! } > > static void > _S_initialize_once() >--- 501,516 ---- > } > }; > >! #ifdef __GTHREADS >! template<typename _Tp, template <bool> class _PoolTp> >! struct __per_type_pool_base<_Tp, _PoolTp, true> >! : public __per_type_pool<_Tp, _PoolTp, true> > { >! using __per_type_pool<_Tp, _PoolTp, true>::_S_get_pool; > >! static void >! _S_initialize() >! { _S_get_pool()._M_initialize_once(); } > > static void > _S_initialize_once() >*************** namespace __gnu_cxx >*** 563,584 **** > static bool __init; > if (__builtin_expect(__init == false, false)) > { >! _S_get_pool()._M_initialize_once(_S_initialize); > __init = true; > } > } >- >- private: >- static void >- _S_destroy_thread_key(void* __freelist_pos) >- { _S_get_pool()._M_destroy_thread_key(__freelist_pos); } >- >- static void >- _S_initialize() >- { _S_get_pool()._M_initialize(_S_destroy_thread_key); } > }; > #endif > > /// @brief Base class for _Tp dependent member functions. > template<typename _Tp> > class __mt_alloc_base >--- 518,552 ---- > static bool __init; > if (__builtin_expect(__init == false, false)) > { >! if (__gthread_active_p()) >! { >! // On some platforms, __gthread_once_t is an aggregate. >! static __gthread_once_t __once = __GTHREAD_ONCE_INIT; >! __gthread_once(&__once, _S_initialize); >! } >! else >! _S_get_pool()._M_initialize_once(); > __init = true; > } > } > }; > #endif > >+ /// @brief Policy for individual __pool objects. >+ template<typename _Tp, template <bool> class _PoolTp, bool _Thread> >+ struct __per_type_pool_policy >+ : public __per_type_pool_base<_Tp, _PoolTp, _Thread> >+ { >+ template<typename _Tp1, template <bool> class _PoolTp1 = _PoolTp, >+ bool _Thread1 = _Thread> >+ struct _M_rebind >+ { typedef __per_type_pool_policy<_Tp1, _PoolTp1, _Thread1> other; }; >+ >+ using __per_type_pool_base<_Tp, _PoolTp, _Thread>::_S_get_pool; >+ using __per_type_pool_base<_Tp, _PoolTp, _Thread>::_S_initialize_once; >+ }; >+ >+ > /// @brief Base class for _Tp dependent member functions. > template<typename _Tp> > class __mt_alloc_base >Index: src/mt_allocator.cc >=================================================================== >RCS file: /cvs/gcc/gcc/libstdc++-v3/src/mt_allocator.cc,v >retrieving revision 1.11 >diff -c -p -r1.11 mt_allocator.cc >*** src/mt_allocator.cc 17 Aug 2005 02:14:24 -0000 1.11 >--- src/mt_allocator.cc 9 Sep 2005 08:58:51 -0000 >*************** >*** 1,8 **** > // Allocator details. > >! // Copyright (C) 2004 Free Software Foundation, Inc. > // >! // This file is part of the GNU ISO C++ Librarbooly. 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) >--- 1,8 ---- > // Allocator details. > >! // Copyright (C) 2004, 2005 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) >*************** >*** 37,46 **** > > namespace __gnu_internal > { >- __glibcxx_mutex_define_initialized(freelist_mutex); >- > #ifdef __GTHREADS >! __gthread_key_t freelist_key; > #endif > } > >--- 37,78 ---- > > namespace __gnu_internal > { > #ifdef __GTHREADS >! struct __freelist >! { >! typedef __gnu_cxx::__pool<true>::_Thread_record _Thread_record; >! _Thread_record* _M_thread_freelist; >! _Thread_record* _M_thread_freelist_array; >! size_t _M_max_threads; >! __gthread_key_t _M_key; >! >! ~__freelist() >! { >! if (_M_thread_freelist_array) >! { >! __gthread_key_delete(_M_key); >! ::operator delete(static_cast<void*>(_M_thread_freelist_array)); >! } >! } >! }; >! >! // Ensure freelist is constructed first. >! static __freelist freelist; >! static __glibcxx_mutex_define_initialized(freelist_mutex); >! >! static void >! _M_destroy_thread_key(void* __id) >! { >! // Return this thread id record to front of thread_freelist. >! __gnu_cxx::lock sentry(__gnu_internal::freelist_mutex); >! size_t _M_id = reinterpret_cast<size_t>(__id); >! >! using namespace __gnu_internal; >! 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 > } > >*************** namespace __gnu_cxx >*** 171,176 **** >--- 203,209 ---- > } > _M_init = true; > } >+ > > #ifdef __GTHREADS > void >*************** namespace __gnu_cxx >*** 194,200 **** > ::operator delete(__bin._M_used); > ::operator delete(__bin._M_mutex); > } >- ::operator delete(_M_thread_freelist_initial); > } > else > { >--- 227,232 ---- >*************** namespace __gnu_cxx >*** 386,393 **** > return reinterpret_cast<char*>(__block) + __options._M_align; > } > >! void >! __pool<true>::_M_initialize(__destroy_handler __d) > { > // _M_force_new must not change after the first allocate(), > // which in turn calls this method, so if it's false, it's false >--- 418,425 ---- > return reinterpret_cast<char*>(__block) + __options._M_align; > } > >! void >! __pool<true>::_M_initialize() > { > // _M_force_new must not change after the first allocate(), > // which in turn calls this method, so if it's false, it's false >*************** namespace __gnu_cxx >*** 397,403 **** > _M_init = true; > return; > } >! > // Create the bins. > // Calculate the number of bins required based on _M_max_bytes. > // _M_bin_size is statically-initialized to one. >--- 429,435 ---- > _M_init = true; > return; > } >! > // Create the bins. > // Calculate the number of bins required based on _M_max_bytes. > // _M_bin_size is statically-initialized to one. >*************** namespace __gnu_cxx >*** 433,461 **** > // directly and have no need for this. > if (__gthread_active_p()) > { >! const size_t __k = sizeof(_Thread_record) * _M_options._M_max_threads; >! __v = ::operator new(__k); >! _M_thread_freelist = static_cast<_Thread_record*>(__v); >! _M_thread_freelist_initial = __v; >! >! // NOTE! The first assignable thread id is 1 since the >! // global pool uses id 0 >! size_t __i; >! for (__i = 1; __i < _M_options._M_max_threads; ++__i) >! { >! _Thread_record& __tr = _M_thread_freelist[__i - 1]; >! __tr._M_next = &_M_thread_freelist[__i]; >! __tr._M_id = __i; >! } >! >! // Set last record. >! _M_thread_freelist[__i - 1]._M_next = NULL; >! _M_thread_freelist[__i - 1]._M_id = __i; >! >! // Initialize per thread key to hold pointer to >! // _M_thread_freelist. >! __gthread_key_create(&__gnu_internal::freelist_key, __d); >! > const size_t __max_threads = _M_options._M_max_threads + 1; > for (size_t __n = 0; __n < _M_bin_size; ++__n) > { >--- 465,534 ---- > // directly and have no need for this. > if (__gthread_active_p()) > { >! { >! __gnu_cxx::lock sentry(__gnu_internal::freelist_mutex); >! >! if (!__gnu_internal::freelist._M_thread_freelist_array >! || __gnu_internal::freelist._M_max_threads >! < _M_options._M_max_threads) >! { >! const size_t __k = sizeof(_Thread_record) >! * _M_options._M_max_threads; >! __v = ::operator new(__k); >! _Thread_record* _M_thread_freelist >! = static_cast<_Thread_record*>(__v); >! >! // NOTE! The first assignable thread id is 1 since the >! // global pool uses id 0 >! size_t __i; >! for (__i = 1; __i < _M_options._M_max_threads; ++__i) >! { >! _Thread_record& __tr = _M_thread_freelist[__i - 1]; >! __tr._M_next = &_M_thread_freelist[__i]; >! __tr._M_id = __i; >! } >! >! // Set last record. >! _M_thread_freelist[__i - 1]._M_next = NULL; >! _M_thread_freelist[__i - 1]._M_id = __i; >! >! if (!__gnu_internal::freelist._M_thread_freelist_array) >! { >! // Initialize per thread key to hold pointer to >! // _M_thread_freelist. >! __gthread_key_create(&__gnu_internal::freelist._M_key, >! __gnu_internal::_M_destroy_thread_key); >! __gnu_internal::freelist._M_thread_freelist >! = _M_thread_freelist; >! } >! else >! { >! _Thread_record* _M_old_freelist >! = __gnu_internal::freelist._M_thread_freelist; >! _Thread_record* _M_old_array >! = __gnu_internal::freelist._M_thread_freelist_array; >! __gnu_internal::freelist._M_thread_freelist >! = &_M_thread_freelist[_M_old_freelist - _M_old_array]; >! while (_M_old_freelist) >! { >! size_t next_id; >! if (_M_old_freelist->_M_next) >! next_id = _M_old_freelist->_M_next - _M_old_array; >! else >! next_id = __gnu_internal::freelist._M_max_threads; >! _M_thread_freelist[_M_old_freelist->_M_id - 1]._M_next >! = &_M_thread_freelist[next_id]; >! _M_old_freelist = _M_old_freelist->_M_next; >! } >! ::operator delete(static_cast<void*>(_M_old_array)); >! } >! __gnu_internal::freelist._M_thread_freelist_array >! = _M_thread_freelist; >! __gnu_internal::freelist._M_max_threads >! = _M_options._M_max_threads; >! } >! } >! > const size_t __max_threads = _M_options._M_max_threads + 1; > for (size_t __n = 0; __n < _M_bin_size; ++__n) > { >*************** namespace __gnu_cxx >*** 514,536 **** > // returns it's id. > if (__gthread_active_p()) > { >! void* v = __gthread_getspecific(__gnu_internal::freelist_key); >! _Thread_record* __freelist_pos = static_cast<_Thread_record*>(v); >! if (__freelist_pos == NULL) >! { >! // Since _M_options._M_max_threads must be larger than >! // the theoretical max number of threads of the OS the >! // list can never be empty. > { > __gnu_cxx::lock sentry(__gnu_internal::freelist_mutex); >! __freelist_pos = _M_thread_freelist; >! _M_thread_freelist = _M_thread_freelist->_M_next; > } >! >! __gthread_setspecific(__gnu_internal::freelist_key, >! static_cast<void*>(__freelist_pos)); > } >! return __freelist_pos->_M_id; > } > > // Otherwise (no thread support or inactive) all requests are >--- 587,610 ---- > // returns it's id. > if (__gthread_active_p()) > { >! void* v = __gthread_getspecific(__gnu_internal::freelist._M_key); >! size_t _M_id = (size_t)v; >! if (_M_id == 0) >! { > { > __gnu_cxx::lock sentry(__gnu_internal::freelist_mutex); >! if (__gnu_internal::freelist._M_thread_freelist) >! { >! _M_id = __gnu_internal::freelist._M_thread_freelist->_M_id; >! __gnu_internal::freelist._M_thread_freelist >! = __gnu_internal::freelist._M_thread_freelist->_M_next; >! } > } >! >! __gthread_setspecific(__gnu_internal::freelist._M_key, >! (void*)_M_id); > } >! return _M_id >= _M_options._M_max_threads ? 0 : _M_id; > } > > // Otherwise (no thread support or inactive) all requests are >*************** namespace __gnu_cxx >*** 538,551 **** > return 0; > } > > void >! __pool<true>::_M_destroy_thread_key(void* __freelist_pos) > { >! // Return this thread id record to front of thread_freelist. >! __gnu_cxx::lock sentry(__gnu_internal::freelist_mutex); >! _Thread_record* __tr = static_cast<_Thread_record*>(__freelist_pos); >! __tr->_M_next = _M_thread_freelist; >! _M_thread_freelist = __tr; > } > #endif > >--- 612,780 ---- > return 0; > } > >+ // XXX GLIBCXX_ABI Deprecated >+ void >+ __pool<true>::_M_destroy_thread_key(void*) { } >+ >+ // XXX GLIBCXX_ABI Deprecated > void >! __pool<true>::_M_initialize(__destroy_handler) > { >! // _M_force_new must not change after the first allocate(), >! // which in turn calls this method, so if it's false, it's false >! // forever and we don't need to return here ever again. >! if (_M_options._M_force_new) >! { >! _M_init = true; >! return; >! } >! >! // Create the bins. >! // Calculate the number of bins required based on _M_max_bytes. >! // _M_bin_size is statically-initialized to one. >! size_t __bin_size = _M_options._M_min_bin; >! while (_M_options._M_max_bytes > __bin_size) >! { >! __bin_size <<= 1; >! ++_M_bin_size; >! } >! >! // Setup the bin map for quick lookup of the relevant bin. >! const size_t __j = (_M_options._M_max_bytes + 1) * sizeof(_Binmap_type); >! _M_binmap = static_cast<_Binmap_type*>(::operator new(__j)); >! _Binmap_type* __bp = _M_binmap; >! _Binmap_type __bin_max = _M_options._M_min_bin; >! _Binmap_type __bint = 0; >! for (_Binmap_type __ct = 0; __ct <= _M_options._M_max_bytes; ++__ct) >! { >! if (__ct > __bin_max) >! { >! __bin_max <<= 1; >! ++__bint; >! } >! *__bp++ = __bint; >! } >! >! // Initialize _M_bin and its members. >! void* __v = ::operator new(sizeof(_Bin_record) * _M_bin_size); >! _M_bin = static_cast<_Bin_record*>(__v); >! >! // If __gthread_active_p() create and initialize the list of >! // free thread ids. Single threaded applications use thread id 0 >! // directly and have no need for this. >! if (__gthread_active_p()) >! { >! { >! __gnu_cxx::lock sentry(__gnu_internal::freelist_mutex); >! >! if (!__gnu_internal::freelist._M_thread_freelist_array >! || __gnu_internal::freelist._M_max_threads >! < _M_options._M_max_threads) >! { >! const size_t __k = sizeof(_Thread_record) >! * _M_options._M_max_threads; >! __v = ::operator new(__k); >! _Thread_record* _M_thread_freelist >! = static_cast<_Thread_record*>(__v); >! >! // NOTE! The first assignable thread id is 1 since the >! // global pool uses id 0 >! size_t __i; >! for (__i = 1; __i < _M_options._M_max_threads; ++__i) >! { >! _Thread_record& __tr = _M_thread_freelist[__i - 1]; >! __tr._M_next = &_M_thread_freelist[__i]; >! __tr._M_id = __i; >! } >! >! // Set last record. >! _M_thread_freelist[__i - 1]._M_next = NULL; >! _M_thread_freelist[__i - 1]._M_id = __i; >! >! if (!__gnu_internal::freelist._M_thread_freelist_array) >! { >! // Initialize per thread key to hold pointer to >! // _M_thread_freelist. >! __gthread_key_create(&__gnu_internal::freelist._M_key, >! __gnu_internal::_M_destroy_thread_key); >! __gnu_internal::freelist._M_thread_freelist >! = _M_thread_freelist; >! } >! else >! { >! _Thread_record* _M_old_freelist >! = __gnu_internal::freelist._M_thread_freelist; >! _Thread_record* _M_old_array >! = __gnu_internal::freelist._M_thread_freelist_array; >! __gnu_internal::freelist._M_thread_freelist >! = &_M_thread_freelist[_M_old_freelist - _M_old_array]; >! while (_M_old_freelist) >! { >! size_t next_id; >! if (_M_old_freelist->_M_next) >! next_id = _M_old_freelist->_M_next - _M_old_array; >! else >! next_id = __gnu_internal::freelist._M_max_threads; >! _M_thread_freelist[_M_old_freelist->_M_id - 1]._M_next >! = &_M_thread_freelist[next_id]; >! _M_old_freelist = _M_old_freelist->_M_next; >! } >! ::operator delete(static_cast<void*>(_M_old_array)); >! } >! __gnu_internal::freelist._M_thread_freelist_array >! = _M_thread_freelist; >! __gnu_internal::freelist._M_max_threads >! = _M_options._M_max_threads; >! } >! } >! >! const size_t __max_threads = _M_options._M_max_threads + 1; >! for (size_t __n = 0; __n < _M_bin_size; ++__n) >! { >! _Bin_record& __bin = _M_bin[__n]; >! __v = ::operator new(sizeof(_Block_record*) * __max_threads); >! __bin._M_first = static_cast<_Block_record**>(__v); >! >! __bin._M_address = NULL; >! >! __v = ::operator new(sizeof(size_t) * __max_threads); >! __bin._M_free = static_cast<size_t*>(__v); >! >! __v = ::operator new(sizeof(size_t) * __max_threads); >! __bin._M_used = static_cast<size_t*>(__v); >! >! __v = ::operator new(sizeof(__gthread_mutex_t)); >! __bin._M_mutex = static_cast<__gthread_mutex_t*>(__v); >! >! #ifdef __GTHREAD_MUTEX_INIT >! { >! // Do not copy a POSIX/gthr mutex once in use. >! __gthread_mutex_t __tmp = __GTHREAD_MUTEX_INIT; >! *__bin._M_mutex = __tmp; >! } >! #else >! { __GTHREAD_MUTEX_INIT_FUNCTION(__bin._M_mutex); } >! #endif >! for (size_t __threadn = 0; __threadn < __max_threads; ++__threadn) >! { >! __bin._M_first[__threadn] = NULL; >! __bin._M_free[__threadn] = 0; >! __bin._M_used[__threadn] = 0; >! } >! } >! } >! else >! { >! for (size_t __n = 0; __n < _M_bin_size; ++__n) >! { >! _Bin_record& __bin = _M_bin[__n]; >! __v = ::operator new(sizeof(_Block_record*)); >! __bin._M_first = static_cast<_Block_record**>(__v); >! __bin._M_first[0] = NULL; >! __bin._M_address = NULL; >! } >! } >! _M_init = true; > } > #endif > >Index: testsuite/testsuite_shared.cc >=================================================================== >RCS file: testsuite/testsuite_shared.cc >diff -N testsuite/testsuite_shared.cc >*** /dev/null 1 Jan 1970 00:00:00 -0000 >--- testsuite/testsuite_shared.cc 9 Sep 2005 08:58:51 -0000 >*************** >*** 0 **** >--- 1,36 ---- >+ // Copyright (C) 2004, 2005 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, >+ // USA. >+ >+ #include <string> >+ #include <ext/mt_allocator.h> >+ >+ // libstdc++/22309 >+ extern "C" void >+ foo() >+ { >+ typedef char value_t; >+ >+ typedef __gnu_cxx::__common_pool_policy<__gnu_cxx::__pool, true> policy_t; >+ typedef __gnu_cxx::__mt_alloc<value_t, policy_t> allocator_t; >+ >+ typedef std::char_traits<value_t> traits_t; >+ typedef std::basic_string<value_t, traits_t, allocator_t> string_t; >+ >+ string_t s; >+ s += "west beach, indiana dunes"; >+ } >Index: testsuite/ext/mt_allocator/22309_thread.cc >=================================================================== >RCS file: testsuite/ext/mt_allocator/22309_thread.cc >diff -N testsuite/ext/mt_allocator/22309_thread.cc >*** /dev/null 1 Jan 1970 00:00:00 -0000 >--- testsuite/ext/mt_allocator/22309_thread.cc 9 Sep 2005 08:58:52 -0000 >*************** >*** 0 **** >--- 1,100 ---- >+ // { dg-do run { target *-*-linux* } } >+ // { dg-options "-g -O2 -pthread -ldl" { target *-*-linux* } } >+ >+ // Copyright (C) 2004, 2005 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, >+ // USA. >+ >+ #include <dlfcn.h> >+ #include <pthread.h> >+ #include <cstdlib> >+ #include <stdexcept> >+ >+ void >+ check_dlopen(void*& h) >+ { >+ dlerror(); >+ void* tmp = dlopen("./testsuite_shared.so", RTLD_LAZY); >+ if (!tmp) >+ { >+ try >+ { >+ // Throws std::logic_error on NULL string. >+ std::string error(dlerror()); >+ throw std::runtime_error(error); >+ } >+ catch (const std::logic_error&) >+ { } >+ } >+ h = tmp; >+ } >+ >+ void >+ check_dlsym(void*& h) >+ { >+ dlerror(); >+ >+ typedef void (*function_type) (void); >+ function_type fn; >+ fn = reinterpret_cast<function_type>(dlsym(h, "foo")); >+ >+ try >+ { >+ std::string error(dlerror()); >+ throw std::runtime_error(error); >+ } >+ catch (const std::logic_error&) >+ { } >+ >+ fn(); >+ } >+ >+ void >+ check_dlclose(void*& h) >+ { >+ dlerror(); >+ if (dlclose(h) != 0) >+ { >+ try >+ { >+ std::string error(dlerror()); >+ throw std::runtime_error(error); >+ } >+ catch (const std::logic_error&) >+ { } >+ } >+ } >+ >+ void* >+ tf(void* arg) >+ { >+ void* h; >+ check_dlopen(h); >+ check_dlsym(h); >+ check_dlclose(h); >+ return 0; >+ } >+ >+ // libstdc++/22309 >+ int >+ main (void) >+ { >+ pthread_t th; >+ pthread_create(&th, NULL, tf, NULL); >+ pthread_join(th, NULL); >+ return 0; >+ } >Index: testsuite/lib/libstdc++.exp >=================================================================== >RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/lib/libstdc++.exp,v >retrieving revision 1.45 >diff -c -p -r1.45 libstdc++.exp >*** testsuite/lib/libstdc++.exp 1 Sep 2005 16:58:25 -0000 1.45 >--- testsuite/lib/libstdc++.exp 9 Sep 2005 08:58:52 -0000 >*************** proc v3-build_support {} { >*** 353,359 **** > > # Build the support objects. > set source_files \ >! [list testsuite_abi.cc testsuite_allocator.cc testsuite_character.cc testsuite_hooks.cc] > foreach f $source_files { > set object_file [file rootname $f].o > # Compile with "-w" so that warnings issued by the compiler >--- 353,359 ---- > > # Build the support objects. > set source_files \ >! [list testsuite_abi.cc testsuite_allocator.cc testsuite_character.cc testsuite_hooks.cc ] > foreach f $source_files { > set object_file [file rootname $f].o > # Compile with "-w" so that warnings issued by the compiler >*************** proc v3-build_support {} { >*** 365,370 **** >--- 365,384 ---- > } > append v3-test_objs "$object_file " > } >+ >+ # Build the shared support objects. >+ set source_files \ >+ [list testsuite_shared.cc] >+ foreach f $source_files { >+ set object_file [file rootname $f].so >+ # Compile with "-w" so that warnings issued by the compiler >+ # do not prevent compilation. >+ if { [v3_target_compile $srcdir/$f $object_file "executable" \ >+ [list "incdir=$srcdir" "additional_flags=-w -shared -fPIC -DPIC"]] >+ != "" } { >+ error "could not compile $f" >+ } >+ } > } > > proc check_v3_target_namedlocale { } { >*************** proc check_v3_target_cxa_atexit { } { >*** 491,517 **** > puts $f "static unsigned int count;" > puts $f "struct X" > puts $f "{" >! puts $f "X() { count = 1; }" >! puts $f "~X()" >! puts $f "{" >! puts $f " if (count != 3)" >! puts $f " exit(1);" >! puts $f " count = 4;" >! puts $f "}" > puts $f "};" > puts $f "void f()" > puts $f "{" >! puts $f "static X x;" > puts $f "}" > puts $f "struct Y" > puts $f "{" >! puts $f "Y() { f(); count = 2; }" >! puts $f "~Y()" >! puts $f "{" >! puts $f "if (count != 2)" >! puts $f " exit(1);" >! puts $f "count = 3;" >! puts $f "}" > puts $f "};" > puts $f "Y y;" > puts $f "int main()" >--- 505,531 ---- > puts $f "static unsigned int count;" > puts $f "struct X" > puts $f "{" >! puts $f " X() { count = 1; }" >! puts $f " ~X()" >! puts $f " {" >! puts $f " if (count != 3)" >! puts $f " exit(1);" >! puts $f " count = 4;" >! puts $f " }" > puts $f "};" > puts $f "void f()" > puts $f "{" >! puts $f " static X x;" > puts $f "}" > puts $f "struct Y" > puts $f "{" >! puts $f " Y() { f(); count = 2; }" >! puts $f " ~Y()" >! puts $f " {" >! puts $f " if (count != 2)" >! puts $f " exit(1);" >! puts $f " count = 3;" >! puts $f " }" > puts $f "};" > puts $f "Y y;" > puts $f "int main()"
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 22309
:
9614
|
9677
|
9698
| 9700