1*e4b17023SJohn Marino // Allocator details. 2*e4b17023SJohn Marino 3*e4b17023SJohn Marino // Copyright (C) 2004, 2005, 2006, 2009, 2010 Free Software Foundation, Inc. 4*e4b17023SJohn Marino // 5*e4b17023SJohn Marino // This file is part of the GNU ISO C++ Library. This library is free 6*e4b17023SJohn Marino // software; you can redistribute it and/or modify it under the 7*e4b17023SJohn Marino // terms of the GNU General Public License as published by the 8*e4b17023SJohn Marino // Free Software Foundation; either version 3, or (at your option) 9*e4b17023SJohn Marino // any later version. 10*e4b17023SJohn Marino 11*e4b17023SJohn Marino // This library is distributed in the hope that it will be useful, 12*e4b17023SJohn Marino // but WITHOUT ANY WARRANTY; without even the implied warranty of 13*e4b17023SJohn Marino // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*e4b17023SJohn Marino // GNU General Public License for more details. 15*e4b17023SJohn Marino 16*e4b17023SJohn Marino // Under Section 7 of GPL version 3, you are granted additional 17*e4b17023SJohn Marino // permissions described in the GCC Runtime Library Exception, version 18*e4b17023SJohn Marino // 3.1, as published by the Free Software Foundation. 19*e4b17023SJohn Marino 20*e4b17023SJohn Marino // You should have received a copy of the GNU General Public License and 21*e4b17023SJohn Marino // a copy of the GCC Runtime Library Exception along with this program; 22*e4b17023SJohn Marino // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23*e4b17023SJohn Marino // <http://www.gnu.org/licenses/>. 24*e4b17023SJohn Marino 25*e4b17023SJohn Marino // 26*e4b17023SJohn Marino // ISO C++ 14882: 27*e4b17023SJohn Marino // 28*e4b17023SJohn Marino 29*e4b17023SJohn Marino #include <bits/c++config.h> 30*e4b17023SJohn Marino #include <ext/concurrence.h> 31*e4b17023SJohn Marino #include <ext/mt_allocator.h> 32*e4b17023SJohn Marino #include <cstring> 33*e4b17023SJohn Marino 34*e4b17023SJohn Marino namespace 35*e4b17023SJohn Marino { 36*e4b17023SJohn Marino #ifdef __GTHREADS 37*e4b17023SJohn Marino struct __freelist 38*e4b17023SJohn Marino { 39*e4b17023SJohn Marino typedef __gnu_cxx::__pool<true>::_Thread_record _Thread_record; 40*e4b17023SJohn Marino _Thread_record* _M_thread_freelist; 41*e4b17023SJohn Marino _Thread_record* _M_thread_freelist_array; 42*e4b17023SJohn Marino size_t _M_max_threads; 43*e4b17023SJohn Marino __gthread_key_t _M_key; 44*e4b17023SJohn Marino ~__freelist__anon3203a9670111::__freelist45*e4b17023SJohn Marino ~__freelist() 46*e4b17023SJohn Marino { 47*e4b17023SJohn Marino if (_M_thread_freelist_array) 48*e4b17023SJohn Marino { 49*e4b17023SJohn Marino __gthread_key_delete(_M_key); 50*e4b17023SJohn Marino ::operator delete(static_cast<void*>(_M_thread_freelist_array)); 51*e4b17023SJohn Marino } 52*e4b17023SJohn Marino } 53*e4b17023SJohn Marino }; 54*e4b17023SJohn Marino 55*e4b17023SJohn Marino __freelist& get_freelist()56*e4b17023SJohn Marino get_freelist() 57*e4b17023SJohn Marino { 58*e4b17023SJohn Marino static __freelist freelist; 59*e4b17023SJohn Marino return freelist; 60*e4b17023SJohn Marino } 61*e4b17023SJohn Marino 62*e4b17023SJohn Marino __gnu_cxx::__mutex& get_freelist_mutex()63*e4b17023SJohn Marino get_freelist_mutex() 64*e4b17023SJohn Marino { 65*e4b17023SJohn Marino static __gnu_cxx::__mutex freelist_mutex; 66*e4b17023SJohn Marino return freelist_mutex; 67*e4b17023SJohn Marino } 68*e4b17023SJohn Marino 69*e4b17023SJohn Marino static void _M_destroy_thread_key(void * __id)70*e4b17023SJohn Marino _M_destroy_thread_key(void* __id) 71*e4b17023SJohn Marino { 72*e4b17023SJohn Marino // Return this thread id record to the front of thread_freelist. 73*e4b17023SJohn Marino __freelist& freelist = get_freelist(); 74*e4b17023SJohn Marino { 75*e4b17023SJohn Marino __gnu_cxx::__scoped_lock sentry(get_freelist_mutex()); 76*e4b17023SJohn Marino size_t _M_id = reinterpret_cast<size_t>(__id); 77*e4b17023SJohn Marino 78*e4b17023SJohn Marino typedef __gnu_cxx::__pool<true>::_Thread_record _Thread_record; 79*e4b17023SJohn Marino _Thread_record* __tr = &freelist._M_thread_freelist_array[_M_id - 1]; 80*e4b17023SJohn Marino __tr->_M_next = freelist._M_thread_freelist; 81*e4b17023SJohn Marino freelist._M_thread_freelist = __tr; 82*e4b17023SJohn Marino } 83*e4b17023SJohn Marino } 84*e4b17023SJohn Marino #endif 85*e4b17023SJohn Marino } // anonymous namespace 86*e4b17023SJohn Marino 87*e4b17023SJohn Marino namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) 88*e4b17023SJohn Marino { 89*e4b17023SJohn Marino _GLIBCXX_BEGIN_NAMESPACE_VERSION 90*e4b17023SJohn Marino 91*e4b17023SJohn Marino void _M_destroy()92*e4b17023SJohn Marino __pool<false>::_M_destroy() throw() 93*e4b17023SJohn Marino { 94*e4b17023SJohn Marino if (_M_init && !_M_options._M_force_new) 95*e4b17023SJohn Marino { 96*e4b17023SJohn Marino for (size_t __n = 0; __n < _M_bin_size; ++__n) 97*e4b17023SJohn Marino { 98*e4b17023SJohn Marino _Bin_record& __bin = _M_bin[__n]; 99*e4b17023SJohn Marino while (__bin._M_address) 100*e4b17023SJohn Marino { 101*e4b17023SJohn Marino _Block_address* __tmp = __bin._M_address->_M_next; 102*e4b17023SJohn Marino ::operator delete(__bin._M_address->_M_initial); 103*e4b17023SJohn Marino __bin._M_address = __tmp; 104*e4b17023SJohn Marino } 105*e4b17023SJohn Marino ::operator delete(__bin._M_first); 106*e4b17023SJohn Marino } 107*e4b17023SJohn Marino ::operator delete(_M_bin); 108*e4b17023SJohn Marino ::operator delete(_M_binmap); 109*e4b17023SJohn Marino } 110*e4b17023SJohn Marino } 111*e4b17023SJohn Marino 112*e4b17023SJohn Marino void _M_reclaim_block(char * __p,size_t __bytes)113*e4b17023SJohn Marino __pool<false>::_M_reclaim_block(char* __p, size_t __bytes) throw () 114*e4b17023SJohn Marino { 115*e4b17023SJohn Marino // Round up to power of 2 and figure out which bin to use. 116*e4b17023SJohn Marino const size_t __which = _M_binmap[__bytes]; 117*e4b17023SJohn Marino _Bin_record& __bin = _M_bin[__which]; 118*e4b17023SJohn Marino 119*e4b17023SJohn Marino char* __c = __p - _M_get_align(); 120*e4b17023SJohn Marino _Block_record* __block = reinterpret_cast<_Block_record*>(__c); 121*e4b17023SJohn Marino 122*e4b17023SJohn Marino // Single threaded application - return to global pool. 123*e4b17023SJohn Marino __block->_M_next = __bin._M_first[0]; 124*e4b17023SJohn Marino __bin._M_first[0] = __block; 125*e4b17023SJohn Marino } 126*e4b17023SJohn Marino 127*e4b17023SJohn Marino char* _M_reserve_block(size_t __bytes,const size_t __thread_id)128*e4b17023SJohn Marino __pool<false>::_M_reserve_block(size_t __bytes, const size_t __thread_id) 129*e4b17023SJohn Marino { 130*e4b17023SJohn Marino // Round up to power of 2 and figure out which bin to use. 131*e4b17023SJohn Marino const size_t __which = _M_binmap[__bytes]; 132*e4b17023SJohn Marino _Bin_record& __bin = _M_bin[__which]; 133*e4b17023SJohn Marino const _Tune& __options = _M_get_options(); 134*e4b17023SJohn Marino const size_t __bin_size = (__options._M_min_bin << __which) 135*e4b17023SJohn Marino + __options._M_align; 136*e4b17023SJohn Marino size_t __block_count = __options._M_chunk_size - sizeof(_Block_address); 137*e4b17023SJohn Marino __block_count /= __bin_size; 138*e4b17023SJohn Marino 139*e4b17023SJohn Marino // Get a new block dynamically, set it up for use. 140*e4b17023SJohn Marino void* __v = ::operator new(__options._M_chunk_size); 141*e4b17023SJohn Marino _Block_address* __address = static_cast<_Block_address*>(__v); 142*e4b17023SJohn Marino __address->_M_initial = __v; 143*e4b17023SJohn Marino __address->_M_next = __bin._M_address; 144*e4b17023SJohn Marino __bin._M_address = __address; 145*e4b17023SJohn Marino 146*e4b17023SJohn Marino char* __c = static_cast<char*>(__v) + sizeof(_Block_address); 147*e4b17023SJohn Marino _Block_record* __block = reinterpret_cast<_Block_record*>(__c); 148*e4b17023SJohn Marino __bin._M_first[__thread_id] = __block; 149*e4b17023SJohn Marino while (--__block_count > 0) 150*e4b17023SJohn Marino { 151*e4b17023SJohn Marino __c += __bin_size; 152*e4b17023SJohn Marino __block->_M_next = reinterpret_cast<_Block_record*>(__c); 153*e4b17023SJohn Marino __block = __block->_M_next; 154*e4b17023SJohn Marino } 155*e4b17023SJohn Marino __block->_M_next = 0; 156*e4b17023SJohn Marino 157*e4b17023SJohn Marino __block = __bin._M_first[__thread_id]; 158*e4b17023SJohn Marino __bin._M_first[__thread_id] = __block->_M_next; 159*e4b17023SJohn Marino 160*e4b17023SJohn Marino // NB: For alignment reasons, we can't use the first _M_align 161*e4b17023SJohn Marino // bytes, even when sizeof(_Block_record) < _M_align. 162*e4b17023SJohn Marino return reinterpret_cast<char*>(__block) + __options._M_align; 163*e4b17023SJohn Marino } 164*e4b17023SJohn Marino 165*e4b17023SJohn Marino void _M_initialize()166*e4b17023SJohn Marino __pool<false>::_M_initialize() 167*e4b17023SJohn Marino { 168*e4b17023SJohn Marino // _M_force_new must not change after the first allocate(), which 169*e4b17023SJohn Marino // in turn calls this method, so if it's false, it's false forever 170*e4b17023SJohn Marino // and we don't need to return here ever again. 171*e4b17023SJohn Marino if (_M_options._M_force_new) 172*e4b17023SJohn Marino { 173*e4b17023SJohn Marino _M_init = true; 174*e4b17023SJohn Marino return; 175*e4b17023SJohn Marino } 176*e4b17023SJohn Marino 177*e4b17023SJohn Marino // Create the bins. 178*e4b17023SJohn Marino // Calculate the number of bins required based on _M_max_bytes. 179*e4b17023SJohn Marino // _M_bin_size is statically-initialized to one. 180*e4b17023SJohn Marino size_t __bin_size = _M_options._M_min_bin; 181*e4b17023SJohn Marino while (_M_options._M_max_bytes > __bin_size) 182*e4b17023SJohn Marino { 183*e4b17023SJohn Marino __bin_size <<= 1; 184*e4b17023SJohn Marino ++_M_bin_size; 185*e4b17023SJohn Marino } 186*e4b17023SJohn Marino 187*e4b17023SJohn Marino // Setup the bin map for quick lookup of the relevant bin. 188*e4b17023SJohn Marino const size_t __j = (_M_options._M_max_bytes + 1) * sizeof(_Binmap_type); 189*e4b17023SJohn Marino _M_binmap = static_cast<_Binmap_type*>(::operator new(__j)); 190*e4b17023SJohn Marino _Binmap_type* __bp = _M_binmap; 191*e4b17023SJohn Marino _Binmap_type __bin_max = _M_options._M_min_bin; 192*e4b17023SJohn Marino _Binmap_type __bint = 0; 193*e4b17023SJohn Marino for (_Binmap_type __ct = 0; __ct <= _M_options._M_max_bytes; ++__ct) 194*e4b17023SJohn Marino { 195*e4b17023SJohn Marino if (__ct > __bin_max) 196*e4b17023SJohn Marino { 197*e4b17023SJohn Marino __bin_max <<= 1; 198*e4b17023SJohn Marino ++__bint; 199*e4b17023SJohn Marino } 200*e4b17023SJohn Marino *__bp++ = __bint; 201*e4b17023SJohn Marino } 202*e4b17023SJohn Marino 203*e4b17023SJohn Marino // Initialize _M_bin and its members. 204*e4b17023SJohn Marino void* __v = ::operator new(sizeof(_Bin_record) * _M_bin_size); 205*e4b17023SJohn Marino _M_bin = static_cast<_Bin_record*>(__v); 206*e4b17023SJohn Marino for (size_t __n = 0; __n < _M_bin_size; ++__n) 207*e4b17023SJohn Marino { 208*e4b17023SJohn Marino _Bin_record& __bin = _M_bin[__n]; 209*e4b17023SJohn Marino __v = ::operator new(sizeof(_Block_record*)); 210*e4b17023SJohn Marino __bin._M_first = static_cast<_Block_record**>(__v); 211*e4b17023SJohn Marino __bin._M_first[0] = 0; 212*e4b17023SJohn Marino __bin._M_address = 0; 213*e4b17023SJohn Marino } 214*e4b17023SJohn Marino _M_init = true; 215*e4b17023SJohn Marino } 216*e4b17023SJohn Marino 217*e4b17023SJohn Marino 218*e4b17023SJohn Marino #ifdef __GTHREADS 219*e4b17023SJohn Marino void _M_destroy()220*e4b17023SJohn Marino __pool<true>::_M_destroy() throw() 221*e4b17023SJohn Marino { 222*e4b17023SJohn Marino if (_M_init && !_M_options._M_force_new) 223*e4b17023SJohn Marino { 224*e4b17023SJohn Marino if (__gthread_active_p()) 225*e4b17023SJohn Marino { 226*e4b17023SJohn Marino for (size_t __n = 0; __n < _M_bin_size; ++__n) 227*e4b17023SJohn Marino { 228*e4b17023SJohn Marino _Bin_record& __bin = _M_bin[__n]; 229*e4b17023SJohn Marino while (__bin._M_address) 230*e4b17023SJohn Marino { 231*e4b17023SJohn Marino _Block_address* __tmp = __bin._M_address->_M_next; 232*e4b17023SJohn Marino ::operator delete(__bin._M_address->_M_initial); 233*e4b17023SJohn Marino __bin._M_address = __tmp; 234*e4b17023SJohn Marino } 235*e4b17023SJohn Marino ::operator delete(__bin._M_first); 236*e4b17023SJohn Marino ::operator delete(__bin._M_free); 237*e4b17023SJohn Marino ::operator delete(__bin._M_used); 238*e4b17023SJohn Marino ::operator delete(__bin._M_mutex); 239*e4b17023SJohn Marino } 240*e4b17023SJohn Marino } 241*e4b17023SJohn Marino else 242*e4b17023SJohn Marino { 243*e4b17023SJohn Marino for (size_t __n = 0; __n < _M_bin_size; ++__n) 244*e4b17023SJohn Marino { 245*e4b17023SJohn Marino _Bin_record& __bin = _M_bin[__n]; 246*e4b17023SJohn Marino while (__bin._M_address) 247*e4b17023SJohn Marino { 248*e4b17023SJohn Marino _Block_address* __tmp = __bin._M_address->_M_next; 249*e4b17023SJohn Marino ::operator delete(__bin._M_address->_M_initial); 250*e4b17023SJohn Marino __bin._M_address = __tmp; 251*e4b17023SJohn Marino } 252*e4b17023SJohn Marino ::operator delete(__bin._M_first); 253*e4b17023SJohn Marino } 254*e4b17023SJohn Marino } 255*e4b17023SJohn Marino ::operator delete(_M_bin); 256*e4b17023SJohn Marino ::operator delete(_M_binmap); 257*e4b17023SJohn Marino } 258*e4b17023SJohn Marino } 259*e4b17023SJohn Marino 260*e4b17023SJohn Marino void _M_reclaim_block(char * __p,size_t __bytes)261*e4b17023SJohn Marino __pool<true>::_M_reclaim_block(char* __p, size_t __bytes) throw () 262*e4b17023SJohn Marino { 263*e4b17023SJohn Marino // Round up to power of 2 and figure out which bin to use. 264*e4b17023SJohn Marino const size_t __which = _M_binmap[__bytes]; 265*e4b17023SJohn Marino const _Bin_record& __bin = _M_bin[__which]; 266*e4b17023SJohn Marino 267*e4b17023SJohn Marino // Know __p not null, assume valid block. 268*e4b17023SJohn Marino char* __c = __p - _M_get_align(); 269*e4b17023SJohn Marino _Block_record* __block = reinterpret_cast<_Block_record*>(__c); 270*e4b17023SJohn Marino if (__gthread_active_p()) 271*e4b17023SJohn Marino { 272*e4b17023SJohn Marino // Calculate the number of records to remove from our freelist: 273*e4b17023SJohn Marino // in order to avoid too much contention we wait until the 274*e4b17023SJohn Marino // number of records is "high enough". 275*e4b17023SJohn Marino const size_t __thread_id = _M_get_thread_id(); 276*e4b17023SJohn Marino const _Tune& __options = _M_get_options(); 277*e4b17023SJohn Marino const size_t __limit = (100 * (_M_bin_size - __which) 278*e4b17023SJohn Marino * __options._M_freelist_headroom); 279*e4b17023SJohn Marino 280*e4b17023SJohn Marino size_t __remove = __bin._M_free[__thread_id]; 281*e4b17023SJohn Marino __remove *= __options._M_freelist_headroom; 282*e4b17023SJohn Marino 283*e4b17023SJohn Marino // NB: We assume that reads of _Atomic_words are atomic. 284*e4b17023SJohn Marino const size_t __max_threads = __options._M_max_threads + 1; 285*e4b17023SJohn Marino _Atomic_word* const __reclaimed_base = 286*e4b17023SJohn Marino reinterpret_cast<_Atomic_word*>(__bin._M_used + __max_threads); 287*e4b17023SJohn Marino const _Atomic_word __reclaimed = __reclaimed_base[__thread_id]; 288*e4b17023SJohn Marino const size_t __net_used = __bin._M_used[__thread_id] - __reclaimed; 289*e4b17023SJohn Marino 290*e4b17023SJohn Marino // NB: For performance sake we don't resync every time, in order 291*e4b17023SJohn Marino // to spare atomic ops. Note that if __reclaimed increased by, 292*e4b17023SJohn Marino // say, 1024, since the last sync, it means that the other 293*e4b17023SJohn Marino // threads executed the atomic in the else below at least the 294*e4b17023SJohn Marino // same number of times (at least, because _M_reserve_block may 295*e4b17023SJohn Marino // have decreased the counter), therefore one more cannot hurt. 296*e4b17023SJohn Marino if (__reclaimed > 1024) 297*e4b17023SJohn Marino { 298*e4b17023SJohn Marino __bin._M_used[__thread_id] -= __reclaimed; 299*e4b17023SJohn Marino __atomic_add(&__reclaimed_base[__thread_id], -__reclaimed); 300*e4b17023SJohn Marino } 301*e4b17023SJohn Marino 302*e4b17023SJohn Marino if (__remove >= __net_used) 303*e4b17023SJohn Marino __remove -= __net_used; 304*e4b17023SJohn Marino else 305*e4b17023SJohn Marino __remove = 0; 306*e4b17023SJohn Marino if (__remove > __limit && __remove > __bin._M_free[__thread_id]) 307*e4b17023SJohn Marino { 308*e4b17023SJohn Marino _Block_record* __first = __bin._M_first[__thread_id]; 309*e4b17023SJohn Marino _Block_record* __tmp = __first; 310*e4b17023SJohn Marino __remove /= __options._M_freelist_headroom; 311*e4b17023SJohn Marino const size_t __removed = __remove; 312*e4b17023SJohn Marino while (--__remove > 0) 313*e4b17023SJohn Marino __tmp = __tmp->_M_next; 314*e4b17023SJohn Marino __bin._M_first[__thread_id] = __tmp->_M_next; 315*e4b17023SJohn Marino __bin._M_free[__thread_id] -= __removed; 316*e4b17023SJohn Marino 317*e4b17023SJohn Marino __gthread_mutex_lock(__bin._M_mutex); 318*e4b17023SJohn Marino __tmp->_M_next = __bin._M_first[0]; 319*e4b17023SJohn Marino __bin._M_first[0] = __first; 320*e4b17023SJohn Marino __bin._M_free[0] += __removed; 321*e4b17023SJohn Marino __gthread_mutex_unlock(__bin._M_mutex); 322*e4b17023SJohn Marino } 323*e4b17023SJohn Marino 324*e4b17023SJohn Marino // Return this block to our list and update counters and 325*e4b17023SJohn Marino // owner id as needed. 326*e4b17023SJohn Marino if (__block->_M_thread_id == __thread_id) 327*e4b17023SJohn Marino --__bin._M_used[__thread_id]; 328*e4b17023SJohn Marino else 329*e4b17023SJohn Marino __atomic_add(&__reclaimed_base[__block->_M_thread_id], 1); 330*e4b17023SJohn Marino 331*e4b17023SJohn Marino __block->_M_next = __bin._M_first[__thread_id]; 332*e4b17023SJohn Marino __bin._M_first[__thread_id] = __block; 333*e4b17023SJohn Marino 334*e4b17023SJohn Marino ++__bin._M_free[__thread_id]; 335*e4b17023SJohn Marino } 336*e4b17023SJohn Marino else 337*e4b17023SJohn Marino { 338*e4b17023SJohn Marino // Not using threads, so single threaded application - return 339*e4b17023SJohn Marino // to global pool. 340*e4b17023SJohn Marino __block->_M_next = __bin._M_first[0]; 341*e4b17023SJohn Marino __bin._M_first[0] = __block; 342*e4b17023SJohn Marino } 343*e4b17023SJohn Marino } 344*e4b17023SJohn Marino 345*e4b17023SJohn Marino char* _M_reserve_block(size_t __bytes,const size_t __thread_id)346*e4b17023SJohn Marino __pool<true>::_M_reserve_block(size_t __bytes, const size_t __thread_id) 347*e4b17023SJohn Marino { 348*e4b17023SJohn Marino // Round up to power of 2 and figure out which bin to use. 349*e4b17023SJohn Marino const size_t __which = _M_binmap[__bytes]; 350*e4b17023SJohn Marino const _Tune& __options = _M_get_options(); 351*e4b17023SJohn Marino const size_t __bin_size = ((__options._M_min_bin << __which) 352*e4b17023SJohn Marino + __options._M_align); 353*e4b17023SJohn Marino size_t __block_count = __options._M_chunk_size - sizeof(_Block_address); 354*e4b17023SJohn Marino __block_count /= __bin_size; 355*e4b17023SJohn Marino 356*e4b17023SJohn Marino // Are we using threads? 357*e4b17023SJohn Marino // - Yes, check if there are free blocks on the global 358*e4b17023SJohn Marino // list. If so, grab up to __block_count blocks in one 359*e4b17023SJohn Marino // lock and change ownership. If the global list is 360*e4b17023SJohn Marino // empty, we allocate a new chunk and add those blocks 361*e4b17023SJohn Marino // directly to our own freelist (with us as owner). 362*e4b17023SJohn Marino // - No, all operations are made directly to global pool 0 363*e4b17023SJohn Marino // no need to lock or change ownership but check for free 364*e4b17023SJohn Marino // blocks on global list (and if not add new ones) and 365*e4b17023SJohn Marino // get the first one. 366*e4b17023SJohn Marino _Bin_record& __bin = _M_bin[__which]; 367*e4b17023SJohn Marino _Block_record* __block = 0; 368*e4b17023SJohn Marino if (__gthread_active_p()) 369*e4b17023SJohn Marino { 370*e4b17023SJohn Marino // Resync the _M_used counters. 371*e4b17023SJohn Marino const size_t __max_threads = __options._M_max_threads + 1; 372*e4b17023SJohn Marino _Atomic_word* const __reclaimed_base = 373*e4b17023SJohn Marino reinterpret_cast<_Atomic_word*>(__bin._M_used + __max_threads); 374*e4b17023SJohn Marino const _Atomic_word __reclaimed = __reclaimed_base[__thread_id]; 375*e4b17023SJohn Marino __bin._M_used[__thread_id] -= __reclaimed; 376*e4b17023SJohn Marino __atomic_add(&__reclaimed_base[__thread_id], -__reclaimed); 377*e4b17023SJohn Marino 378*e4b17023SJohn Marino __gthread_mutex_lock(__bin._M_mutex); 379*e4b17023SJohn Marino if (__bin._M_first[0] == 0) 380*e4b17023SJohn Marino { 381*e4b17023SJohn Marino void* __v = ::operator new(__options._M_chunk_size); 382*e4b17023SJohn Marino _Block_address* __address = static_cast<_Block_address*>(__v); 383*e4b17023SJohn Marino __address->_M_initial = __v; 384*e4b17023SJohn Marino __address->_M_next = __bin._M_address; 385*e4b17023SJohn Marino __bin._M_address = __address; 386*e4b17023SJohn Marino __gthread_mutex_unlock(__bin._M_mutex); 387*e4b17023SJohn Marino 388*e4b17023SJohn Marino // No need to hold the lock when we are adding a whole 389*e4b17023SJohn Marino // chunk to our own list. 390*e4b17023SJohn Marino char* __c = static_cast<char*>(__v) + sizeof(_Block_address); 391*e4b17023SJohn Marino __block = reinterpret_cast<_Block_record*>(__c); 392*e4b17023SJohn Marino __bin._M_free[__thread_id] = __block_count; 393*e4b17023SJohn Marino __bin._M_first[__thread_id] = __block; 394*e4b17023SJohn Marino while (--__block_count > 0) 395*e4b17023SJohn Marino { 396*e4b17023SJohn Marino __c += __bin_size; 397*e4b17023SJohn Marino __block->_M_next = reinterpret_cast<_Block_record*>(__c); 398*e4b17023SJohn Marino __block = __block->_M_next; 399*e4b17023SJohn Marino } 400*e4b17023SJohn Marino __block->_M_next = 0; 401*e4b17023SJohn Marino } 402*e4b17023SJohn Marino else 403*e4b17023SJohn Marino { 404*e4b17023SJohn Marino // Is the number of required blocks greater than or equal 405*e4b17023SJohn Marino // to the number that can be provided by the global free 406*e4b17023SJohn Marino // list? 407*e4b17023SJohn Marino __bin._M_first[__thread_id] = __bin._M_first[0]; 408*e4b17023SJohn Marino if (__block_count >= __bin._M_free[0]) 409*e4b17023SJohn Marino { 410*e4b17023SJohn Marino __bin._M_free[__thread_id] = __bin._M_free[0]; 411*e4b17023SJohn Marino __bin._M_free[0] = 0; 412*e4b17023SJohn Marino __bin._M_first[0] = 0; 413*e4b17023SJohn Marino } 414*e4b17023SJohn Marino else 415*e4b17023SJohn Marino { 416*e4b17023SJohn Marino __bin._M_free[__thread_id] = __block_count; 417*e4b17023SJohn Marino __bin._M_free[0] -= __block_count; 418*e4b17023SJohn Marino __block = __bin._M_first[0]; 419*e4b17023SJohn Marino while (--__block_count > 0) 420*e4b17023SJohn Marino __block = __block->_M_next; 421*e4b17023SJohn Marino __bin._M_first[0] = __block->_M_next; 422*e4b17023SJohn Marino __block->_M_next = 0; 423*e4b17023SJohn Marino } 424*e4b17023SJohn Marino __gthread_mutex_unlock(__bin._M_mutex); 425*e4b17023SJohn Marino } 426*e4b17023SJohn Marino } 427*e4b17023SJohn Marino else 428*e4b17023SJohn Marino { 429*e4b17023SJohn Marino void* __v = ::operator new(__options._M_chunk_size); 430*e4b17023SJohn Marino _Block_address* __address = static_cast<_Block_address*>(__v); 431*e4b17023SJohn Marino __address->_M_initial = __v; 432*e4b17023SJohn Marino __address->_M_next = __bin._M_address; 433*e4b17023SJohn Marino __bin._M_address = __address; 434*e4b17023SJohn Marino 435*e4b17023SJohn Marino char* __c = static_cast<char*>(__v) + sizeof(_Block_address); 436*e4b17023SJohn Marino __block = reinterpret_cast<_Block_record*>(__c); 437*e4b17023SJohn Marino __bin._M_first[0] = __block; 438*e4b17023SJohn Marino while (--__block_count > 0) 439*e4b17023SJohn Marino { 440*e4b17023SJohn Marino __c += __bin_size; 441*e4b17023SJohn Marino __block->_M_next = reinterpret_cast<_Block_record*>(__c); 442*e4b17023SJohn Marino __block = __block->_M_next; 443*e4b17023SJohn Marino } 444*e4b17023SJohn Marino __block->_M_next = 0; 445*e4b17023SJohn Marino } 446*e4b17023SJohn Marino 447*e4b17023SJohn Marino __block = __bin._M_first[__thread_id]; 448*e4b17023SJohn Marino __bin._M_first[__thread_id] = __block->_M_next; 449*e4b17023SJohn Marino 450*e4b17023SJohn Marino if (__gthread_active_p()) 451*e4b17023SJohn Marino { 452*e4b17023SJohn Marino __block->_M_thread_id = __thread_id; 453*e4b17023SJohn Marino --__bin._M_free[__thread_id]; 454*e4b17023SJohn Marino ++__bin._M_used[__thread_id]; 455*e4b17023SJohn Marino } 456*e4b17023SJohn Marino 457*e4b17023SJohn Marino // NB: For alignment reasons, we can't use the first _M_align 458*e4b17023SJohn Marino // bytes, even when sizeof(_Block_record) < _M_align. 459*e4b17023SJohn Marino return reinterpret_cast<char*>(__block) + __options._M_align; 460*e4b17023SJohn Marino } 461*e4b17023SJohn Marino 462*e4b17023SJohn Marino void _M_initialize()463*e4b17023SJohn Marino __pool<true>::_M_initialize() 464*e4b17023SJohn Marino { 465*e4b17023SJohn Marino // _M_force_new must not change after the first allocate(), 466*e4b17023SJohn Marino // which in turn calls this method, so if it's false, it's false 467*e4b17023SJohn Marino // forever and we don't need to return here ever again. 468*e4b17023SJohn Marino if (_M_options._M_force_new) 469*e4b17023SJohn Marino { 470*e4b17023SJohn Marino _M_init = true; 471*e4b17023SJohn Marino return; 472*e4b17023SJohn Marino } 473*e4b17023SJohn Marino 474*e4b17023SJohn Marino // Create the bins. 475*e4b17023SJohn Marino // Calculate the number of bins required based on _M_max_bytes. 476*e4b17023SJohn Marino // _M_bin_size is statically-initialized to one. 477*e4b17023SJohn Marino size_t __bin_size = _M_options._M_min_bin; 478*e4b17023SJohn Marino while (_M_options._M_max_bytes > __bin_size) 479*e4b17023SJohn Marino { 480*e4b17023SJohn Marino __bin_size <<= 1; 481*e4b17023SJohn Marino ++_M_bin_size; 482*e4b17023SJohn Marino } 483*e4b17023SJohn Marino 484*e4b17023SJohn Marino // Setup the bin map for quick lookup of the relevant bin. 485*e4b17023SJohn Marino const size_t __j = (_M_options._M_max_bytes + 1) * sizeof(_Binmap_type); 486*e4b17023SJohn Marino _M_binmap = static_cast<_Binmap_type*>(::operator new(__j)); 487*e4b17023SJohn Marino _Binmap_type* __bp = _M_binmap; 488*e4b17023SJohn Marino _Binmap_type __bin_max = _M_options._M_min_bin; 489*e4b17023SJohn Marino _Binmap_type __bint = 0; 490*e4b17023SJohn Marino for (_Binmap_type __ct = 0; __ct <= _M_options._M_max_bytes; ++__ct) 491*e4b17023SJohn Marino { 492*e4b17023SJohn Marino if (__ct > __bin_max) 493*e4b17023SJohn Marino { 494*e4b17023SJohn Marino __bin_max <<= 1; 495*e4b17023SJohn Marino ++__bint; 496*e4b17023SJohn Marino } 497*e4b17023SJohn Marino *__bp++ = __bint; 498*e4b17023SJohn Marino } 499*e4b17023SJohn Marino 500*e4b17023SJohn Marino // Initialize _M_bin and its members. 501*e4b17023SJohn Marino void* __v = ::operator new(sizeof(_Bin_record) * _M_bin_size); 502*e4b17023SJohn Marino _M_bin = static_cast<_Bin_record*>(__v); 503*e4b17023SJohn Marino 504*e4b17023SJohn Marino // If __gthread_active_p() create and initialize the list of 505*e4b17023SJohn Marino // free thread ids. Single threaded applications use thread id 0 506*e4b17023SJohn Marino // directly and have no need for this. 507*e4b17023SJohn Marino if (__gthread_active_p()) 508*e4b17023SJohn Marino { 509*e4b17023SJohn Marino __freelist& freelist = get_freelist(); 510*e4b17023SJohn Marino { 511*e4b17023SJohn Marino __gnu_cxx::__scoped_lock sentry(get_freelist_mutex()); 512*e4b17023SJohn Marino 513*e4b17023SJohn Marino if (!freelist._M_thread_freelist_array 514*e4b17023SJohn Marino || freelist._M_max_threads < _M_options._M_max_threads) 515*e4b17023SJohn Marino { 516*e4b17023SJohn Marino const size_t __k = sizeof(_Thread_record) 517*e4b17023SJohn Marino * _M_options._M_max_threads; 518*e4b17023SJohn Marino __v = ::operator new(__k); 519*e4b17023SJohn Marino _M_thread_freelist = static_cast<_Thread_record*>(__v); 520*e4b17023SJohn Marino 521*e4b17023SJohn Marino // NOTE! The first assignable thread id is 1 since the 522*e4b17023SJohn Marino // global pool uses id 0 523*e4b17023SJohn Marino size_t __i; 524*e4b17023SJohn Marino for (__i = 1; __i < _M_options._M_max_threads; ++__i) 525*e4b17023SJohn Marino { 526*e4b17023SJohn Marino _Thread_record& __tr = _M_thread_freelist[__i - 1]; 527*e4b17023SJohn Marino __tr._M_next = &_M_thread_freelist[__i]; 528*e4b17023SJohn Marino __tr._M_id = __i; 529*e4b17023SJohn Marino } 530*e4b17023SJohn Marino 531*e4b17023SJohn Marino // Set last record. 532*e4b17023SJohn Marino _M_thread_freelist[__i - 1]._M_next = 0; 533*e4b17023SJohn Marino _M_thread_freelist[__i - 1]._M_id = __i; 534*e4b17023SJohn Marino 535*e4b17023SJohn Marino if (!freelist._M_thread_freelist_array) 536*e4b17023SJohn Marino { 537*e4b17023SJohn Marino // Initialize per thread key to hold pointer to 538*e4b17023SJohn Marino // _M_thread_freelist. 539*e4b17023SJohn Marino __gthread_key_create(&freelist._M_key, 540*e4b17023SJohn Marino ::_M_destroy_thread_key); 541*e4b17023SJohn Marino freelist._M_thread_freelist = _M_thread_freelist; 542*e4b17023SJohn Marino } 543*e4b17023SJohn Marino else 544*e4b17023SJohn Marino { 545*e4b17023SJohn Marino _Thread_record* _M_old_freelist 546*e4b17023SJohn Marino = freelist._M_thread_freelist; 547*e4b17023SJohn Marino _Thread_record* _M_old_array 548*e4b17023SJohn Marino = freelist._M_thread_freelist_array; 549*e4b17023SJohn Marino freelist._M_thread_freelist 550*e4b17023SJohn Marino = &_M_thread_freelist[_M_old_freelist - _M_old_array]; 551*e4b17023SJohn Marino while (_M_old_freelist) 552*e4b17023SJohn Marino { 553*e4b17023SJohn Marino size_t next_id; 554*e4b17023SJohn Marino if (_M_old_freelist->_M_next) 555*e4b17023SJohn Marino next_id = _M_old_freelist->_M_next - _M_old_array; 556*e4b17023SJohn Marino else 557*e4b17023SJohn Marino next_id = freelist._M_max_threads; 558*e4b17023SJohn Marino _M_thread_freelist[_M_old_freelist->_M_id - 1]._M_next 559*e4b17023SJohn Marino = &_M_thread_freelist[next_id]; 560*e4b17023SJohn Marino _M_old_freelist = _M_old_freelist->_M_next; 561*e4b17023SJohn Marino } 562*e4b17023SJohn Marino ::operator delete(static_cast<void*>(_M_old_array)); 563*e4b17023SJohn Marino } 564*e4b17023SJohn Marino freelist._M_thread_freelist_array = _M_thread_freelist; 565*e4b17023SJohn Marino freelist._M_max_threads = _M_options._M_max_threads; 566*e4b17023SJohn Marino } 567*e4b17023SJohn Marino } 568*e4b17023SJohn Marino 569*e4b17023SJohn Marino const size_t __max_threads = _M_options._M_max_threads + 1; 570*e4b17023SJohn Marino for (size_t __n = 0; __n < _M_bin_size; ++__n) 571*e4b17023SJohn Marino { 572*e4b17023SJohn Marino _Bin_record& __bin = _M_bin[__n]; 573*e4b17023SJohn Marino __v = ::operator new(sizeof(_Block_record*) * __max_threads); 574*e4b17023SJohn Marino std::memset(__v, 0, sizeof(_Block_record*) * __max_threads); 575*e4b17023SJohn Marino __bin._M_first = static_cast<_Block_record**>(__v); 576*e4b17023SJohn Marino 577*e4b17023SJohn Marino __bin._M_address = 0; 578*e4b17023SJohn Marino 579*e4b17023SJohn Marino __v = ::operator new(sizeof(size_t) * __max_threads); 580*e4b17023SJohn Marino std::memset(__v, 0, sizeof(size_t) * __max_threads); 581*e4b17023SJohn Marino 582*e4b17023SJohn Marino __bin._M_free = static_cast<size_t*>(__v); 583*e4b17023SJohn Marino 584*e4b17023SJohn Marino __v = ::operator new(sizeof(size_t) * __max_threads 585*e4b17023SJohn Marino + sizeof(_Atomic_word) * __max_threads); 586*e4b17023SJohn Marino std::memset(__v, 0, (sizeof(size_t) * __max_threads 587*e4b17023SJohn Marino + sizeof(_Atomic_word) * __max_threads)); 588*e4b17023SJohn Marino __bin._M_used = static_cast<size_t*>(__v); 589*e4b17023SJohn Marino 590*e4b17023SJohn Marino __v = ::operator new(sizeof(__gthread_mutex_t)); 591*e4b17023SJohn Marino __bin._M_mutex = static_cast<__gthread_mutex_t*>(__v); 592*e4b17023SJohn Marino 593*e4b17023SJohn Marino #ifdef __GTHREAD_MUTEX_INIT 594*e4b17023SJohn Marino { 595*e4b17023SJohn Marino // Do not copy a POSIX/gthr mutex once in use. 596*e4b17023SJohn Marino __gthread_mutex_t __tmp = __GTHREAD_MUTEX_INIT; 597*e4b17023SJohn Marino *__bin._M_mutex = __tmp; 598*e4b17023SJohn Marino } 599*e4b17023SJohn Marino #else 600*e4b17023SJohn Marino { __GTHREAD_MUTEX_INIT_FUNCTION(__bin._M_mutex); } 601*e4b17023SJohn Marino #endif 602*e4b17023SJohn Marino } 603*e4b17023SJohn Marino } 604*e4b17023SJohn Marino else 605*e4b17023SJohn Marino { 606*e4b17023SJohn Marino for (size_t __n = 0; __n < _M_bin_size; ++__n) 607*e4b17023SJohn Marino { 608*e4b17023SJohn Marino _Bin_record& __bin = _M_bin[__n]; 609*e4b17023SJohn Marino __v = ::operator new(sizeof(_Block_record*)); 610*e4b17023SJohn Marino __bin._M_first = static_cast<_Block_record**>(__v); 611*e4b17023SJohn Marino __bin._M_first[0] = 0; 612*e4b17023SJohn Marino __bin._M_address = 0; 613*e4b17023SJohn Marino } 614*e4b17023SJohn Marino } 615*e4b17023SJohn Marino _M_init = true; 616*e4b17023SJohn Marino } 617*e4b17023SJohn Marino 618*e4b17023SJohn Marino size_t _M_get_thread_id()619*e4b17023SJohn Marino __pool<true>::_M_get_thread_id() 620*e4b17023SJohn Marino { 621*e4b17023SJohn Marino // If we have thread support and it's active we check the thread 622*e4b17023SJohn Marino // key value and return its id or if it's not set we take the 623*e4b17023SJohn Marino // first record from _M_thread_freelist and sets the key and 624*e4b17023SJohn Marino // returns its id. 625*e4b17023SJohn Marino if (__gthread_active_p()) 626*e4b17023SJohn Marino { 627*e4b17023SJohn Marino __freelist& freelist = get_freelist(); 628*e4b17023SJohn Marino void* v = __gthread_getspecific(freelist._M_key); 629*e4b17023SJohn Marino size_t _M_id = (size_t)v; 630*e4b17023SJohn Marino if (_M_id == 0) 631*e4b17023SJohn Marino { 632*e4b17023SJohn Marino { 633*e4b17023SJohn Marino __gnu_cxx::__scoped_lock sentry(get_freelist_mutex()); 634*e4b17023SJohn Marino if (freelist._M_thread_freelist) 635*e4b17023SJohn Marino { 636*e4b17023SJohn Marino _M_id = freelist._M_thread_freelist->_M_id; 637*e4b17023SJohn Marino freelist._M_thread_freelist 638*e4b17023SJohn Marino = freelist._M_thread_freelist->_M_next; 639*e4b17023SJohn Marino } 640*e4b17023SJohn Marino } 641*e4b17023SJohn Marino 642*e4b17023SJohn Marino __gthread_setspecific(freelist._M_key, (void*)_M_id); 643*e4b17023SJohn Marino } 644*e4b17023SJohn Marino return _M_id >= _M_options._M_max_threads ? 0 : _M_id; 645*e4b17023SJohn Marino } 646*e4b17023SJohn Marino 647*e4b17023SJohn Marino // Otherwise (no thread support or inactive) all requests are 648*e4b17023SJohn Marino // served from the global pool 0. 649*e4b17023SJohn Marino return 0; 650*e4b17023SJohn Marino } 651*e4b17023SJohn Marino 652*e4b17023SJohn Marino // XXX GLIBCXX_ABI Deprecated 653*e4b17023SJohn Marino void _M_destroy_thread_key(void *)654*e4b17023SJohn Marino __pool<true>::_M_destroy_thread_key(void*) throw () { } 655*e4b17023SJohn Marino 656*e4b17023SJohn Marino // XXX GLIBCXX_ABI Deprecated 657*e4b17023SJohn Marino void _M_initialize(__destroy_handler)658*e4b17023SJohn Marino __pool<true>::_M_initialize(__destroy_handler) 659*e4b17023SJohn Marino { 660*e4b17023SJohn Marino // _M_force_new must not change after the first allocate(), 661*e4b17023SJohn Marino // which in turn calls this method, so if it's false, it's false 662*e4b17023SJohn Marino // forever and we don't need to return here ever again. 663*e4b17023SJohn Marino if (_M_options._M_force_new) 664*e4b17023SJohn Marino { 665*e4b17023SJohn Marino _M_init = true; 666*e4b17023SJohn Marino return; 667*e4b17023SJohn Marino } 668*e4b17023SJohn Marino 669*e4b17023SJohn Marino // Create the bins. 670*e4b17023SJohn Marino // Calculate the number of bins required based on _M_max_bytes. 671*e4b17023SJohn Marino // _M_bin_size is statically-initialized to one. 672*e4b17023SJohn Marino size_t __bin_size = _M_options._M_min_bin; 673*e4b17023SJohn Marino while (_M_options._M_max_bytes > __bin_size) 674*e4b17023SJohn Marino { 675*e4b17023SJohn Marino __bin_size <<= 1; 676*e4b17023SJohn Marino ++_M_bin_size; 677*e4b17023SJohn Marino } 678*e4b17023SJohn Marino 679*e4b17023SJohn Marino // Setup the bin map for quick lookup of the relevant bin. 680*e4b17023SJohn Marino const size_t __j = (_M_options._M_max_bytes + 1) * sizeof(_Binmap_type); 681*e4b17023SJohn Marino _M_binmap = static_cast<_Binmap_type*>(::operator new(__j)); 682*e4b17023SJohn Marino _Binmap_type* __bp = _M_binmap; 683*e4b17023SJohn Marino _Binmap_type __bin_max = _M_options._M_min_bin; 684*e4b17023SJohn Marino _Binmap_type __bint = 0; 685*e4b17023SJohn Marino for (_Binmap_type __ct = 0; __ct <= _M_options._M_max_bytes; ++__ct) 686*e4b17023SJohn Marino { 687*e4b17023SJohn Marino if (__ct > __bin_max) 688*e4b17023SJohn Marino { 689*e4b17023SJohn Marino __bin_max <<= 1; 690*e4b17023SJohn Marino ++__bint; 691*e4b17023SJohn Marino } 692*e4b17023SJohn Marino *__bp++ = __bint; 693*e4b17023SJohn Marino } 694*e4b17023SJohn Marino 695*e4b17023SJohn Marino // Initialize _M_bin and its members. 696*e4b17023SJohn Marino void* __v = ::operator new(sizeof(_Bin_record) * _M_bin_size); 697*e4b17023SJohn Marino _M_bin = static_cast<_Bin_record*>(__v); 698*e4b17023SJohn Marino 699*e4b17023SJohn Marino // If __gthread_active_p() create and initialize the list of 700*e4b17023SJohn Marino // free thread ids. Single threaded applications use thread id 0 701*e4b17023SJohn Marino // directly and have no need for this. 702*e4b17023SJohn Marino if (__gthread_active_p()) 703*e4b17023SJohn Marino { 704*e4b17023SJohn Marino __freelist& freelist = get_freelist(); 705*e4b17023SJohn Marino { 706*e4b17023SJohn Marino __gnu_cxx::__scoped_lock sentry(get_freelist_mutex()); 707*e4b17023SJohn Marino 708*e4b17023SJohn Marino if (!freelist._M_thread_freelist_array 709*e4b17023SJohn Marino || freelist._M_max_threads < _M_options._M_max_threads) 710*e4b17023SJohn Marino { 711*e4b17023SJohn Marino const size_t __k = sizeof(_Thread_record) 712*e4b17023SJohn Marino * _M_options._M_max_threads; 713*e4b17023SJohn Marino __v = ::operator new(__k); 714*e4b17023SJohn Marino _M_thread_freelist = static_cast<_Thread_record*>(__v); 715*e4b17023SJohn Marino 716*e4b17023SJohn Marino // NOTE! The first assignable thread id is 1 since the 717*e4b17023SJohn Marino // global pool uses id 0 718*e4b17023SJohn Marino size_t __i; 719*e4b17023SJohn Marino for (__i = 1; __i < _M_options._M_max_threads; ++__i) 720*e4b17023SJohn Marino { 721*e4b17023SJohn Marino _Thread_record& __tr = _M_thread_freelist[__i - 1]; 722*e4b17023SJohn Marino __tr._M_next = &_M_thread_freelist[__i]; 723*e4b17023SJohn Marino __tr._M_id = __i; 724*e4b17023SJohn Marino } 725*e4b17023SJohn Marino 726*e4b17023SJohn Marino // Set last record. 727*e4b17023SJohn Marino _M_thread_freelist[__i - 1]._M_next = 0; 728*e4b17023SJohn Marino _M_thread_freelist[__i - 1]._M_id = __i; 729*e4b17023SJohn Marino 730*e4b17023SJohn Marino if (!freelist._M_thread_freelist_array) 731*e4b17023SJohn Marino { 732*e4b17023SJohn Marino // Initialize per thread key to hold pointer to 733*e4b17023SJohn Marino // _M_thread_freelist. 734*e4b17023SJohn Marino __gthread_key_create(&freelist._M_key, 735*e4b17023SJohn Marino ::_M_destroy_thread_key); 736*e4b17023SJohn Marino freelist._M_thread_freelist = _M_thread_freelist; 737*e4b17023SJohn Marino } 738*e4b17023SJohn Marino else 739*e4b17023SJohn Marino { 740*e4b17023SJohn Marino _Thread_record* _M_old_freelist 741*e4b17023SJohn Marino = freelist._M_thread_freelist; 742*e4b17023SJohn Marino _Thread_record* _M_old_array 743*e4b17023SJohn Marino = freelist._M_thread_freelist_array; 744*e4b17023SJohn Marino freelist._M_thread_freelist 745*e4b17023SJohn Marino = &_M_thread_freelist[_M_old_freelist - _M_old_array]; 746*e4b17023SJohn Marino while (_M_old_freelist) 747*e4b17023SJohn Marino { 748*e4b17023SJohn Marino size_t next_id; 749*e4b17023SJohn Marino if (_M_old_freelist->_M_next) 750*e4b17023SJohn Marino next_id = _M_old_freelist->_M_next - _M_old_array; 751*e4b17023SJohn Marino else 752*e4b17023SJohn Marino next_id = freelist._M_max_threads; 753*e4b17023SJohn Marino _M_thread_freelist[_M_old_freelist->_M_id - 1]._M_next 754*e4b17023SJohn Marino = &_M_thread_freelist[next_id]; 755*e4b17023SJohn Marino _M_old_freelist = _M_old_freelist->_M_next; 756*e4b17023SJohn Marino } 757*e4b17023SJohn Marino ::operator delete(static_cast<void*>(_M_old_array)); 758*e4b17023SJohn Marino } 759*e4b17023SJohn Marino freelist._M_thread_freelist_array = _M_thread_freelist; 760*e4b17023SJohn Marino freelist._M_max_threads = _M_options._M_max_threads; 761*e4b17023SJohn Marino } 762*e4b17023SJohn Marino } 763*e4b17023SJohn Marino 764*e4b17023SJohn Marino const size_t __max_threads = _M_options._M_max_threads + 1; 765*e4b17023SJohn Marino for (size_t __n = 0; __n < _M_bin_size; ++__n) 766*e4b17023SJohn Marino { 767*e4b17023SJohn Marino _Bin_record& __bin = _M_bin[__n]; 768*e4b17023SJohn Marino __v = ::operator new(sizeof(_Block_record*) * __max_threads); 769*e4b17023SJohn Marino std::memset(__v, 0, sizeof(_Block_record*) * __max_threads); 770*e4b17023SJohn Marino __bin._M_first = static_cast<_Block_record**>(__v); 771*e4b17023SJohn Marino 772*e4b17023SJohn Marino __bin._M_address = 0; 773*e4b17023SJohn Marino 774*e4b17023SJohn Marino __v = ::operator new(sizeof(size_t) * __max_threads); 775*e4b17023SJohn Marino std::memset(__v, 0, sizeof(size_t) * __max_threads); 776*e4b17023SJohn Marino __bin._M_free = static_cast<size_t*>(__v); 777*e4b17023SJohn Marino 778*e4b17023SJohn Marino __v = ::operator new(sizeof(size_t) * __max_threads + 779*e4b17023SJohn Marino sizeof(_Atomic_word) * __max_threads); 780*e4b17023SJohn Marino std::memset(__v, 0, (sizeof(size_t) * __max_threads 781*e4b17023SJohn Marino + sizeof(_Atomic_word) * __max_threads)); 782*e4b17023SJohn Marino __bin._M_used = static_cast<size_t*>(__v); 783*e4b17023SJohn Marino 784*e4b17023SJohn Marino __v = ::operator new(sizeof(__gthread_mutex_t)); 785*e4b17023SJohn Marino __bin._M_mutex = static_cast<__gthread_mutex_t*>(__v); 786*e4b17023SJohn Marino 787*e4b17023SJohn Marino #ifdef __GTHREAD_MUTEX_INIT 788*e4b17023SJohn Marino { 789*e4b17023SJohn Marino // Do not copy a POSIX/gthr mutex once in use. 790*e4b17023SJohn Marino __gthread_mutex_t __tmp = __GTHREAD_MUTEX_INIT; 791*e4b17023SJohn Marino *__bin._M_mutex = __tmp; 792*e4b17023SJohn Marino } 793*e4b17023SJohn Marino #else 794*e4b17023SJohn Marino { __GTHREAD_MUTEX_INIT_FUNCTION(__bin._M_mutex); } 795*e4b17023SJohn Marino #endif 796*e4b17023SJohn Marino } 797*e4b17023SJohn Marino } 798*e4b17023SJohn Marino else 799*e4b17023SJohn Marino { 800*e4b17023SJohn Marino for (size_t __n = 0; __n < _M_bin_size; ++__n) 801*e4b17023SJohn Marino { 802*e4b17023SJohn Marino _Bin_record& __bin = _M_bin[__n]; 803*e4b17023SJohn Marino __v = ::operator new(sizeof(_Block_record*)); 804*e4b17023SJohn Marino __bin._M_first = static_cast<_Block_record**>(__v); 805*e4b17023SJohn Marino __bin._M_first[0] = 0; 806*e4b17023SJohn Marino __bin._M_address = 0; 807*e4b17023SJohn Marino } 808*e4b17023SJohn Marino } 809*e4b17023SJohn Marino _M_init = true; 810*e4b17023SJohn Marino } 811*e4b17023SJohn Marino #endif 812*e4b17023SJohn Marino 813*e4b17023SJohn Marino // Instantiations. 814*e4b17023SJohn Marino template class __mt_alloc<char>; 815*e4b17023SJohn Marino template class __mt_alloc<wchar_t>; 816*e4b17023SJohn Marino 817*e4b17023SJohn Marino _GLIBCXX_END_NAMESPACE_VERSION 818*e4b17023SJohn Marino } // namespace 819