xref: /dflybsd-src/contrib/gcc-4.7/libstdc++-v3/src/c++98/mt_allocator.cc (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
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