Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "alloc_impl.hxx"
21 : #include "rtl/alloc.h"
22 : #include <sal/log.hxx>
23 : #include <sal/macros.h>
24 :
25 : #include <cassert>
26 : #include <string.h>
27 : #include <stdio.h>
28 :
29 : #include "internal/rtllifecycle.h"
30 : #include <internal/oslmemory.h>
31 :
32 : AllocMode alloc_mode = AMode_UNSET;
33 :
34 : #if !defined(FORCE_SYSALLOC)
35 2842 : static void determine_alloc_mode()
36 : {
37 : assert(alloc_mode == AMode_UNSET);
38 2842 : alloc_mode = (getenv("G_SLICE") == NULL ? AMode_CUSTOM : AMode_SYSTEM);
39 2842 : }
40 :
41 : /* ================================================================= *
42 : *
43 : * custom allocator includes.
44 : *
45 : * ================================================================= */
46 :
47 : #include "sal/macros.h"
48 :
49 : /* ================================================================= *
50 : *
51 : * custom allocator internals.
52 : *
53 : * ================================================================= */
54 :
55 : static const sal_Size g_alloc_sizes[] =
56 : {
57 : /* powers of 2**(1/4) */
58 : 4 * 4, 6 * 4,
59 : 4 * 8, 5 * 8, 6 * 8, 7 * 8,
60 : 4 * 16, 5 * 16, 6 * 16, 7 * 16,
61 : 4 * 32, 5 * 32, 6 * 32, 7 * 32,
62 : 4 * 64, 5 * 64, 6 * 64, 7 * 64,
63 : 4 * 128, 5 * 128, 6 * 128, 7 * 128,
64 : 4 * 256, 5 * 256, 6 * 256, 7 * 256,
65 : 4 * 512, 5 * 512, 6 * 512, 7 * 512,
66 : 4 * 1024, 5 * 1024, 6 * 1024, 7 * 1024,
67 : 4 * 2048, 5 * 2048, 6 * 2048, 7 * 2048,
68 : 4 * 4096
69 : };
70 :
71 : #define RTL_MEMORY_CACHED_LIMIT 4 * 4096
72 : #define RTL_MEMORY_CACHED_SIZES (SAL_N_ELEMENTS(g_alloc_sizes))
73 :
74 : static rtl_cache_type * g_alloc_caches[RTL_MEMORY_CACHED_SIZES] =
75 : {
76 : 0,
77 : };
78 :
79 : #define RTL_MEMALIGN 8
80 : #define RTL_MEMALIGN_SHIFT 3
81 :
82 : static rtl_cache_type * g_alloc_table[RTL_MEMORY_CACHED_LIMIT >> RTL_MEMALIGN_SHIFT] =
83 : {
84 : 0,
85 : };
86 :
87 : static rtl_arena_type * gp_alloc_arena = 0;
88 :
89 : /* ================================================================= *
90 : *
91 : * custom allocator implemenation.
92 : *
93 : * ================================================================= */
94 :
95 : void *
96 312517332 : SAL_CALL rtl_allocateMemory_CUSTOM (sal_Size n) SAL_THROW_EXTERN_C()
97 : {
98 312517332 : void * p = 0;
99 312517332 : if (n > 0)
100 : {
101 : char * addr;
102 312517277 : sal_Size size = RTL_MEMORY_ALIGN(n + RTL_MEMALIGN, RTL_MEMALIGN);
103 :
104 : assert(RTL_MEMALIGN >= sizeof(sal_Size));
105 312517277 : if (n >= SAL_MAX_SIZE - (RTL_MEMALIGN + RTL_MEMALIGN - 1))
106 : {
107 : /* requested size too large for roundup alignment */
108 0 : return 0;
109 : }
110 :
111 : try_alloc:
112 312519759 : if (size <= RTL_MEMORY_CACHED_LIMIT)
113 311910856 : addr = (char*)rtl_cache_alloc(g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT]);
114 : else
115 608903 : addr = (char*)rtl_arena_alloc (gp_alloc_arena, &size);
116 :
117 312520737 : if (addr != 0)
118 : {
119 312518177 : ((sal_Size*)(addr))[0] = size;
120 312518177 : p = addr + RTL_MEMALIGN;
121 : }
122 2560 : else if (gp_alloc_arena == 0)
123 : {
124 2482 : ensureMemorySingleton();
125 2482 : if (gp_alloc_arena)
126 : {
127 : /* try again */
128 2482 : goto try_alloc;
129 : }
130 : }
131 : }
132 312518310 : return (p);
133 : }
134 :
135 : /* ================================================================= */
136 :
137 311655451 : void SAL_CALL rtl_freeMemory_CUSTOM (void * p) SAL_THROW_EXTERN_C()
138 : {
139 311655451 : if (p != 0)
140 : {
141 311652866 : char * addr = (char*)(p) - RTL_MEMALIGN;
142 311652866 : sal_Size size = ((sal_Size*)(addr))[0];
143 :
144 311652866 : if (size <= RTL_MEMORY_CACHED_LIMIT)
145 311044008 : rtl_cache_free(g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT], addr);
146 : else
147 608858 : rtl_arena_free (gp_alloc_arena, addr, size);
148 : }
149 311656130 : }
150 :
151 : /* ================================================================= */
152 :
153 8615668 : void * SAL_CALL rtl_reallocateMemory_CUSTOM (void * p, sal_Size n) SAL_THROW_EXTERN_C()
154 : {
155 8615668 : if (n > 0)
156 : {
157 8615668 : if (p != 0)
158 : {
159 8615664 : void * p_old = p;
160 8615664 : sal_Size n_old = ((sal_Size*)( (char*)(p) - RTL_MEMALIGN ))[0] - RTL_MEMALIGN;
161 :
162 8615664 : p = rtl_allocateMemory (n);
163 8615664 : if (p != 0)
164 : {
165 8615664 : memcpy (p, p_old, (n < n_old) ? n : n_old);
166 8615664 : rtl_freeMemory (p_old);
167 : }
168 : }
169 : else
170 : {
171 4 : p = rtl_allocateMemory (n);
172 : }
173 : }
174 0 : else if (p != 0)
175 : {
176 0 : rtl_freeMemory (p), p = 0;
177 : }
178 8615668 : return (p);
179 : }
180 :
181 : #endif
182 :
183 : /* ================================================================= *
184 : *
185 : * custom allocator initialization / finalization.
186 : *
187 : * ================================================================= */
188 :
189 2482 : void rtl_memory_init()
190 : {
191 : #if !defined(FORCE_SYSALLOC)
192 : {
193 : /* global memory arena */
194 : assert(gp_alloc_arena == 0);
195 :
196 : gp_alloc_arena = rtl_arena_create (
197 : "rtl_alloc_arena",
198 : 2048, /* quantum */
199 : 0, /* w/o quantum caching */
200 : 0, /* default source */
201 : rtl_arena_alloc,
202 : rtl_arena_free,
203 : 0 /* flags */
204 2482 : );
205 : assert(gp_alloc_arena != 0);
206 : }
207 : {
208 : sal_Size size;
209 2482 : int i, n = RTL_MEMORY_CACHED_SIZES;
210 :
211 99280 : for (i = 0; i < n; i++)
212 : {
213 : char name[RTL_CACHE_NAME_LENGTH + 1];
214 96798 : (void) snprintf (name, sizeof(name), "rtl_alloc_%" SAL_PRIuUINTPTR, g_alloc_sizes[i]);
215 96798 : g_alloc_caches[i] = rtl_cache_create (name, g_alloc_sizes[i], 0, NULL, NULL, NULL, NULL, NULL, 0);
216 : }
217 :
218 2482 : size = RTL_MEMALIGN;
219 99280 : for (i = 0; i < n; i++)
220 : {
221 5276732 : while (size <= g_alloc_sizes[i])
222 : {
223 5083136 : g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT] = g_alloc_caches[i];
224 5083136 : size += RTL_MEMALIGN;
225 : }
226 : }
227 : }
228 : #endif
229 : // SAL_INFO("sal.rtl", "rtl_memory_init completed");
230 2482 : }
231 :
232 : /* ================================================================= */
233 :
234 2482 : void rtl_memory_fini()
235 : {
236 : #if !defined(FORCE_SYSALLOC)
237 : int i, n;
238 :
239 : /* clear g_alloc_table */
240 2482 : memset (g_alloc_table, 0, sizeof(g_alloc_table));
241 :
242 : /* cleanup g_alloc_caches */
243 99280 : for (i = 0, n = RTL_MEMORY_CACHED_SIZES; i < n; i++)
244 : {
245 96798 : if (g_alloc_caches[i] != 0)
246 : {
247 96798 : rtl_cache_destroy (g_alloc_caches[i]);
248 96798 : g_alloc_caches[i] = 0;
249 : }
250 : }
251 :
252 : /* cleanup gp_alloc_arena */
253 2482 : if (gp_alloc_arena != 0)
254 : {
255 2482 : rtl_arena_destroy (gp_alloc_arena);
256 2482 : gp_alloc_arena = 0;
257 : }
258 : #endif
259 : // SAL_INFO("sal.rtl", "rtl_memory_fini completed");
260 2482 : }
261 :
262 : /* ================================================================= *
263 : *
264 : * system allocator implemenation.
265 : *
266 : * ================================================================= */
267 :
268 103623261 : void * SAL_CALL rtl_allocateMemory_SYSTEM (sal_Size n)
269 : {
270 103623261 : return malloc (n);
271 : }
272 :
273 : /* ================================================================= */
274 :
275 103316139 : void SAL_CALL rtl_freeMemory_SYSTEM (void * p)
276 : {
277 103316139 : free (p);
278 103316139 : }
279 :
280 : /* ================================================================= */
281 :
282 611879 : void * SAL_CALL rtl_reallocateMemory_SYSTEM (void * p, sal_Size n)
283 : {
284 611879 : return realloc (p, n);
285 : }
286 :
287 : /* ================================================================= */
288 :
289 416139579 : void* SAL_CALL rtl_allocateMemory (sal_Size n) SAL_THROW_EXTERN_C()
290 : {
291 : SAL_WARN_IF(
292 : n >= SAL_MAX_INT32, "sal.rtl",
293 : "suspicious massive alloc " << n);
294 : #if !defined(FORCE_SYSALLOC)
295 : while (true)
296 : {
297 416142417 : if (alloc_mode == AMode_CUSTOM)
298 : {
299 312517356 : return rtl_allocateMemory_CUSTOM(n);
300 : }
301 103625061 : if (alloc_mode == AMode_SYSTEM)
302 : {
303 103622223 : return rtl_allocateMemory_SYSTEM(n);
304 : }
305 2838 : determine_alloc_mode();
306 2838 : }
307 : #else
308 : return rtl_allocateMemory_SYSTEM(n);
309 : #endif
310 : }
311 :
312 9227547 : void* SAL_CALL rtl_reallocateMemory (void * p, sal_Size n) SAL_THROW_EXTERN_C()
313 : {
314 : SAL_WARN_IF(
315 : n >= SAL_MAX_INT32, "sal.rtl",
316 : "suspicious massive alloc " << n);
317 : #if !defined(FORCE_SYSALLOC)
318 : while (true)
319 : {
320 9227547 : if (alloc_mode == AMode_CUSTOM)
321 : {
322 8615668 : return rtl_reallocateMemory_CUSTOM(p,n);
323 : }
324 611879 : if (alloc_mode == AMode_SYSTEM)
325 : {
326 611879 : return rtl_reallocateMemory_SYSTEM(p,n);
327 : }
328 0 : determine_alloc_mode();
329 0 : }
330 : #else
331 : return rtl_reallocateMemory_SYSTEM(p,n);
332 : #endif
333 : }
334 :
335 414971632 : void SAL_CALL rtl_freeMemory (void * p) SAL_THROW_EXTERN_C()
336 : {
337 : #if !defined(FORCE_SYSALLOC)
338 : while (true)
339 : {
340 414971632 : if (alloc_mode == AMode_CUSTOM)
341 : {
342 311655452 : rtl_freeMemory_CUSTOM(p);
343 311656125 : return;
344 : }
345 103316180 : if (alloc_mode == AMode_SYSTEM)
346 : {
347 103316176 : rtl_freeMemory_SYSTEM(p);
348 103316894 : return;
349 : }
350 4 : determine_alloc_mode();
351 : }
352 : #else
353 : rtl_freeMemory_SYSTEM(p);
354 : #endif
355 : }
356 :
357 : /* ================================================================= *
358 : *
359 : * rtl_(allocate|free)ZeroMemory() implemenation.
360 : *
361 : * ================================================================= */
362 :
363 11050 : void * SAL_CALL rtl_allocateZeroMemory (sal_Size n) SAL_THROW_EXTERN_C()
364 : {
365 11050 : void * p = rtl_allocateMemory (n);
366 11050 : if (p != 0)
367 11016 : memset (p, 0, n);
368 11050 : return (p);
369 : }
370 :
371 : /* ================================================================= */
372 :
373 3894 : void SAL_CALL rtl_freeZeroMemory (void * p, sal_Size n) SAL_THROW_EXTERN_C()
374 : {
375 3894 : if (p != 0)
376 : {
377 3894 : memset (p, 0, n);
378 3894 : rtl_freeMemory (p);
379 : }
380 3894 : }
381 :
382 28 : void* SAL_CALL rtl_allocateAlignedMemory (sal_Size Alignment, sal_Size Bytes) SAL_THROW_EXTERN_C()
383 : {
384 28 : return osl_aligned_alloc(Alignment, Bytes);
385 : }
386 :
387 28 : void SAL_CALL rtl_freeAlignedMemory (void* Ptr) SAL_THROW_EXTERN_C()
388 : {
389 28 : osl_aligned_free(Ptr);
390 28 : }
391 :
392 : /* ================================================================= */
393 :
394 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|