xref: /aoo41x/main/sal/rtl/source/alloc_global.c (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
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.
14  *
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).
20  *
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.
25  *
26  ************************************************************************/
27 
28 #include "rtl/alloc.h"
29 #include "alloc_impl.h"
30 
31 #ifndef INCLUDED_STRING_H
32 #include <string.h>
33 #define INCLUDED_STRING_H
34 #endif
35 
36 #if !defined(FORCE_SYSALLOC)
37 
38 /* ================================================================= *
39  *
40  * custom allocator includes.
41  *
42  * ================================================================= */
43 
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"
51 
52 /* ================================================================= *
53  *
54  * custom allocator internals.
55  *
56  * ================================================================= */
57 
58 static const sal_Size g_alloc_sizes[] =
59 {
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
72 };
73 
74 #define RTL_MEMORY_CACHED_LIMIT 4 * 4096
75 #define RTL_MEMORY_CACHED_SIZES (sizeof(g_alloc_sizes) / sizeof(g_alloc_sizes[0]))
76 
77 static rtl_cache_type * g_alloc_caches[RTL_MEMORY_CACHED_SIZES] =
78 {
79 	0,
80 };
81 
82 #define RTL_MEMALIGN       8
83 #define RTL_MEMALIGN_SHIFT 3
84 
85 static rtl_cache_type * g_alloc_table[RTL_MEMORY_CACHED_LIMIT >> RTL_MEMALIGN_SHIFT] =
86 {
87 	0,
88 };
89 
90 static rtl_arena_type * gp_alloc_arena = 0;
91 
92 /* ================================================================= *
93  *
94  * custom allocator initialization / finalization.
95  *
96  * ================================================================= */
97 
98 static void
99 rtl_memory_once_init (void)
100 {
101 	{
102 		/* global memory arena */
103 		OSL_ASSERT(gp_alloc_arena == 0);
104 
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 */
113 		);
114 		OSL_ASSERT(gp_alloc_arena != 0);
115 	}
116 	{
117 		sal_Size size;
118 		int i, n = RTL_MEMORY_CACHED_SIZES;
119 
120 		for (i = 0; i < n; i++)
121 		{
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);
125 		}
126 
127 		size = RTL_MEMALIGN;
128 		for (i = 0; i < n; i++)
129 		{
130 			while (size <= g_alloc_sizes[i])
131 			{
132 				g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT] = g_alloc_caches[i];
133 				size += RTL_MEMALIGN;
134 			}
135 		}
136 	}
137 }
138 
139 static int
140 rtl_memory_init (void)
141 {
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);
145 }
146 
147 /* ================================================================= */
148 
149 /*
150   Issue http://udk.openoffice.org/issues/show_bug.cgi?id=92388
151 
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.
156 
157   Delegated the call to "rtl_memory_fini()" into a dummy C++ object,
158   see alloc_fini.cxx .
159 */
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 */
166 
167 void
168 rtl_memory_fini (void)
169 {
170 	int i, n;
171 
172 	/* clear g_alloc_table */
173 	memset (g_alloc_table, 0, sizeof(g_alloc_table));
174 
175 	/* cleanup g_alloc_caches */
176 	for (i = 0, n = RTL_MEMORY_CACHED_SIZES; i < n; i++)
177 	{
178 		if (g_alloc_caches[i] != 0)
179 		{
180 			rtl_cache_destroy (g_alloc_caches[i]);
181 			g_alloc_caches[i] = 0;
182 		}
183 	}
184 
185 	/* cleanup gp_alloc_arena */
186 	if (gp_alloc_arena != 0)
187 	{
188 		rtl_arena_destroy (gp_alloc_arena);
189 		gp_alloc_arena = 0;
190 	}
191 }
192 
193 /* ================================================================= *
194  *
195  * custom allocator implemenation.
196  *
197  * ================================================================= */
198 
199 void *
200 SAL_CALL rtl_allocateMemory (sal_Size n) SAL_THROW_EXTERN_C()
201 {
202 	void * p = 0;
203 	if (n > 0)
204 	{
205 		char *     addr;
206 		sal_Size   size = RTL_MEMORY_ALIGN(n + RTL_MEMALIGN, RTL_MEMALIGN);
207 
208 		OSL_ASSERT(RTL_MEMALIGN >= sizeof(sal_Size));
209 		if (n >= SAL_MAX_SIZE - (RTL_MEMALIGN + RTL_MEMALIGN - 1))
210 		{
211 			/* requested size too large for roundup alignment */
212 			return 0;
213 		}
214 
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);
220 
221 		if (addr != 0)
222 		{
223 			((sal_Size*)(addr))[0] = size;
224 			p = addr + RTL_MEMALIGN;
225 		}
226 		else if (gp_alloc_arena == 0)
227 		{
228 			if (rtl_memory_init())
229 			{
230 				/* try again */
231 				goto try_alloc;
232 			}
233 		}
234 	}
235 	return (p);
236 }
237 
238 /* ================================================================= */
239 
240 void SAL_CALL rtl_freeMemory (void * p) SAL_THROW_EXTERN_C()
241 {
242 	if (p != 0)
243 	{
244 		char *   addr = (char*)(p) - RTL_MEMALIGN;
245 		sal_Size size = ((sal_Size*)(addr))[0];
246 
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);
251 	}
252 }
253 
254 /* ================================================================= */
255 
256 void * SAL_CALL rtl_reallocateMemory (void * p, sal_Size n) SAL_THROW_EXTERN_C()
257 {
258 	if (n > 0)
259 	{
260 		if (p != 0)
261 		{
262 			void *   p_old = p;
263 			sal_Size n_old = ((sal_Size*)( (char*)(p) - RTL_MEMALIGN  ))[0] - RTL_MEMALIGN;
264 
265 			p = rtl_allocateMemory (n);
266 			if (p != 0)
267 			{
268 				memcpy (p, p_old, SAL_MIN(n, n_old));
269 				rtl_freeMemory (p_old);
270 			}
271 		}
272 		else
273 		{
274 			p = rtl_allocateMemory (n);
275 		}
276 	}
277 	else if (p != 0)
278 	{
279 		rtl_freeMemory (p), p = 0;
280 	}
281 	return (p);
282 }
283 
284 #else  /* FORCE_SYSALLOC */
285 
286 /* ================================================================= *
287  *
288  * system allocator includes.
289  *
290  * ================================================================= */
291 
292 #ifndef INCLUDED_STDLIB_H
293 #include <stdlib.h>
294 #define INCLUDED_STDLIB_H
295 #endif
296 
297 /* ================================================================= *
298  *
299  * system allocator implemenation.
300  *
301  * ================================================================= */
302 
303 void * SAL_CALL rtl_allocateMemory (sal_Size n)
304 {
305 	return malloc (n);
306 }
307 
308 /* ================================================================= */
309 
310 void SAL_CALL rtl_freeMemory (void * p)
311 {
312 	free (p);
313 }
314 
315 /* ================================================================= */
316 
317 void * SAL_CALL rtl_reallocateMemory (void * p, sal_Size n)
318 {
319 	return realloc (p, n);
320 }
321 
322 /* ================================================================= */
323 
324 void
325 rtl_memory_fini (void)
326 {
327 	/* nothing to do */
328 }
329 
330 #endif /* FORCE_SYSALLOC */
331 
332 /* ================================================================= *
333  *
334  * rtl_(allocate|free)ZeroMemory() implemenation.
335  *
336  * ================================================================= */
337 
338 void * SAL_CALL rtl_allocateZeroMemory (sal_Size n) SAL_THROW_EXTERN_C()
339 {
340 	void * p = rtl_allocateMemory (n);
341 	if (p != 0)
342 		memset (p, 0, n);
343 	return (p);
344 }
345 
346 /* ================================================================= */
347 
348 void SAL_CALL rtl_freeZeroMemory (void * p, sal_Size n) SAL_THROW_EXTERN_C()
349 {
350 	if (p != 0)
351 	{
352 		memset (p, 0, n);
353 		rtl_freeMemory (p);
354 	}
355 }
356 
357 /* ================================================================= */
358