Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "alloc_impl.hxx"
30 : : #include "rtl/alloc.h"
31 : : #include <sal/log.hxx>
32 : : #include <sal/macros.h>
33 : :
34 : : #include <cassert>
35 : : #include <string.h>
36 : : #include <stdio.h>
37 : :
38 : : #include "internal/rtllifecycle.h"
39 : :
40 : : AllocMode alloc_mode = AMode_UNSET;
41 : :
42 : : #if !defined(FORCE_SYSALLOC)
43 : 3013 : static void determine_alloc_mode()
44 : : {
45 : : assert(alloc_mode == AMode_UNSET);
46 : 3013 : alloc_mode = (getenv("G_SLICE") == NULL ? AMode_CUSTOM : AMode_SYSTEM);
47 : 3013 : }
48 : :
49 : : /* ================================================================= *
50 : : *
51 : : * custom allocator includes.
52 : : *
53 : : * ================================================================= */
54 : :
55 : : #include "sal/macros.h"
56 : :
57 : : /* ================================================================= *
58 : : *
59 : : * custom allocator internals.
60 : : *
61 : : * ================================================================= */
62 : :
63 : : static const sal_Size g_alloc_sizes[] =
64 : : {
65 : : /* powers of 2**(1/4) */
66 : : 4 * 4, 6 * 4,
67 : : 4 * 8, 5 * 8, 6 * 8, 7 * 8,
68 : : 4 * 16, 5 * 16, 6 * 16, 7 * 16,
69 : : 4 * 32, 5 * 32, 6 * 32, 7 * 32,
70 : : 4 * 64, 5 * 64, 6 * 64, 7 * 64,
71 : : 4 * 128, 5 * 128, 6 * 128, 7 * 128,
72 : : 4 * 256, 5 * 256, 6 * 256, 7 * 256,
73 : : 4 * 512, 5 * 512, 6 * 512, 7 * 512,
74 : : 4 * 1024, 5 * 1024, 6 * 1024, 7 * 1024,
75 : : 4 * 2048, 5 * 2048, 6 * 2048, 7 * 2048,
76 : : 4 * 4096
77 : : };
78 : :
79 : : #define RTL_MEMORY_CACHED_LIMIT 4 * 4096
80 : : #define RTL_MEMORY_CACHED_SIZES (SAL_N_ELEMENTS(g_alloc_sizes))
81 : :
82 : : static rtl_cache_type * g_alloc_caches[RTL_MEMORY_CACHED_SIZES] =
83 : : {
84 : : 0,
85 : : };
86 : :
87 : : #define RTL_MEMALIGN 8
88 : : #define RTL_MEMALIGN_SHIFT 3
89 : :
90 : : static rtl_cache_type * g_alloc_table[RTL_MEMORY_CACHED_LIMIT >> RTL_MEMALIGN_SHIFT] =
91 : : {
92 : : 0,
93 : : };
94 : :
95 : : static rtl_arena_type * gp_alloc_arena = 0;
96 : :
97 : : /* ================================================================= *
98 : : *
99 : : * custom allocator implemenation.
100 : : *
101 : : * ================================================================= */
102 : :
103 : : void *
104 : 129625921 : SAL_CALL rtl_allocateMemory_CUSTOM (sal_Size n) SAL_THROW_EXTERN_C()
105 : : {
106 : 129625921 : void * p = 0;
107 [ + + ]: 129625921 : if (n > 0)
108 : : {
109 : : char * addr;
110 : 129580212 : sal_Size size = RTL_MEMORY_ALIGN(n + RTL_MEMALIGN, RTL_MEMALIGN);
111 : :
112 : : assert(RTL_MEMALIGN >= sizeof(sal_Size));
113 [ - + ]: 129580212 : if (n >= SAL_MAX_SIZE - (RTL_MEMALIGN + RTL_MEMALIGN - 1))
114 : : {
115 : : /* requested size too large for roundup alignment */
116 : 0 : return 0;
117 : : }
118 : :
119 : : try_alloc:
120 [ + + ]: 129582954 : if (size <= RTL_MEMORY_CACHED_LIMIT)
121 : 129473172 : addr = (char*)rtl_cache_alloc(g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT]);
122 : : else
123 : 109782 : addr = (char*)rtl_arena_alloc (gp_alloc_arena, &size);
124 : :
125 [ + + ]: 129582954 : if (addr != 0)
126 : : {
127 : 129580212 : ((sal_Size*)(addr))[0] = size;
128 : 129580212 : p = addr + RTL_MEMALIGN;
129 : : }
130 [ + - ]: 2742 : else if (gp_alloc_arena == 0)
131 : : {
132 [ + - ]: 2742 : ensureMemorySingleton();
133 [ + - ]: 2742 : if (gp_alloc_arena)
134 : : {
135 : : /* try again */
136 : 129582954 : goto try_alloc;
137 : : }
138 : : }
139 : : }
140 : 129625921 : return (p);
141 : : }
142 : :
143 : : /* ================================================================= */
144 : :
145 : 126574105 : void SAL_CALL rtl_freeMemory_CUSTOM (void * p) SAL_THROW_EXTERN_C()
146 : : {
147 [ + + ]: 126574105 : if (p != 0)
148 : : {
149 : 126538499 : char * addr = (char*)(p) - RTL_MEMALIGN;
150 : 126538499 : sal_Size size = ((sal_Size*)(addr))[0];
151 : :
152 [ + + ]: 126538499 : if (size <= RTL_MEMORY_CACHED_LIMIT)
153 : 126429871 : rtl_cache_free(g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT], addr);
154 : : else
155 : 108628 : rtl_arena_free (gp_alloc_arena, addr, size);
156 : : }
157 : 126574105 : }
158 : :
159 : : /* ================================================================= */
160 : :
161 : 5500105 : void * SAL_CALL rtl_reallocateMemory_CUSTOM (void * p, sal_Size n) SAL_THROW_EXTERN_C()
162 : : {
163 [ + - ]: 5500105 : if (n > 0)
164 : : {
165 [ + - ]: 5500105 : if (p != 0)
166 : : {
167 : 5500105 : void * p_old = p;
168 : 5500105 : sal_Size n_old = ((sal_Size*)( (char*)(p) - RTL_MEMALIGN ))[0] - RTL_MEMALIGN;
169 : :
170 : 5500105 : p = rtl_allocateMemory (n);
171 [ + - ]: 5500105 : if (p != 0)
172 : : {
173 [ + + ]: 5500105 : memcpy (p, p_old, SAL_MIN(n, n_old));
174 : 5500105 : rtl_freeMemory (p_old);
175 : : }
176 : : }
177 : : else
178 : : {
179 : 0 : p = rtl_allocateMemory (n);
180 : : }
181 : : }
182 [ # # ]: 0 : else if (p != 0)
183 : : {
184 : 0 : rtl_freeMemory (p), p = 0;
185 : : }
186 : 5500105 : return (p);
187 : : }
188 : :
189 : : #endif
190 : :
191 : : /* ================================================================= *
192 : : *
193 : : * custom allocator initialization / finalization.
194 : : *
195 : : * ================================================================= */
196 : :
197 : 2742 : void rtl_memory_init()
198 : : {
199 : : #if !defined(FORCE_SYSALLOC)
200 : : {
201 : : /* global memory arena */
202 : : assert(gp_alloc_arena == 0);
203 : :
204 : : gp_alloc_arena = rtl_arena_create (
205 : : "rtl_alloc_arena",
206 : : 2048, /* quantum */
207 : : 0, /* w/o quantum caching */
208 : : 0, /* default source */
209 : : rtl_arena_alloc,
210 : : rtl_arena_free,
211 : : 0 /* flags */
212 : 2742 : );
213 : : assert(gp_alloc_arena != 0);
214 : : }
215 : : {
216 : : sal_Size size;
217 : 2742 : int i, n = RTL_MEMORY_CACHED_SIZES;
218 : :
219 [ + + ]: 109680 : for (i = 0; i < n; i++)
220 : : {
221 : : char name[RTL_CACHE_NAME_LENGTH + 1];
222 : 106938 : (void) snprintf (name, sizeof(name), "rtl_alloc_%lu", g_alloc_sizes[i]);
223 : 106938 : g_alloc_caches[i] = rtl_cache_create (name, g_alloc_sizes[i], 0, NULL, NULL, NULL, NULL, NULL, 0);
224 : : }
225 : :
226 : 2742 : size = RTL_MEMALIGN;
227 [ + + ]: 109680 : for (i = 0; i < n; i++)
228 : : {
229 [ + + ]: 5722554 : while (size <= g_alloc_sizes[i])
230 : : {
231 : 5615616 : g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT] = g_alloc_caches[i];
232 : 5615616 : size += RTL_MEMALIGN;
233 : : }
234 : : }
235 : : }
236 : : #endif
237 : : // SAL_INFO("sal", "rtl_memory_init completed");
238 : 2742 : }
239 : :
240 : : /* ================================================================= */
241 : :
242 : 2742 : void rtl_memory_fini()
243 : : {
244 : : #if !defined(FORCE_SYSALLOC)
245 : : int i, n;
246 : :
247 : : /* clear g_alloc_table */
248 : 2742 : memset (g_alloc_table, 0, sizeof(g_alloc_table));
249 : :
250 : : /* cleanup g_alloc_caches */
251 [ + + ]: 109680 : for (i = 0, n = RTL_MEMORY_CACHED_SIZES; i < n; i++)
252 : : {
253 [ + - ]: 106938 : if (g_alloc_caches[i] != 0)
254 : : {
255 : 106938 : rtl_cache_destroy (g_alloc_caches[i]);
256 : 106938 : g_alloc_caches[i] = 0;
257 : : }
258 : : }
259 : :
260 : : /* cleanup gp_alloc_arena */
261 [ + - ]: 2742 : if (gp_alloc_arena != 0)
262 : : {
263 : 2742 : rtl_arena_destroy (gp_alloc_arena);
264 : 2742 : gp_alloc_arena = 0;
265 : : }
266 : : #endif
267 : : // SAL_INFO("sal", "rtl_memory_fini completed");
268 : 2742 : }
269 : :
270 : : /* ================================================================= *
271 : : *
272 : : * system allocator implemenation.
273 : : *
274 : : * ================================================================= */
275 : :
276 : 106202503 : void * SAL_CALL rtl_allocateMemory_SYSTEM (sal_Size n)
277 : : {
278 : 106202503 : return malloc (n);
279 : : }
280 : :
281 : : /* ================================================================= */
282 : :
283 : 105557097 : void SAL_CALL rtl_freeMemory_SYSTEM (void * p)
284 : : {
285 : 105557097 : free (p);
286 : 105557097 : }
287 : :
288 : : /* ================================================================= */
289 : :
290 : 923936 : void * SAL_CALL rtl_reallocateMemory_SYSTEM (void * p, sal_Size n)
291 : : {
292 : 923936 : return realloc (p, n);
293 : : }
294 : :
295 : : /* ================================================================= */
296 : :
297 : 235828012 : void* SAL_CALL rtl_allocateMemory (sal_Size n) SAL_THROW_EXTERN_C()
298 : : {
299 : : SAL_WARN_IF(
300 : : n >= SAL_MAX_INT32, "sal",
301 : : "suspicious massive alloc " << n);
302 : : #if !defined(FORCE_SYSALLOC)
303 : 235831459 : while (1)
304 : : {
305 [ + + ]: 235831015 : if (alloc_mode == AMode_CUSTOM)
306 : : {
307 : 129625920 : return rtl_allocateMemory_CUSTOM(n);
308 : : }
309 [ + + ]: 106205095 : if (alloc_mode == AMode_SYSTEM)
310 : : {
311 : 106202092 : return rtl_allocateMemory_SYSTEM(n);
312 : : }
313 : 3003 : determine_alloc_mode();
314 : : }
315 : : #else
316 : : return rtl_allocateMemory_SYSTEM(n);
317 : : #endif
318 : : }
319 : :
320 : 6424041 : void* SAL_CALL rtl_reallocateMemory (void * p, sal_Size n) SAL_THROW_EXTERN_C()
321 : : {
322 : : SAL_WARN_IF(
323 : : n >= SAL_MAX_INT32, "sal",
324 : : "suspicious massive alloc " << n);
325 : : #if !defined(FORCE_SYSALLOC)
326 : 6424041 : while (1)
327 : : {
328 [ + + ]: 6424041 : if (alloc_mode == AMode_CUSTOM)
329 : : {
330 : 5500105 : return rtl_reallocateMemory_CUSTOM(p,n);
331 : : }
332 [ + - ]: 923936 : if (alloc_mode == AMode_SYSTEM)
333 : : {
334 : 923936 : return rtl_reallocateMemory_SYSTEM(p,n);
335 : : }
336 : 0 : determine_alloc_mode();
337 : : }
338 : : #else
339 : : return rtl_reallocateMemory_SYSTEM(p,n);
340 : : #endif
341 : : }
342 : :
343 : 232131059 : void SAL_CALL rtl_freeMemory (void * p) SAL_THROW_EXTERN_C()
344 : : {
345 : : #if !defined(FORCE_SYSALLOC)
346 : 10 : while (1)
347 : : {
348 [ + + ]: 232131059 : if (alloc_mode == AMode_CUSTOM)
349 : : {
350 : 126574104 : rtl_freeMemory_CUSTOM(p);
351 : 232131377 : return;
352 : : }
353 [ + + ]: 105556955 : if (alloc_mode == AMode_SYSTEM)
354 : : {
355 : 105556945 : rtl_freeMemory_SYSTEM(p);
356 : 105557272 : return;
357 : : }
358 : 10 : determine_alloc_mode();
359 : : }
360 : : #else
361 : : rtl_freeMemory_SYSTEM(p);
362 : : #endif
363 : : }
364 : :
365 : : /* ================================================================= *
366 : : *
367 : : * rtl_(allocate|free)ZeroMemory() implemenation.
368 : : *
369 : : * ================================================================= */
370 : :
371 : 68140 : void * SAL_CALL rtl_allocateZeroMemory (sal_Size n) SAL_THROW_EXTERN_C()
372 : : {
373 : 68140 : void * p = rtl_allocateMemory (n);
374 [ + + ]: 68140 : if (p != 0)
375 : 22436 : memset (p, 0, n);
376 : 68140 : return (p);
377 : : }
378 : :
379 : : /* ================================================================= */
380 : :
381 : 2330 : void SAL_CALL rtl_freeZeroMemory (void * p, sal_Size n) SAL_THROW_EXTERN_C()
382 : : {
383 [ + - ]: 2330 : if (p != 0)
384 : : {
385 : 2330 : memset (p, 0, n);
386 : 2330 : rtl_freeMemory (p);
387 : : }
388 : 2330 : }
389 : :
390 : : /* ================================================================= */
391 : :
392 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|