1*f8a1b7d9SAlexander Kabaev // Allocator details.
2*f8a1b7d9SAlexander Kabaev
3*f8a1b7d9SAlexander Kabaev // Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
4*f8a1b7d9SAlexander Kabaev //
5*f8a1b7d9SAlexander Kabaev // This file is part of the GNU ISO C++ Library. This library is free
6*f8a1b7d9SAlexander Kabaev // software; you can redistribute it and/or modify it under the
7*f8a1b7d9SAlexander Kabaev // terms of the GNU General Public License as published by the
8*f8a1b7d9SAlexander Kabaev // Free Software Foundation; either version 2, or (at your option)
9*f8a1b7d9SAlexander Kabaev // any later version.
10*f8a1b7d9SAlexander Kabaev
11*f8a1b7d9SAlexander Kabaev // This library is distributed in the hope that it will be useful,
12*f8a1b7d9SAlexander Kabaev // but WITHOUT ANY WARRANTY; without even the implied warranty of
13*f8a1b7d9SAlexander Kabaev // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*f8a1b7d9SAlexander Kabaev // GNU General Public License for more details.
15*f8a1b7d9SAlexander Kabaev
16*f8a1b7d9SAlexander Kabaev // You should have received a copy of the GNU General Public License along
17*f8a1b7d9SAlexander Kabaev // with this library; see the file COPYING. If not, write to the Free
18*f8a1b7d9SAlexander Kabaev // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19*f8a1b7d9SAlexander Kabaev // USA.
20*f8a1b7d9SAlexander Kabaev
21*f8a1b7d9SAlexander Kabaev // As a special exception, you may use this file as part of a free software
22*f8a1b7d9SAlexander Kabaev // library without restriction. Specifically, if other files instantiate
23*f8a1b7d9SAlexander Kabaev // templates or use macros or inline functions from this file, or you compile
24*f8a1b7d9SAlexander Kabaev // this file and link it with other files to produce an executable, this
25*f8a1b7d9SAlexander Kabaev // file does not by itself cause the resulting executable to be covered by
26*f8a1b7d9SAlexander Kabaev // the GNU General Public License. This exception does not however
27*f8a1b7d9SAlexander Kabaev // invalidate any other reasons why the executable file might be covered by
28*f8a1b7d9SAlexander Kabaev // the GNU General Public License.
29*f8a1b7d9SAlexander Kabaev
30*f8a1b7d9SAlexander Kabaev //
31*f8a1b7d9SAlexander Kabaev // ISO C++ 14882:
32*f8a1b7d9SAlexander Kabaev //
33*f8a1b7d9SAlexander Kabaev
34*f8a1b7d9SAlexander Kabaev #include <bits/c++config.h>
35*f8a1b7d9SAlexander Kabaev #include <cstdlib>
36*f8a1b7d9SAlexander Kabaev #include <ext/pool_allocator.h>
37*f8a1b7d9SAlexander Kabaev
38*f8a1b7d9SAlexander Kabaev namespace
39*f8a1b7d9SAlexander Kabaev {
40*f8a1b7d9SAlexander Kabaev __gnu_cxx::__mutex palloc_init_mutex;
41*f8a1b7d9SAlexander Kabaev } // anonymous namespace
42*f8a1b7d9SAlexander Kabaev
_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)43*f8a1b7d9SAlexander Kabaev _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
44*f8a1b7d9SAlexander Kabaev
45*f8a1b7d9SAlexander Kabaev // Definitions for __pool_alloc_base.
46*f8a1b7d9SAlexander Kabaev __pool_alloc_base::_Obj* volatile*
47*f8a1b7d9SAlexander Kabaev __pool_alloc_base::_M_get_free_list(size_t __bytes)
48*f8a1b7d9SAlexander Kabaev {
49*f8a1b7d9SAlexander Kabaev size_t __i = ((__bytes + (size_t)_S_align - 1) / (size_t)_S_align - 1);
50*f8a1b7d9SAlexander Kabaev return _S_free_list + __i;
51*f8a1b7d9SAlexander Kabaev }
52*f8a1b7d9SAlexander Kabaev
53*f8a1b7d9SAlexander Kabaev __mutex&
_M_get_mutex()54*f8a1b7d9SAlexander Kabaev __pool_alloc_base::_M_get_mutex()
55*f8a1b7d9SAlexander Kabaev { return palloc_init_mutex; }
56*f8a1b7d9SAlexander Kabaev
57*f8a1b7d9SAlexander Kabaev // Allocate memory in large chunks in order to avoid fragmenting the
58*f8a1b7d9SAlexander Kabaev // heap too much. Assume that __n is properly aligned. We hold the
59*f8a1b7d9SAlexander Kabaev // allocation lock.
60*f8a1b7d9SAlexander Kabaev char*
_M_allocate_chunk(size_t __n,int & __nobjs)61*f8a1b7d9SAlexander Kabaev __pool_alloc_base::_M_allocate_chunk(size_t __n, int& __nobjs)
62*f8a1b7d9SAlexander Kabaev {
63*f8a1b7d9SAlexander Kabaev char* __result;
64*f8a1b7d9SAlexander Kabaev size_t __total_bytes = __n * __nobjs;
65*f8a1b7d9SAlexander Kabaev size_t __bytes_left = _S_end_free - _S_start_free;
66*f8a1b7d9SAlexander Kabaev
67*f8a1b7d9SAlexander Kabaev if (__bytes_left >= __total_bytes)
68*f8a1b7d9SAlexander Kabaev {
69*f8a1b7d9SAlexander Kabaev __result = _S_start_free;
70*f8a1b7d9SAlexander Kabaev _S_start_free += __total_bytes;
71*f8a1b7d9SAlexander Kabaev return __result ;
72*f8a1b7d9SAlexander Kabaev }
73*f8a1b7d9SAlexander Kabaev else if (__bytes_left >= __n)
74*f8a1b7d9SAlexander Kabaev {
75*f8a1b7d9SAlexander Kabaev __nobjs = (int)(__bytes_left / __n);
76*f8a1b7d9SAlexander Kabaev __total_bytes = __n * __nobjs;
77*f8a1b7d9SAlexander Kabaev __result = _S_start_free;
78*f8a1b7d9SAlexander Kabaev _S_start_free += __total_bytes;
79*f8a1b7d9SAlexander Kabaev return __result;
80*f8a1b7d9SAlexander Kabaev }
81*f8a1b7d9SAlexander Kabaev else
82*f8a1b7d9SAlexander Kabaev {
83*f8a1b7d9SAlexander Kabaev // Try to make use of the left-over piece.
84*f8a1b7d9SAlexander Kabaev if (__bytes_left > 0)
85*f8a1b7d9SAlexander Kabaev {
86*f8a1b7d9SAlexander Kabaev _Obj* volatile* __free_list = _M_get_free_list(__bytes_left);
87*f8a1b7d9SAlexander Kabaev ((_Obj*)(void*)_S_start_free)->_M_free_list_link = *__free_list;
88*f8a1b7d9SAlexander Kabaev *__free_list = (_Obj*)(void*)_S_start_free;
89*f8a1b7d9SAlexander Kabaev }
90*f8a1b7d9SAlexander Kabaev
91*f8a1b7d9SAlexander Kabaev size_t __bytes_to_get = (2 * __total_bytes
92*f8a1b7d9SAlexander Kabaev + _M_round_up(_S_heap_size >> 4));
93*f8a1b7d9SAlexander Kabaev try
94*f8a1b7d9SAlexander Kabaev {
95*f8a1b7d9SAlexander Kabaev _S_start_free = static_cast<char*>(::operator new(__bytes_to_get));
96*f8a1b7d9SAlexander Kabaev }
97*f8a1b7d9SAlexander Kabaev catch (...)
98*f8a1b7d9SAlexander Kabaev {
99*f8a1b7d9SAlexander Kabaev // Try to make do with what we have. That can't hurt. We
100*f8a1b7d9SAlexander Kabaev // do not try smaller requests, since that tends to result
101*f8a1b7d9SAlexander Kabaev // in disaster on multi-process machines.
102*f8a1b7d9SAlexander Kabaev size_t __i = __n;
103*f8a1b7d9SAlexander Kabaev for (; __i <= (size_t) _S_max_bytes; __i += (size_t) _S_align)
104*f8a1b7d9SAlexander Kabaev {
105*f8a1b7d9SAlexander Kabaev _Obj* volatile* __free_list = _M_get_free_list(__i);
106*f8a1b7d9SAlexander Kabaev _Obj* __p = *__free_list;
107*f8a1b7d9SAlexander Kabaev if (__p != 0)
108*f8a1b7d9SAlexander Kabaev {
109*f8a1b7d9SAlexander Kabaev *__free_list = __p->_M_free_list_link;
110*f8a1b7d9SAlexander Kabaev _S_start_free = (char*)__p;
111*f8a1b7d9SAlexander Kabaev _S_end_free = _S_start_free + __i;
112*f8a1b7d9SAlexander Kabaev return _M_allocate_chunk(__n, __nobjs);
113*f8a1b7d9SAlexander Kabaev // Any leftover piece will eventually make it to the
114*f8a1b7d9SAlexander Kabaev // right free list.
115*f8a1b7d9SAlexander Kabaev }
116*f8a1b7d9SAlexander Kabaev }
117*f8a1b7d9SAlexander Kabaev // What we have wasn't enough. Rethrow.
118*f8a1b7d9SAlexander Kabaev _S_start_free = _S_end_free = 0; // We have no chunk.
119*f8a1b7d9SAlexander Kabaev __throw_exception_again;
120*f8a1b7d9SAlexander Kabaev }
121*f8a1b7d9SAlexander Kabaev _S_heap_size += __bytes_to_get;
122*f8a1b7d9SAlexander Kabaev _S_end_free = _S_start_free + __bytes_to_get;
123*f8a1b7d9SAlexander Kabaev return _M_allocate_chunk(__n, __nobjs);
124*f8a1b7d9SAlexander Kabaev }
125*f8a1b7d9SAlexander Kabaev }
126*f8a1b7d9SAlexander Kabaev
127*f8a1b7d9SAlexander Kabaev // Returns an object of size __n, and optionally adds to "size
128*f8a1b7d9SAlexander Kabaev // __n"'s free list. We assume that __n is properly aligned. We
129*f8a1b7d9SAlexander Kabaev // hold the allocation lock.
130*f8a1b7d9SAlexander Kabaev void*
_M_refill(size_t __n)131*f8a1b7d9SAlexander Kabaev __pool_alloc_base::_M_refill(size_t __n)
132*f8a1b7d9SAlexander Kabaev {
133*f8a1b7d9SAlexander Kabaev int __nobjs = 20;
134*f8a1b7d9SAlexander Kabaev char* __chunk = _M_allocate_chunk(__n, __nobjs);
135*f8a1b7d9SAlexander Kabaev _Obj* volatile* __free_list;
136*f8a1b7d9SAlexander Kabaev _Obj* __result;
137*f8a1b7d9SAlexander Kabaev _Obj* __current_obj;
138*f8a1b7d9SAlexander Kabaev _Obj* __next_obj;
139*f8a1b7d9SAlexander Kabaev
140*f8a1b7d9SAlexander Kabaev if (__nobjs == 1)
141*f8a1b7d9SAlexander Kabaev return __chunk;
142*f8a1b7d9SAlexander Kabaev __free_list = _M_get_free_list(__n);
143*f8a1b7d9SAlexander Kabaev
144*f8a1b7d9SAlexander Kabaev // Build free list in chunk.
145*f8a1b7d9SAlexander Kabaev __result = (_Obj*)(void*)__chunk;
146*f8a1b7d9SAlexander Kabaev *__free_list = __next_obj = (_Obj*)(void*)(__chunk + __n);
147*f8a1b7d9SAlexander Kabaev for (int __i = 1; ; __i++)
148*f8a1b7d9SAlexander Kabaev {
149*f8a1b7d9SAlexander Kabaev __current_obj = __next_obj;
150*f8a1b7d9SAlexander Kabaev __next_obj = (_Obj*)(void*)((char*)__next_obj + __n);
151*f8a1b7d9SAlexander Kabaev if (__nobjs - 1 == __i)
152*f8a1b7d9SAlexander Kabaev {
153*f8a1b7d9SAlexander Kabaev __current_obj->_M_free_list_link = 0;
154*f8a1b7d9SAlexander Kabaev break;
155*f8a1b7d9SAlexander Kabaev }
156*f8a1b7d9SAlexander Kabaev else
157*f8a1b7d9SAlexander Kabaev __current_obj->_M_free_list_link = __next_obj;
158*f8a1b7d9SAlexander Kabaev }
159*f8a1b7d9SAlexander Kabaev return __result;
160*f8a1b7d9SAlexander Kabaev }
161*f8a1b7d9SAlexander Kabaev
162*f8a1b7d9SAlexander Kabaev __pool_alloc_base::_Obj* volatile __pool_alloc_base::_S_free_list[_S_free_list_size];
163*f8a1b7d9SAlexander Kabaev
164*f8a1b7d9SAlexander Kabaev char* __pool_alloc_base::_S_start_free = 0;
165*f8a1b7d9SAlexander Kabaev
166*f8a1b7d9SAlexander Kabaev char* __pool_alloc_base::_S_end_free = 0;
167*f8a1b7d9SAlexander Kabaev
168*f8a1b7d9SAlexander Kabaev size_t __pool_alloc_base::_S_heap_size = 0;
169*f8a1b7d9SAlexander Kabaev
170*f8a1b7d9SAlexander Kabaev // Instantiations.
171*f8a1b7d9SAlexander Kabaev template class __pool_alloc<char>;
172*f8a1b7d9SAlexander Kabaev template class __pool_alloc<wchar_t>;
173*f8a1b7d9SAlexander Kabaev
174*f8a1b7d9SAlexander Kabaev _GLIBCXX_END_NAMESPACE
175