1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #include "rtl/alloc.h" 25 #include "alloc_impl.h" 26 27 #ifndef INCLUDED_STRING_H 28 #include <string.h> 29 #define INCLUDED_STRING_H 30 #endif 31 32 #if !defined(FORCE_SYSALLOC) 33 34 /* ================================================================= * 35 * 36 * custom allocator includes. 37 * 38 * ================================================================= */ 39 40 #ifndef INCLUDED_STDIO_H 41 #include <stdio.h> 42 #define INCLUDED_STDIO_H 43 #endif 44 #include "internal/once.h" 45 #include "sal/macros.h" 46 #include "osl/diagnose.h" 47 48 /* ================================================================= * 49 * 50 * custom allocator internals. 51 * 52 * ================================================================= */ 53 54 static const sal_Size g_alloc_sizes[] = 55 { 56 /* powers of 2**(1/4) */ 57 4 * 4, 6 * 4, 58 4 * 8, 5 * 8, 6 * 8, 7 * 8, 59 4 * 16, 5 * 16, 6 * 16, 7 * 16, 60 4 * 32, 5 * 32, 6 * 32, 7 * 32, 61 4 * 64, 5 * 64, 6 * 64, 7 * 64, 62 4 * 128, 5 * 128, 6 * 128, 7 * 128, 63 4 * 256, 5 * 256, 6 * 256, 7 * 256, 64 4 * 512, 5 * 512, 6 * 512, 7 * 512, 65 4 * 1024, 5 * 1024, 6 * 1024, 7 * 1024, 66 4 * 2048, 5 * 2048, 6 * 2048, 7 * 2048, 67 4 * 4096 68 }; 69 70 #define RTL_MEMORY_CACHED_LIMIT 4 * 4096 71 #define RTL_MEMORY_CACHED_SIZES (sizeof(g_alloc_sizes) / sizeof(g_alloc_sizes[0])) 72 73 static rtl_cache_type * g_alloc_caches[RTL_MEMORY_CACHED_SIZES] = 74 { 75 0, 76 }; 77 78 #ifdef NEED_ALIGN16 79 #define RTL_MEMALIGN 16 80 #define RTL_MEMALIGN_SHIFT 4 81 #else 82 #define RTL_MEMALIGN 8 83 #define RTL_MEMALIGN_SHIFT 3 84 #endif 85 86 static rtl_cache_type * g_alloc_table[RTL_MEMORY_CACHED_LIMIT >> RTL_MEMALIGN_SHIFT] = 87 { 88 0, 89 }; 90 91 static rtl_arena_type * gp_alloc_arena = NULL; 92 93 /* ================================================================= * 94 * 95 * custom allocator initialization / finalization. 96 * 97 * ================================================================= */ 98 99 static void 100 rtl_memory_once_init (void) 101 { 102 { 103 /* global memory arena */ 104 OSL_ASSERT(gp_alloc_arena == NULL); 105 106 gp_alloc_arena = rtl_arena_create ( 107 "rtl_alloc_arena", 108 2048, /* quantum */ 109 0, /* w/o quantum caching */ 110 0, /* default source */ 111 rtl_arena_alloc, 112 rtl_arena_free, 113 0 /* flags */ 114 ); 115 OSL_ASSERT(gp_alloc_arena != NULL); 116 } 117 { 118 sal_Size size; 119 int i, n = RTL_MEMORY_CACHED_SIZES; 120 121 for (i = 0; i < n; i++) 122 { 123 char name[RTL_CACHE_NAME_LENGTH + 1]; 124 (void) snprintf (name, sizeof(name), "rtl_alloc_%lu", g_alloc_sizes[i]); 125 g_alloc_caches[i] = rtl_cache_create (name, g_alloc_sizes[i], 0, NULL, NULL, NULL, NULL, NULL, 0); 126 } 127 128 size = RTL_MEMALIGN; 129 for (i = 0; i < n; i++) 130 { 131 while (size <= g_alloc_sizes[i]) 132 { 133 g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT] = g_alloc_caches[i]; 134 size += RTL_MEMALIGN; 135 } 136 } 137 } 138 } 139 140 static int 141 rtl_memory_init (void) 142 { 143 static sal_once_type g_once = SAL_ONCE_INIT; 144 SAL_ONCE(&g_once, rtl_memory_once_init); 145 return (gp_alloc_arena != NULL); 146 } 147 148 /* ================================================================= */ 149 150 /* 151 Issue http://udk.openoffice.org/issues/show_bug.cgi?id=92388 152 153 Mac OS X does not seem to support "__cxa__atexit", thus leading 154 to the situation that "__attribute__((destructor))__" functions 155 (in particular "rtl_{memory|cache|arena}_fini") become called 156 _before_ global C++ object d'tors. 157 158 Delegated the call to "rtl_memory_fini()" into a dummy C++ object, 159 see alloc_fini.cxx . 160 */ 161 #if defined(__GNUC__) && !defined(MACOSX) 162 static void rtl_memory_fini (void) __attribute__((destructor)); 163 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) 164 #pragma fini(rtl_memory_fini) 165 static void rtl_memory_fini (void); 166 #endif /* __GNUC__ || __SUNPRO_C */ 167 168 void 169 rtl_memory_fini (void) 170 { 171 int i, n; 172 173 /* clear g_alloc_table */ 174 memset (g_alloc_table, 0, sizeof(g_alloc_table)); 175 176 /* cleanup g_alloc_caches */ 177 for (i = 0, n = RTL_MEMORY_CACHED_SIZES; i < n; i++) 178 { 179 if (g_alloc_caches[i] != NULL) 180 { 181 rtl_cache_destroy (g_alloc_caches[i]); 182 g_alloc_caches[i] = NULL; 183 } 184 } 185 186 /* cleanup gp_alloc_arena */ 187 if (gp_alloc_arena != NULL) 188 { 189 rtl_arena_destroy (gp_alloc_arena); 190 gp_alloc_arena = NULL; 191 } 192 } 193 194 /* ================================================================= * 195 * 196 * custom allocator implemenation. 197 * 198 * ================================================================= */ 199 200 void * 201 SAL_CALL rtl_allocateMemory (sal_Size n) SAL_THROW_EXTERN_C() 202 { 203 void * p = 0; 204 if (n > 0) 205 { 206 char * addr; 207 sal_Size size = RTL_MEMORY_ALIGN(n + RTL_MEMALIGN, RTL_MEMALIGN); 208 209 OSL_ASSERT(RTL_MEMALIGN >= sizeof(sal_Size)); 210 if (n >= SAL_MAX_SIZE - (RTL_MEMALIGN + RTL_MEMALIGN - 1)) 211 { 212 /* requested size too large for roundup alignment */ 213 return 0; 214 } 215 216 try_alloc: 217 if (size <= RTL_MEMORY_CACHED_LIMIT) 218 addr = (char*)rtl_cache_alloc(g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT]); 219 else 220 addr = (char*)rtl_arena_alloc (gp_alloc_arena, &size); 221 222 if (addr != 0) 223 { 224 ((sal_Size*)(addr))[0] = size; 225 p = addr + RTL_MEMALIGN; 226 } 227 else if (gp_alloc_arena == 0) 228 { 229 if (rtl_memory_init()) 230 { 231 /* try again */ 232 goto try_alloc; 233 } 234 } 235 } 236 return (p); 237 } 238 239 /* ================================================================= */ 240 241 void SAL_CALL rtl_freeMemory (void * p) SAL_THROW_EXTERN_C() 242 { 243 if (p != 0) 244 { 245 char * addr = (char*)(p) - RTL_MEMALIGN; 246 sal_Size size = ((sal_Size*)(addr))[0]; 247 248 if (size <= RTL_MEMORY_CACHED_LIMIT) 249 rtl_cache_free(g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT], addr); 250 else 251 rtl_arena_free (gp_alloc_arena, addr, size); 252 } 253 } 254 255 /* ================================================================= */ 256 257 void * SAL_CALL rtl_reallocateMemory (void * p, sal_Size n) SAL_THROW_EXTERN_C() 258 { 259 if (n > 0) 260 { 261 if (p != 0) 262 { 263 void * p_old = p; 264 sal_Size n_old = ((sal_Size*)( (char*)(p) - RTL_MEMALIGN ))[0] - RTL_MEMALIGN; 265 266 p = rtl_allocateMemory (n); 267 if (p != 0) 268 { 269 memcpy (p, p_old, SAL_MIN(n, n_old)); 270 rtl_freeMemory (p_old); 271 } 272 } 273 else 274 { 275 p = rtl_allocateMemory (n); 276 } 277 } 278 else if (p != 0) 279 { 280 rtl_freeMemory (p), p = 0; 281 } 282 return (p); 283 } 284 285 #else /* FORCE_SYSALLOC */ 286 287 /* ================================================================= * 288 * 289 * system allocator includes. 290 * 291 * ================================================================= */ 292 293 #ifndef INCLUDED_STDLIB_H 294 #include <stdlib.h> 295 #define INCLUDED_STDLIB_H 296 #endif 297 298 /* ================================================================= * 299 * 300 * system allocator implemenation. 301 * 302 * ================================================================= */ 303 304 void * SAL_CALL rtl_allocateMemory (sal_Size n) 305 { 306 return malloc (n); 307 } 308 309 /* ================================================================= */ 310 311 void SAL_CALL rtl_freeMemory (void * p) 312 { 313 free (p); 314 } 315 316 /* ================================================================= */ 317 318 void * SAL_CALL rtl_reallocateMemory (void * p, sal_Size n) 319 { 320 return realloc (p, n); 321 } 322 323 /* ================================================================= */ 324 325 void 326 rtl_memory_fini (void) 327 { 328 /* nothing to do */ 329 } 330 331 #endif /* FORCE_SYSALLOC */ 332 333 /* ================================================================= * 334 * 335 * rtl_(allocate|free)ZeroMemory() implemenation. 336 * 337 * ================================================================= */ 338 339 void * SAL_CALL rtl_allocateZeroMemory (sal_Size n) SAL_THROW_EXTERN_C() 340 { 341 void * p = rtl_allocateMemory (n); 342 if (p != 0) 343 memset (p, 0, n); 344 return (p); 345 } 346 347 /* ================================================================= */ 348 349 void SAL_CALL rtl_freeZeroMemory (void * p, sal_Size n) SAL_THROW_EXTERN_C() 350 { 351 if (p != 0) 352 { 353 memset (p, 0, n); 354 rtl_freeMemory (p); 355 } 356 } 357 358 /* ================================================================= */ 359