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 1788 : static void determine_alloc_mode()
36 : {
37 : assert(alloc_mode == AMode_UNSET);
38 1788 : alloc_mode = (getenv("G_SLICE") == NULL ? AMode_CUSTOM : AMode_SYSTEM);
39 1788 : }
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 136865490 : SAL_CALL rtl_allocateMemory_CUSTOM (sal_Size n) SAL_THROW_EXTERN_C()
97 : {
98 136865490 : void * p = 0;
99 136865490 : if (n > 0)
100 : {
101 : char * addr;
102 136864530 : sal_Size size = RTL_MEMORY_ALIGN(n + RTL_MEMALIGN, RTL_MEMALIGN);
103 :
104 : assert(RTL_MEMALIGN >= sizeof(sal_Size));
105 136864530 : 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 136866138 : if (size <= RTL_MEMORY_CACHED_LIMIT)
113 136452575 : addr = (char*)rtl_cache_alloc(g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT]);
114 : else
115 413563 : addr = (char*)rtl_arena_alloc (gp_alloc_arena, &size);
116 :
117 136865129 : if (addr != 0)
118 : {
119 136864516 : ((sal_Size*)(addr))[0] = size;
120 136864516 : p = addr + RTL_MEMALIGN;
121 : }
122 613 : else if (gp_alloc_arena == 0)
123 : {
124 1608 : ensureMemorySingleton();
125 1608 : if (gp_alloc_arena)
126 : {
127 : /* try again */
128 1608 : goto try_alloc;
129 : }
130 : }
131 : }
132 136864481 : return (p);
133 : }
134 :
135 : /* ================================================================= */
136 :
137 135972129 : void SAL_CALL rtl_freeMemory_CUSTOM (void * p) SAL_THROW_EXTERN_C()
138 : {
139 135972129 : if (p != 0)
140 : {
141 135970417 : char * addr = (char*)(p) - RTL_MEMALIGN;
142 135970417 : sal_Size size = ((sal_Size*)(addr))[0];
143 :
144 135970417 : if (size <= RTL_MEMORY_CACHED_LIMIT)
145 135557163 : rtl_cache_free(g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT], addr);
146 : else
147 413254 : rtl_arena_free (gp_alloc_arena, addr, size);
148 : }
149 135972139 : }
150 :
151 : /* ================================================================= */
152 :
153 5554695 : void * SAL_CALL rtl_reallocateMemory_CUSTOM (void * p, sal_Size n) SAL_THROW_EXTERN_C()
154 : {
155 5554695 : if (n > 0)
156 : {
157 5554695 : if (p != 0)
158 : {
159 5554693 : void * p_old = p;
160 5554693 : sal_Size n_old = ((sal_Size*)( (char*)(p) - RTL_MEMALIGN ))[0] - RTL_MEMALIGN;
161 :
162 5554693 : p = rtl_allocateMemory (n);
163 5554693 : if (p != 0)
164 : {
165 5554693 : memcpy (p, p_old, (n < n_old) ? n : n_old);
166 5554693 : rtl_freeMemory (p_old);
167 : }
168 : }
169 : else
170 : {
171 2 : p = rtl_allocateMemory (n);
172 : }
173 : }
174 0 : else if (p != 0)
175 : {
176 0 : rtl_freeMemory (p), p = 0;
177 : }
178 5554695 : return (p);
179 : }
180 :
181 : #endif
182 :
183 : /* ================================================================= *
184 : *
185 : * custom allocator initialization / finalization.
186 : *
187 : * ================================================================= */
188 :
189 1608 : 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 1608 : );
205 : assert(gp_alloc_arena != 0);
206 : }
207 : {
208 : sal_Size size;
209 1608 : int i, n = RTL_MEMORY_CACHED_SIZES;
210 :
211 64320 : for (i = 0; i < n; i++)
212 : {
213 : char name[RTL_CACHE_NAME_LENGTH + 1];
214 62712 : (void) snprintf (name, sizeof(name), "rtl_alloc_%" SAL_PRIuUINTPTR, g_alloc_sizes[i]);
215 62712 : g_alloc_caches[i] = rtl_cache_create (name, g_alloc_sizes[i], 0, NULL, NULL, NULL, NULL, NULL, 0);
216 : }
217 :
218 1608 : size = RTL_MEMALIGN;
219 64320 : for (i = 0; i < n; i++)
220 : {
221 3418608 : while (size <= g_alloc_sizes[i])
222 : {
223 3293184 : g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT] = g_alloc_caches[i];
224 3293184 : size += RTL_MEMALIGN;
225 : }
226 : }
227 : }
228 : #endif
229 : // SAL_INFO("sal.rtl", "rtl_memory_init completed");
230 1608 : }
231 :
232 : /* ================================================================= */
233 :
234 1608 : void rtl_memory_fini()
235 : {
236 : #if !defined(FORCE_SYSALLOC)
237 : int i, n;
238 :
239 : /* clear g_alloc_table */
240 1608 : memset (g_alloc_table, 0, sizeof(g_alloc_table));
241 :
242 : /* cleanup g_alloc_caches */
243 64320 : for (i = 0, n = RTL_MEMORY_CACHED_SIZES; i < n; i++)
244 : {
245 62712 : if (g_alloc_caches[i] != 0)
246 : {
247 62712 : rtl_cache_destroy (g_alloc_caches[i]);
248 62712 : g_alloc_caches[i] = 0;
249 : }
250 : }
251 :
252 : /* cleanup gp_alloc_arena */
253 1608 : if (gp_alloc_arena != 0)
254 : {
255 1608 : rtl_arena_destroy (gp_alloc_arena);
256 1608 : gp_alloc_arena = 0;
257 : }
258 : #endif
259 : // SAL_INFO("sal.rtl", "rtl_memory_fini completed");
260 1608 : }
261 :
262 : /* ================================================================= *
263 : *
264 : * system allocator implemenation.
265 : *
266 : * ================================================================= */
267 :
268 58474255 : void * SAL_CALL rtl_allocateMemory_SYSTEM (sal_Size n)
269 : {
270 58474255 : return malloc (n);
271 : }
272 :
273 : /* ================================================================= */
274 :
275 58252925 : void SAL_CALL rtl_freeMemory_SYSTEM (void * p)
276 : {
277 58252925 : free (p);
278 58252925 : }
279 :
280 : /* ================================================================= */
281 :
282 375681 : void * SAL_CALL rtl_reallocateMemory_SYSTEM (void * p, sal_Size n)
283 : {
284 375681 : return realloc (p, n);
285 : }
286 :
287 : /* ================================================================= */
288 :
289 195338799 : 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 195340585 : if (alloc_mode == AMode_CUSTOM)
298 : {
299 136864534 : return rtl_allocateMemory_CUSTOM(n);
300 : }
301 58476051 : if (alloc_mode == AMode_SYSTEM)
302 : {
303 58474265 : return rtl_allocateMemory_SYSTEM(n);
304 : }
305 1786 : determine_alloc_mode();
306 1786 : }
307 : #else
308 : return rtl_allocateMemory_SYSTEM(n);
309 : #endif
310 : }
311 :
312 5930376 : 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 5930376 : if (alloc_mode == AMode_CUSTOM)
321 : {
322 5554695 : return rtl_reallocateMemory_CUSTOM(p,n);
323 : }
324 375681 : if (alloc_mode == AMode_SYSTEM)
325 : {
326 375681 : 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 194225030 : void SAL_CALL rtl_freeMemory (void * p) SAL_THROW_EXTERN_C()
336 : {
337 : #if !defined(FORCE_SYSALLOC)
338 : while (true)
339 : {
340 194225028 : if (alloc_mode == AMode_CUSTOM)
341 : {
342 135972121 : rtl_freeMemory_CUSTOM(p);
343 135972146 : return;
344 : }
345 58252907 : if (alloc_mode == AMode_SYSTEM)
346 : {
347 58252905 : rtl_freeMemory_SYSTEM(p);
348 58252904 : 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() implemenation.
360 : *
361 : * ================================================================= */
362 :
363 5510 : void * SAL_CALL rtl_allocateZeroMemory (sal_Size n) SAL_THROW_EXTERN_C()
364 : {
365 5510 : void * p = rtl_allocateMemory (n);
366 5510 : if (p != 0)
367 5499 : memset (p, 0, n);
368 5510 : return (p);
369 : }
370 :
371 : /* ================================================================= */
372 :
373 1533 : void SAL_CALL rtl_freeZeroMemory (void * p, sal_Size n) SAL_THROW_EXTERN_C()
374 : {
375 1533 : if (p != 0)
376 : {
377 1533 : memset (p, 0, n);
378 1533 : rtl_freeMemory (p);
379 : }
380 1533 : }
381 :
382 14 : void* SAL_CALL rtl_allocateAlignedMemory (sal_Size Alignment, sal_Size Bytes) SAL_THROW_EXTERN_C()
383 : {
384 14 : return osl_aligned_alloc(Alignment, Bytes);
385 : }
386 :
387 11 : void SAL_CALL rtl_freeAlignedMemory (void* Ptr) SAL_THROW_EXTERN_C()
388 : {
389 11 : osl_aligned_free(Ptr);
390 11 : }
391 :
392 : /* ================================================================= */
393 :
394 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|