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