Commit c37514ff by Benjamin Kosnik Committed by Benjamin Kosnik

allocator-inst.cc: Explicitly instantiate.


2003-06-12  Benjamin Kosnik  <bkoz@redhat.com>

	* src/allocator-inst.cc: Explicitly instantiate.
	* include/ext/pool_allocator.h: Inhibit implicit instantiations.
	Tweaks.
	* config/linker-map.gnu: Add __pool_alloc bits. Tweaks.

From-SVN: r67882
parent 5482aaab
2003-06-12 Benjamin Kosnik <bkoz@redhat.com>
* src/allocator-inst.cc: Explicitly instantiate.
* include/ext/pool_allocator.h: Inhibit implicit instantiations.
Tweaks.
* config/linker-map.gnu: Add __pool_alloc bits. Tweaks.
2003-06-11 Benjamin Kosnik <bkoz@redhat.com> 2003-06-11 Benjamin Kosnik <bkoz@redhat.com>
* acinclude.m4 (GLIBCPP_ENABLE_CSTDIO): Simplify. * acinclude.m4 (GLIBCPP_ENABLE_CSTDIO): Simplify.
......
...@@ -55,12 +55,7 @@ GLIBCPP_3.4 { ...@@ -55,12 +55,7 @@ GLIBCPP_3.4 {
std::__num_base::_S_format_float*; std::__num_base::_S_format_float*;
std::__num_base::_S_format_int*; std::__num_base::_S_format_int*;
std::__num_base::_S_atoms_in; std::__num_base::_S_atoms_in;
std::__num_base::_S_atoms_out; std::__num_base::_S_atoms_out
# Needed only when generic cpu's atomicity.h is in use.
__gnu_cxx::_Atomic_add_mutex;
__gnu_cxx::_Atomic_add_mutex_once;
__gnu_cxx::__gthread_atomic_add_mutex_once
}; };
# Names not in an 'extern' block are mangled names. # Names not in an 'extern' block are mangled names.
...@@ -78,28 +73,7 @@ GLIBCPP_3.4 { ...@@ -78,28 +73,7 @@ GLIBCPP_3.4 {
# bool has_facet # bool has_facet
_ZSt9has_facet*; _ZSt9has_facet*;
# operator new(size_t) # virtual table
_Znw[jm];
# operator new(size_t, std::nothrow_t const&)
_Znw[jm]RKSt9nothrow_t;
# operator delete(void*)
_ZdlPv;
# operator delete(void*, std::nothrow_t const&)
_ZdlPvRKSt9nothrow_t;
# operator new[](size_t)
_Zna[jm];
# operator new[](size_t, std::nothrow_t const&)
_Zna[jm]RKSt9nothrow_t;
# operator delete[](void*)
_ZdaPv;
# operator delete[](void*, std::nothrow_t const&)
_ZdaPvRKSt9nothrow_t;
# vtable
_ZTVN9__gnu_cxx*;
_ZTVNSt8ios_base7failureE; _ZTVNSt8ios_base7failureE;
_ZTVNSt6locale5facetE; _ZTVNSt6locale5facetE;
_ZTVS[a-z]; _ZTVS[a-z];
...@@ -109,18 +83,15 @@ GLIBCPP_3.4 { ...@@ -109,18 +83,15 @@ GLIBCPP_3.4 {
_ZTVSt23__codecvt_abstract_baseI[cw]c11__mbstate_tE; _ZTVSt23__codecvt_abstract_baseI[cw]c11__mbstate_tE;
_ZTVSt21__ctype_abstract_baseI[cw]E; _ZTVSt21__ctype_abstract_baseI[cw]E;
# VTT structure
_ZTTS[a-z]; _ZTTS[a-z];
_ZTTSt[0-9][A-Za-z]*; _ZTTSt[0-9][A-Za-z]*;
_ZTTSt[0-9][0-9][A-Za-z]*; _ZTTSt[0-9][0-9][A-Za-z]*;
# typeinfo # typeinfo structure
_ZTI[a-z]; _ZTIS[a-z];
_ZTINSt8ios_base7failureE; _ZTINSt8ios_base7failureE;
_ZTINSt6locale5facetE; _ZTINSt6locale5facetE;
_ZTIN9__gnu_cxx*;
_ZTIP[a-z];
_ZTIPK[a-z];
_ZTIS[a-z];
_ZTISt[0-9][A-Za-z]*; _ZTISt[0-9][A-Za-z]*;
_ZTISt[0-9][0-9][A-Za-z]*; _ZTISt[0-9][0-9][A-Za-z]*;
_ZTISt11__timepunctI[cw]E; _ZTISt11__timepunctI[cw]E;
...@@ -128,12 +99,9 @@ GLIBCPP_3.4 { ...@@ -128,12 +99,9 @@ GLIBCPP_3.4 {
_ZTISt21__ctype_abstract_baseI[cw]E; _ZTISt21__ctype_abstract_baseI[cw]E;
_ZTISt23__codecvt_abstract_baseI[cw]c11__mbstate_tE; _ZTISt23__codecvt_abstract_baseI[cw]c11__mbstate_tE;
_ZTS[a-z]; # typeinfo name
_ZTSNSt8ios_base7failureE; _ZTSNSt8ios_base7failureE;
_ZTSNSt6locale5facetE; _ZTSNSt6locale5facetE;
_ZTSN9__gnu_cxx*;
_ZTSP[a-z];
_ZTSPK[a-z];
_ZTSS[a-z]; _ZTSS[a-z];
_ZTSSt[0-9][A-Za-z]*; _ZTSSt[0-9][A-Za-z]*;
_ZTSSt[0-9][0-9][A-Za-z]*; _ZTSSt[0-9][0-9][A-Za-z]*;
...@@ -143,12 +111,11 @@ GLIBCPP_3.4 { ...@@ -143,12 +111,11 @@ GLIBCPP_3.4 {
_ZTSSt23__codecvt_abstract_baseI[cw]c11__mbstate_tE; _ZTSSt23__codecvt_abstract_baseI[cw]c11__mbstate_tE;
# function-scope static objects requires a guard variable. # function-scope static objects requires a guard variable.
_ZGV*; _ZGVNSt*;
# virtual function thunks # virtual function thunks
_ZTh*; _ZThn8_NS*;
_ZTv*; _ZTv0_n12_NS*;
_ZTc*;
# std::__convert_to_v # std::__convert_to_v
_ZSt14__convert_to_v*; _ZSt14__convert_to_v*;
...@@ -187,6 +154,18 @@ GLIBCPP_3.4 { ...@@ -187,6 +154,18 @@ GLIBCPP_3.4 {
__signbitf; __signbitf;
__signbitl; __signbitl;
# __gnu_cxx::__pool_alloc
_ZN9__gnu_cxx12__pool_allocILb1ELi0EE8allocateE[jm];
_ZN9__gnu_cxx12__pool_allocILb1ELi0EE10deallocateEPv[jm];
# __gnu_cxx::stdio_sync_filebuf
_ZTVN9__gnu_cxx18stdio_sync_filebufI[cw]St11char_traitsI[cw]EEE;
# Needed only when generic cpu's atomicity.h is in use.
_ZN9__gnu_cxx17_Atomic_add_mutexE;
_ZN9__gnu_cxx22_Atomic_add_mutex_onceE;
_ZN9__gnu_cxx31__gthread_atomic_add_mutex_onceEv;
local: local:
*; *;
}; };
...@@ -227,15 +206,60 @@ CXXABI_1.3 { ...@@ -227,15 +206,60 @@ CXXABI_1.3 {
__gxx_personality_sj0; __gxx_personality_sj0;
__dynamic_cast; __dynamic_cast;
# __gnu_cxx::_verbose_terminate_handler() # operator new(size_t)
_ZN9__gnu_cxx27__verbose_terminate_handlerEv; _Znw[jm];
# operator new(size_t, std::nothrow_t const&)
_Znw[jm]RKSt9nothrow_t;
# operator delete(void*)
_ZdlPv;
# operator delete(void*, std::nothrow_t const&)
_ZdlPvRKSt9nothrow_t;
# typeinfo # operator new[](size_t)
_ZTIN10__cxxabi*; _Zna[jm];
_ZTSN10__cxxabi*; # operator new[](size_t, std::nothrow_t const&)
_Zna[jm]RKSt9nothrow_t;
# vtable # operator delete[](void*)
_ZTVN10__cxxabi*; _ZdaPv;
# operator delete[](void*, std::nothrow_t const&)
_ZdaPvRKSt9nothrow_t;
# virtual table
_ZTVN10__cxxabiv117__class_type_infoE;
_ZTVN10__cxxabiv120__si_class_type_infoE;
_ZTVN10__cxxabiv121__vmi_class_type_infoE;
_ZTVN10__cxxabiv123__fundamental_type_infoE;
_ZTVN10__cxxabiv117__array_type_infoE;
_ZTVN10__cxxabiv120__function_type_infoE;
_ZTVN10__cxxabiv116__enum_type_infoE;
_ZTVN10__cxxabiv117__pbase_type_infoE;
_ZTVN10__cxxabiv119__pointer_type_infoE;
_ZTVN10__cxxabiv129__pointer_to_member_type_infoE;
# typeinfo structure (and some names)
_ZTI[a-z];
_ZTIP[a-z];
_ZTIPK[a-z];
_ZTIN10__cxxabiv117__class_type_infoE;
_ZTIN10__cxxabiv120__si_class_type_infoE;
_ZTIN10__cxxabiv121__vmi_class_type_infoE;
_ZTIN10__cxxabiv123__fundamental_type_infoE;
_ZTIN10__cxxabiv117__array_type_infoE;
_ZTIN10__cxxabiv120__function_type_infoE;
_ZTIN10__cxxabiv116__enum_type_infoE;
_ZTIN10__cxxabiv117__pbase_type_infoE;
_ZTIN10__cxxabiv119__pointer_type_infoE;
_ZTIN10__cxxabiv129__pointer_to_member_type_infoE;
# typeinfo name
_ZTS[a-z];
_ZTSP[a-z];
_ZTSPK[a-z];
# __gnu_cxx::_verbose_terminate_handler()
_ZN9__gnu_cxx27__verbose_terminate_handlerEv;
local: local:
*; *;
......
...@@ -129,7 +129,7 @@ namespace __gnu_cxx ...@@ -129,7 +129,7 @@ namespace __gnu_cxx
// Allocates a chunk for nobjs of size size. nobjs may be reduced // Allocates a chunk for nobjs of size size. nobjs may be reduced
// if it is inconvenient to allocate the requested number. // if it is inconvenient to allocate the requested number.
static char* static char*
_S_chunk_alloc(size_t __size, int& __nobjs); _S_chunk_alloc(size_t __n, int& __nobjs);
// It would be nice to use _STL_auto_lock here. But we need a // It would be nice to use _STL_auto_lock here. But we need a
// test whether threads are in use. // test whether threads are in use.
...@@ -143,70 +143,13 @@ namespace __gnu_cxx ...@@ -143,70 +143,13 @@ namespace __gnu_cxx
public: public:
// __n must be > 0 // __n must be > 0
static void* static void*
allocate(size_t __n) allocate(size_t __n);
{
void* __ret = 0;
// If there is a race through here, assume answer from getenv
// will resolve in same direction. Inspired by techniques
// to efficiently support threading found in basic_string.h.
if (_S_force_new == 0)
{
if (getenv("GLIBCPP_FORCE_NEW"))
__atomic_add(&_S_force_new, 1);
else
__atomic_add(&_S_force_new, -1);
}
if ((__n > (size_t) _S_max_bytes) || (_S_force_new > 0))
__ret = __new_alloc::allocate(__n);
else
{
_Obj* volatile* __my_free_list = _S_free_list
+ _S_freelist_index(__n);
// Acquire the lock here with a constructor call. This
// ensures that it is released in exit or during stack
// unwinding.
_Lock __lock_instance;
_Obj* __restrict__ __result = *__my_free_list;
if (__builtin_expect(__result == 0, 0))
__ret = _S_refill(_S_round_up(__n));
else
{
*__my_free_list = __result -> _M_free_list_link;
__ret = __result;
}
if (__builtin_expect(__ret == 0, 0))
__throw_bad_alloc();
}
return __ret;
}
// __p may not be 0 // __p may not be 0
static void static void
deallocate(void* __p, size_t __n) deallocate(void* __p, size_t __n);
{
if ((__n > (size_t) _S_max_bytes) || (_S_force_new > 0))
__new_alloc::deallocate(__p, __n);
else
{
_Obj* volatile* __my_free_list = _S_free_list
+ _S_freelist_index(__n);
_Obj* __q = (_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;
__q -> _M_free_list_link = *__my_free_list;
*__my_free_list = __q;
}
}
}; };
template<bool __threads, int __inst> _Atomic_word
__pool_alloc<__threads, __inst>::_S_force_new = 0;
template<bool __threads, int __inst> template<bool __threads, int __inst>
inline bool inline bool
operator==(const __pool_alloc<__threads,__inst>&, operator==(const __pool_alloc<__threads,__inst>&,
...@@ -220,16 +163,15 @@ namespace __gnu_cxx ...@@ -220,16 +163,15 @@ namespace __gnu_cxx
{ return false; } { return false; }
// We allocate memory in large chunks in order to avoid fragmenting the // Allocate memory in large chunks in order to avoid fragmenting the
// heap too much. We assume that __size is properly aligned. We hold // heap too much. Assume that __n is properly aligned. We hold
// the allocation lock. // the allocation lock.
template<bool __threads, int __inst> template<bool __threads, int __inst>
char* char*
__pool_alloc<__threads, __inst>:: __pool_alloc<__threads, __inst>::_S_chunk_alloc(size_t __n, int& __nobjs)
_S_chunk_alloc(size_t __size, int& __nobjs)
{ {
char* __result; char* __result;
size_t __total_bytes = __size * __nobjs; size_t __total_bytes = __n * __nobjs;
size_t __bytes_left = _S_end_free - _S_start_free; size_t __bytes_left = _S_end_free - _S_start_free;
if (__bytes_left >= __total_bytes) if (__bytes_left >= __total_bytes)
...@@ -238,10 +180,10 @@ namespace __gnu_cxx ...@@ -238,10 +180,10 @@ namespace __gnu_cxx
_S_start_free += __total_bytes; _S_start_free += __total_bytes;
return __result ; return __result ;
} }
else if (__bytes_left >= __size) else if (__bytes_left >= __n)
{ {
__nobjs = (int)(__bytes_left/__size); __nobjs = (int)(__bytes_left/__n);
__total_bytes = __size * __nobjs; __total_bytes = __n * __nobjs;
__result = _S_start_free; __result = _S_start_free;
_S_start_free += __total_bytes; _S_start_free += __total_bytes;
return __result; return __result;
...@@ -253,32 +195,32 @@ namespace __gnu_cxx ...@@ -253,32 +195,32 @@ namespace __gnu_cxx
// Try to make use of the left-over piece. // Try to make use of the left-over piece.
if (__bytes_left > 0) if (__bytes_left > 0)
{ {
_Obj* volatile* __my_free_list = _Obj* volatile* __free_list =
_S_free_list + _S_freelist_index(__bytes_left); _S_free_list + _S_freelist_index(__bytes_left);
((_Obj*)(void*)_S_start_free) -> _M_free_list_link = *__my_free_list; ((_Obj*)(void*)_S_start_free)->_M_free_list_link = *__free_list;
*__my_free_list = (_Obj*)(void*)_S_start_free; *__free_list = (_Obj*)(void*)_S_start_free;
} }
_S_start_free = (char*) __new_alloc::allocate(__bytes_to_get); _S_start_free = (char*) __new_alloc::allocate(__bytes_to_get);
if (_S_start_free == 0) if (_S_start_free == 0)
{ {
size_t __i; size_t __i;
_Obj* volatile* __my_free_list; _Obj* volatile* __free_list;
_Obj* __p; _Obj* __p;
// Try to make do with what we have. That can't hurt. We // Try to make do with what we have. That can't hurt. We
// do not try smaller requests, since that tends to result // do not try smaller requests, since that tends to result
// in disaster on multi-process machines. // in disaster on multi-process machines.
__i = __size; __i = __n;
for (; __i <= (size_t) _S_max_bytes; __i += (size_t) _S_align) for (; __i <= (size_t) _S_max_bytes; __i += (size_t) _S_align)
{ {
__my_free_list = _S_free_list + _S_freelist_index(__i); __free_list = _S_free_list + _S_freelist_index(__i);
__p = *__my_free_list; __p = *__free_list;
if (__p != 0) if (__p != 0)
{ {
*__my_free_list = __p -> _M_free_list_link; *__free_list = __p -> _M_free_list_link;
_S_start_free = (char*)__p; _S_start_free = (char*)__p;
_S_end_free = _S_start_free + __i; _S_end_free = _S_start_free + __i;
return _S_chunk_alloc(__size, __nobjs); return _S_chunk_alloc(__n, __nobjs);
// Any leftover piece will eventually make it to the // Any leftover piece will eventually make it to the
// right free list. // right free list.
} }
...@@ -290,11 +232,10 @@ namespace __gnu_cxx ...@@ -290,11 +232,10 @@ namespace __gnu_cxx
} }
_S_heap_size += __bytes_to_get; _S_heap_size += __bytes_to_get;
_S_end_free = _S_start_free + __bytes_to_get; _S_end_free = _S_start_free + __bytes_to_get;
return _S_chunk_alloc(__size, __nobjs); return _S_chunk_alloc(__n, __nobjs);
} }
} }
// Returns an object of size __n, and optionally adds to "size // Returns an object of size __n, and optionally adds to "size
// __n"'s free list. We assume that __n is properly aligned. We // __n"'s free list. We assume that __n is properly aligned. We
// hold the allocation lock. // hold the allocation lock.
...@@ -304,7 +245,7 @@ namespace __gnu_cxx ...@@ -304,7 +245,7 @@ namespace __gnu_cxx
{ {
int __nobjs = 20; int __nobjs = 20;
char* __chunk = _S_chunk_alloc(__n, __nobjs); char* __chunk = _S_chunk_alloc(__n, __nobjs);
_Obj* volatile* __my_free_list; _Obj* volatile* __free_list;
_Obj* __result; _Obj* __result;
_Obj* __current_obj; _Obj* __current_obj;
_Obj* __next_obj; _Obj* __next_obj;
...@@ -312,11 +253,11 @@ namespace __gnu_cxx ...@@ -312,11 +253,11 @@ namespace __gnu_cxx
if (1 == __nobjs) if (1 == __nobjs)
return __chunk; return __chunk;
__my_free_list = _S_free_list + _S_freelist_index(__n); __free_list = _S_free_list + _S_freelist_index(__n);
// Build free list in chunk. // Build free list in chunk.
__result = (_Obj*)(void*)__chunk; __result = (_Obj*)(void*)__chunk;
*__my_free_list = __next_obj = (_Obj*)(void*)(__chunk + __n); *__free_list = __next_obj = (_Obj*)(void*)(__chunk + __n);
for (__i = 1; ; __i++) for (__i = 1; ; __i++)
{ {
__current_obj = __next_obj; __current_obj = __next_obj;
...@@ -332,10 +273,69 @@ namespace __gnu_cxx ...@@ -332,10 +273,69 @@ namespace __gnu_cxx
return __result; return __result;
} }
template<bool __threads, int __inst>
void*
__pool_alloc<__threads, __inst>::allocate(size_t __n)
{
void* __ret = 0;
// If there is a race through here, assume answer from getenv
// will resolve in same direction. Inspired by techniques
// to efficiently support threading found in basic_string.h.
if (_S_force_new == 0)
{
if (getenv("GLIBCPP_FORCE_NEW"))
__atomic_add(&_S_force_new, 1);
else
__atomic_add(&_S_force_new, -1);
}
if ((__n > (size_t) _S_max_bytes) || (_S_force_new > 0))
__ret = __new_alloc::allocate(__n);
else
{
_Obj* volatile* __free_list = _S_free_list + _S_freelist_index(__n);
// Acquire the lock here with a constructor call. This
// ensures that it is released in exit or during stack
// unwinding.
_Lock __lock_instance;
_Obj* __restrict__ __result = *__free_list;
if (__builtin_expect(__result == 0, 0))
__ret = _S_refill(_S_round_up(__n));
else
{
*__free_list = __result -> _M_free_list_link;
__ret = __result;
}
if (__builtin_expect(__ret == 0, 0))
__throw_bad_alloc();
}
return __ret;
}
template<bool __threads, int __inst>
void
__pool_alloc<__threads, __inst>::deallocate(void* __p, size_t __n)
{
if ((__n > (size_t) _S_max_bytes) || (_S_force_new > 0))
__new_alloc::deallocate(__p, __n);
else
{
_Obj* volatile* __free_list = _S_free_list + _S_freelist_index(__n);
_Obj* __q = (_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;
__q -> _M_free_list_link = *__free_list;
*__free_list = __q;
}
}
template<bool __threads, int __inst> template<bool __threads, int __inst>
_STL_mutex_lock typename __pool_alloc<__threads, __inst>::_Obj* volatile
__pool_alloc<__threads, __inst>::_S_lock __STL_MUTEX_INITIALIZER; __pool_alloc<__threads, __inst>::_S_free_list[_S_freelists];
template<bool __threads, int __inst> template<bool __threads, int __inst>
char* __pool_alloc<__threads, __inst>::_S_start_free = 0; char* __pool_alloc<__threads, __inst>::_S_start_free = 0;
...@@ -347,8 +347,18 @@ namespace __gnu_cxx ...@@ -347,8 +347,18 @@ namespace __gnu_cxx
size_t __pool_alloc<__threads, __inst>::_S_heap_size = 0; size_t __pool_alloc<__threads, __inst>::_S_heap_size = 0;
template<bool __threads, int __inst> template<bool __threads, int __inst>
typename __pool_alloc<__threads, __inst>::_Obj* volatile _STL_mutex_lock
__pool_alloc<__threads, __inst>::_S_free_list[_S_freelists]; __pool_alloc<__threads, __inst>::_S_lock __STL_MUTEX_INITIALIZER;
template<bool __threads, int __inst> _Atomic_word
__pool_alloc<__threads, __inst>::_S_force_new = 0;
// Inhibit implicit instantiations for required instantiations,
// which are defined via explicit instantiations elsewhere.
// NB: This syntax is a GNU extension.
#if _GLIBCPP_EXTERN_TEMPLATE
extern template class __pool_alloc<true, 0>;
#endif
} // namespace __gnu_cxx } // namespace __gnu_cxx
namespace std namespace std
......
...@@ -39,3 +39,8 @@ namespace std ...@@ -39,3 +39,8 @@ namespace std
template class allocator<char>; template class allocator<char>;
template class allocator<wchar_t>; template class allocator<wchar_t>;
} // namespace std } // namespace std
namespace __gnu_cxx
{
template class __pool_alloc<true, 0>;
} // namespace __gnu_cxx
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