merged tag ooo/DEV300_m102
[LibreOffice.git] / sal / rtl / source / alloc_global.c
blob5da66ca49d96157ac3391ee57fed860704640e72
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 #include "rtl/alloc.h"
29 #include "alloc_impl.h"
31 #ifndef INCLUDED_STRING_H
32 #include <string.h>
33 #define INCLUDED_STRING_H
34 #endif
36 #if !defined(FORCE_SYSALLOC)
38 /* ================================================================= *
40 * custom allocator includes.
42 * ================================================================= */
44 #ifndef INCLUDED_STDIO_H
45 #include <stdio.h>
46 #define INCLUDED_STDIO_H
47 #endif
48 #include "internal/once.h"
49 #include "sal/macros.h"
50 #include "osl/diagnose.h"
52 /* ================================================================= *
54 * custom allocator internals.
56 * ================================================================= */
58 static const sal_Size g_alloc_sizes[] =
60 /* powers of 2**(1/4) */
61 4 * 4, 6 * 4,
62 4 * 8, 5 * 8, 6 * 8, 7 * 8,
63 4 * 16, 5 * 16, 6 * 16, 7 * 16,
64 4 * 32, 5 * 32, 6 * 32, 7 * 32,
65 4 * 64, 5 * 64, 6 * 64, 7 * 64,
66 4 * 128, 5 * 128, 6 * 128, 7 * 128,
67 4 * 256, 5 * 256, 6 * 256, 7 * 256,
68 4 * 512, 5 * 512, 6 * 512, 7 * 512,
69 4 * 1024, 5 * 1024, 6 * 1024, 7 * 1024,
70 4 * 2048, 5 * 2048, 6 * 2048, 7 * 2048,
71 4 * 4096
74 #define RTL_MEMORY_CACHED_LIMIT 4 * 4096
75 #define RTL_MEMORY_CACHED_SIZES (sizeof(g_alloc_sizes) / sizeof(g_alloc_sizes[0]))
77 static rtl_cache_type * g_alloc_caches[RTL_MEMORY_CACHED_SIZES] =
82 #define RTL_MEMALIGN 8
83 #define RTL_MEMALIGN_SHIFT 3
85 static rtl_cache_type * g_alloc_table[RTL_MEMORY_CACHED_LIMIT >> RTL_MEMALIGN_SHIFT] =
90 static rtl_arena_type * gp_alloc_arena = 0;
92 /* ================================================================= *
94 * custom allocator initialization / finalization.
96 * ================================================================= */
98 static void
99 rtl_memory_once_init (void)
102 /* global memory arena */
103 OSL_ASSERT(gp_alloc_arena == 0);
105 gp_alloc_arena = rtl_arena_create (
106 "rtl_alloc_arena",
107 2048, /* quantum */
108 0, /* w/o quantum caching */
109 0, /* default source */
110 rtl_arena_alloc,
111 rtl_arena_free,
112 0 /* flags */
114 OSL_ASSERT(gp_alloc_arena != 0);
117 sal_Size size;
118 int i, n = RTL_MEMORY_CACHED_SIZES;
120 for (i = 0; i < n; i++)
122 char name[RTL_CACHE_NAME_LENGTH + 1];
123 (void) snprintf (name, sizeof(name), "rtl_alloc_%lu", g_alloc_sizes[i]);
124 g_alloc_caches[i] = rtl_cache_create (name, g_alloc_sizes[i], 0, NULL, NULL, NULL, NULL, NULL, 0);
127 size = RTL_MEMALIGN;
128 for (i = 0; i < n; i++)
130 while (size <= g_alloc_sizes[i])
132 g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT] = g_alloc_caches[i];
133 size += RTL_MEMALIGN;
139 static int
140 rtl_memory_init (void)
142 static sal_once_type g_once = SAL_ONCE_INIT;
143 SAL_ONCE(&g_once, rtl_memory_once_init);
144 return (gp_alloc_arena != 0);
147 /* ================================================================= */
150 Issue http://udk.openoffice.org/issues/show_bug.cgi?id=92388
152 Mac OS X does not seem to support "__cxa__atexit", thus leading
153 to the situation that "__attribute__((destructor))__" functions
154 (in particular "rtl_{memory|cache|arena}_fini") become called
155 _before_ global C++ object d'tors.
157 Delegated the call to "rtl_memory_fini()" into a dummy C++ object,
158 see alloc_fini.cxx .
160 #if defined(__GNUC__) && !defined(MACOSX)
161 static void rtl_memory_fini (void) __attribute__((destructor));
162 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
163 #pragma fini(rtl_memory_fini)
164 static void rtl_memory_fini (void);
165 #endif /* __GNUC__ || __SUNPRO_C */
167 void
168 rtl_memory_fini (void)
170 int i, n;
172 /* clear g_alloc_table */
173 memset (g_alloc_table, 0, sizeof(g_alloc_table));
175 /* cleanup g_alloc_caches */
176 for (i = 0, n = RTL_MEMORY_CACHED_SIZES; i < n; i++)
178 if (g_alloc_caches[i] != 0)
180 rtl_cache_destroy (g_alloc_caches[i]);
181 g_alloc_caches[i] = 0;
185 /* cleanup gp_alloc_arena */
186 if (gp_alloc_arena != 0)
188 rtl_arena_destroy (gp_alloc_arena);
189 gp_alloc_arena = 0;
193 /* ================================================================= *
195 * custom allocator implemenation.
197 * ================================================================= */
199 void *
200 SAL_CALL rtl_allocateMemory (sal_Size n) SAL_THROW_EXTERN_C()
202 void * p = 0;
203 if (n > 0)
205 char * addr;
206 sal_Size size = RTL_MEMORY_ALIGN(n + RTL_MEMALIGN, RTL_MEMALIGN);
208 OSL_ASSERT(RTL_MEMALIGN >= sizeof(sal_Size));
209 if (n >= SAL_MAX_SIZE - (RTL_MEMALIGN + RTL_MEMALIGN - 1))
211 /* requested size too large for roundup alignment */
212 return 0;
215 try_alloc:
216 if (size <= RTL_MEMORY_CACHED_LIMIT)
217 addr = (char*)rtl_cache_alloc(g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT]);
218 else
219 addr = (char*)rtl_arena_alloc (gp_alloc_arena, &size);
221 if (addr != 0)
223 ((sal_Size*)(addr))[0] = size;
224 p = addr + RTL_MEMALIGN;
226 else if (gp_alloc_arena == 0)
228 if (rtl_memory_init())
230 /* try again */
231 goto try_alloc;
235 return (p);
238 /* ================================================================= */
240 void SAL_CALL rtl_freeMemory (void * p) SAL_THROW_EXTERN_C()
242 if (p != 0)
244 char * addr = (char*)(p) - RTL_MEMALIGN;
245 sal_Size size = ((sal_Size*)(addr))[0];
247 if (size <= RTL_MEMORY_CACHED_LIMIT)
248 rtl_cache_free(g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT], addr);
249 else
250 rtl_arena_free (gp_alloc_arena, addr, size);
254 /* ================================================================= */
256 void * SAL_CALL rtl_reallocateMemory (void * p, sal_Size n) SAL_THROW_EXTERN_C()
258 if (n > 0)
260 if (p != 0)
262 void * p_old = p;
263 sal_Size n_old = ((sal_Size*)( (char*)(p) - RTL_MEMALIGN ))[0] - RTL_MEMALIGN;
265 p = rtl_allocateMemory (n);
266 if (p != 0)
268 memcpy (p, p_old, SAL_MIN(n, n_old));
269 rtl_freeMemory (p_old);
272 else
274 p = rtl_allocateMemory (n);
277 else if (p != 0)
279 rtl_freeMemory (p), p = 0;
281 return (p);
284 #else /* FORCE_SYSALLOC */
286 /* ================================================================= *
288 * system allocator includes.
290 * ================================================================= */
292 #ifndef INCLUDED_STDLIB_H
293 #include <stdlib.h>
294 #define INCLUDED_STDLIB_H
295 #endif
297 /* ================================================================= *
299 * system allocator implemenation.
301 * ================================================================= */
303 void * SAL_CALL rtl_allocateMemory (sal_Size n)
305 return malloc (n);
308 /* ================================================================= */
310 void SAL_CALL rtl_freeMemory (void * p)
312 free (p);
315 /* ================================================================= */
317 void * SAL_CALL rtl_reallocateMemory (void * p, sal_Size n)
319 return realloc (p, n);
322 /* ================================================================= */
324 void
325 rtl_memory_fini (void)
327 /* nothing to do */
330 #endif /* FORCE_SYSALLOC */
332 /* ================================================================= *
334 * rtl_(allocate|free)ZeroMemory() implemenation.
336 * ================================================================= */
338 void * SAL_CALL rtl_allocateZeroMemory (sal_Size n) SAL_THROW_EXTERN_C()
340 void * p = rtl_allocateMemory (n);
341 if (p != 0)
342 memset (p, 0, n);
343 return (p);
346 /* ================================================================= */
348 void SAL_CALL rtl_freeZeroMemory (void * p, sal_Size n) SAL_THROW_EXTERN_C()
350 if (p != 0)
352 memset (p, 0, n);
353 rtl_freeMemory (p);
357 /* ================================================================= */