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 1912 : static void determine_alloc_mode()
36 : {
37 : assert(alloc_mode == AMode_UNSET);
38 1912 : alloc_mode = (getenv("G_SLICE") == NULL ? AMode_CUSTOM : AMode_SYSTEM);
39 1912 : }
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 implementation.
92 : *
93 : * ================================================================= */
94 :
95 : void *
96 196793519 : SAL_CALL rtl_allocateMemory_CUSTOM (sal_Size n) SAL_THROW_EXTERN_C()
97 : {
98 196793519 : void * p = 0;
99 196793519 : if (n > 0)
100 : {
101 : char * addr;
102 196793505 : sal_Size size = RTL_MEMORY_ALIGN(n + RTL_MEMALIGN, RTL_MEMALIGN);
103 :
104 : assert(RTL_MEMALIGN >= sizeof(sal_Size));
105 196793505 : 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 196795165 : if (size <= RTL_MEMORY_CACHED_LIMIT)
113 196292125 : addr = static_cast<char*>(rtl_cache_alloc(g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT]));
114 : else
115 503040 : addr = static_cast<char*>(rtl_arena_alloc (gp_alloc_arena, &size));
116 :
117 196794914 : if (addr != 0)
118 : {
119 196793310 : reinterpret_cast<sal_Size*>(addr)[0] = size;
120 196793310 : p = addr + RTL_MEMALIGN;
121 : }
122 1604 : else if (gp_alloc_arena == 0)
123 : {
124 1660 : ensureMemorySingleton();
125 1660 : if (gp_alloc_arena)
126 : {
127 : /* try again */
128 1660 : goto try_alloc;
129 : }
130 : }
131 : }
132 196793268 : return p;
133 : }
134 :
135 : /* ================================================================= */
136 :
137 196160958 : void SAL_CALL rtl_freeMemory_CUSTOM (void * p) SAL_THROW_EXTERN_C()
138 : {
139 196160958 : if (p != 0)
140 : {
141 196159128 : char * addr = static_cast<char*>(p) - RTL_MEMALIGN;
142 196159128 : sal_Size size = reinterpret_cast<sal_Size*>(addr)[0];
143 :
144 196159128 : if (size <= RTL_MEMORY_CACHED_LIMIT)
145 195656144 : rtl_cache_free(g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT], addr);
146 : else
147 502984 : rtl_arena_free (gp_alloc_arena, addr, size);
148 : }
149 196160951 : }
150 :
151 : /* ================================================================= */
152 :
153 5536128 : void * SAL_CALL rtl_reallocateMemory_CUSTOM (void * p, sal_Size n) SAL_THROW_EXTERN_C()
154 : {
155 5536128 : if (n > 0)
156 : {
157 5536128 : if (p != 0)
158 : {
159 5536124 : void * p_old = p;
160 5536124 : sal_Size n_old = reinterpret_cast<sal_Size*>( static_cast<char*>(p) - RTL_MEMALIGN )[0] - RTL_MEMALIGN;
161 :
162 5536124 : p = rtl_allocateMemory (n);
163 5536124 : if (p != 0)
164 : {
165 5536124 : memcpy (p, p_old, (n < n_old) ? n : n_old);
166 5536124 : 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 5536128 : return p;
179 : }
180 :
181 : #endif
182 :
183 : /* ================================================================= *
184 : *
185 : * custom allocator initialization / finalization.
186 : *
187 : * ================================================================= */
188 :
189 1660 : 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 1660 : );
205 : assert(gp_alloc_arena != 0);
206 : }
207 : {
208 : sal_Size size;
209 1660 : int i, n = RTL_MEMORY_CACHED_SIZES;
210 :
211 66400 : for (i = 0; i < n; i++)
212 : {
213 : char name[RTL_CACHE_NAME_LENGTH + 1];
214 64740 : (void) snprintf (name, sizeof(name), "rtl_alloc_%" SAL_PRIuUINTPTR, g_alloc_sizes[i]);
215 64740 : g_alloc_caches[i] = rtl_cache_create (name, g_alloc_sizes[i], 0, NULL, NULL, NULL, NULL, NULL, 0);
216 : }
217 :
218 1660 : size = RTL_MEMALIGN;
219 66400 : for (i = 0; i < n; i++)
220 : {
221 3529160 : while (size <= g_alloc_sizes[i])
222 : {
223 3399680 : g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT] = g_alloc_caches[i];
224 3399680 : size += RTL_MEMALIGN;
225 : }
226 : }
227 : }
228 : #endif
229 : // SAL_INFO("sal.rtl", "rtl_memory_init completed");
230 1660 : }
231 :
232 : /* ================================================================= */
233 :
234 1660 : void rtl_memory_fini()
235 : {
236 : #if !defined(FORCE_SYSALLOC)
237 : int i, n;
238 :
239 : /* clear g_alloc_table */
240 1660 : memset (g_alloc_table, 0, sizeof(g_alloc_table));
241 :
242 : /* cleanup g_alloc_caches */
243 66400 : for (i = 0, n = RTL_MEMORY_CACHED_SIZES; i < n; i++)
244 : {
245 64740 : if (g_alloc_caches[i] != 0)
246 : {
247 64740 : rtl_cache_destroy (g_alloc_caches[i]);
248 64740 : g_alloc_caches[i] = 0;
249 : }
250 : }
251 :
252 : /* cleanup gp_alloc_arena */
253 1660 : if (gp_alloc_arena != 0)
254 : {
255 1660 : rtl_arena_destroy (gp_alloc_arena);
256 1660 : gp_alloc_arena = 0;
257 : }
258 : #endif
259 : // SAL_INFO("sal.rtl", "rtl_memory_fini completed");
260 1660 : }
261 :
262 : /* ================================================================= *
263 : *
264 : * system allocator implementation.
265 : *
266 : * ================================================================= */
267 :
268 3413722318 : void * SAL_CALL rtl_allocateMemory_SYSTEM (sal_Size n)
269 : {
270 3413722318 : return malloc (n);
271 : }
272 :
273 : /* ================================================================= */
274 :
275 3413413042 : void SAL_CALL rtl_freeMemory_SYSTEM (void * p)
276 : {
277 3413413042 : free (p);
278 3413413042 : }
279 :
280 : /* ================================================================= */
281 :
282 507067 : void * SAL_CALL rtl_reallocateMemory_SYSTEM (void * p, sal_Size n)
283 : {
284 507067 : return realloc (p, n);
285 : }
286 :
287 : /* ================================================================= */
288 :
289 3610515162 : 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 3610517072 : if (alloc_mode == AMode_CUSTOM)
298 : {
299 196793517 : return rtl_allocateMemory_CUSTOM(n);
300 : }
301 3413723555 : if (alloc_mode == AMode_SYSTEM)
302 : {
303 3413721645 : return rtl_allocateMemory_SYSTEM(n);
304 : }
305 1910 : determine_alloc_mode();
306 1910 : }
307 : #else
308 : return rtl_allocateMemory_SYSTEM(n);
309 : #endif
310 : }
311 :
312 6043195 : 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 6043195 : if (alloc_mode == AMode_CUSTOM)
321 : {
322 5536128 : return rtl_reallocateMemory_CUSTOM(p,n);
323 : }
324 507067 : if (alloc_mode == AMode_SYSTEM)
325 : {
326 507067 : 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 3609574073 : void SAL_CALL rtl_freeMemory (void * p) SAL_THROW_EXTERN_C()
336 : {
337 : #if !defined(FORCE_SYSALLOC)
338 : while (true)
339 : {
340 3609574071 : if (alloc_mode == AMode_CUSTOM)
341 : {
342 196160959 : rtl_freeMemory_CUSTOM(p);
343 196160952 : return;
344 : }
345 3413413112 : if (alloc_mode == AMode_SYSTEM)
346 : {
347 3413413110 : rtl_freeMemory_SYSTEM(p);
348 3413413856 : return;
349 : }
350 2 : determine_alloc_mode();
351 : }
352 : #else
353 : rtl_freeMemory_SYSTEM(p);
354 : #endif
355 : }
356 :
357 : /* ================================================================= *
358 : *
359 : * rtl_(allocate|free)ZeroMemory() implementation.
360 : *
361 : * ================================================================= */
362 :
363 6724 : void * SAL_CALL rtl_allocateZeroMemory (sal_Size n) SAL_THROW_EXTERN_C()
364 : {
365 6724 : void * p = rtl_allocateMemory (n);
366 6724 : if (p != 0)
367 6711 : memset (p, 0, n);
368 6724 : return p;
369 : }
370 :
371 : /* ================================================================= */
372 :
373 2403 : void SAL_CALL rtl_freeZeroMemory (void * p, sal_Size n) SAL_THROW_EXTERN_C()
374 : {
375 2403 : if (p != 0)
376 : {
377 2403 : rtl_secureZeroMemory (p, n);
378 2403 : rtl_freeMemory (p);
379 : }
380 2403 : }
381 :
382 16 : void* SAL_CALL rtl_allocateAlignedMemory (sal_Size Alignment, sal_Size Bytes) SAL_THROW_EXTERN_C()
383 : {
384 16 : return osl_aligned_alloc(Alignment, Bytes);
385 : }
386 :
387 16 : void SAL_CALL rtl_freeAlignedMemory (void* Ptr) SAL_THROW_EXTERN_C()
388 : {
389 16 : osl_aligned_free(Ptr);
390 16 : }
391 :
392 : /* ================================================================= */
393 :
394 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|