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 #define RTL_MEMALIGN 8 79 #define RTL_MEMALIGN_SHIFT 3 80 81 static rtl_cache_type * g_alloc_table[RTL_MEMORY_CACHED_LIMIT >> RTL_MEMALIGN_SHIFT] = 82 { 83 0, 84 }; 85 86 static rtl_arena_type * gp_alloc_arena = 0; 87 88 /* ================================================================= * 89 * 90 * custom allocator initialization / finalization. 91 * 92 * ================================================================= */ 93 94 static void 95 rtl_memory_once_init (void) 96 { 97 { 98 /* global memory arena */ 99 OSL_ASSERT(gp_alloc_arena == 0); 100 101 gp_alloc_arena = rtl_arena_create ( 102 "rtl_alloc_arena", 103 2048, /* quantum */ 104 0, /* w/o quantum caching */ 105 0, /* default source */ 106 rtl_arena_alloc, 107 rtl_arena_free, 108 0 /* flags */ 109 ); 110 OSL_ASSERT(gp_alloc_arena != 0); 111 } 112 { 113 sal_Size size; 114 int i, n = RTL_MEMORY_CACHED_SIZES; 115 116 for (i = 0; i < n; i++) 117 { 118 char name[RTL_CACHE_NAME_LENGTH + 1]; 119 (void) snprintf (name, sizeof(name), "rtl_alloc_%lu", g_alloc_sizes[i]); 120 g_alloc_caches[i] = rtl_cache_create (name, g_alloc_sizes[i], 0, NULL, NULL, NULL, NULL, NULL, 0); 121 } 122 123 size = RTL_MEMALIGN; 124 for (i = 0; i < n; i++) 125 { 126 while (size <= g_alloc_sizes[i]) 127 { 128 g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT] = g_alloc_caches[i]; 129 size += RTL_MEMALIGN; 130 } 131 } 132 } 133 } 134 135 static int 136 rtl_memory_init (void) 137 { 138 static sal_once_type g_once = SAL_ONCE_INIT; 139 SAL_ONCE(&g_once, rtl_memory_once_init); 140 return (gp_alloc_arena != 0); 141 } 142 143 /* ================================================================= */ 144 145 /* 146 Issue http://udk.openoffice.org/issues/show_bug.cgi?id=92388 147 148 Mac OS X does not seem to support "__cxa__atexit", thus leading 149 to the situation that "__attribute__((destructor))__" functions 150 (in particular "rtl_{memory|cache|arena}_fini") become called 151 _before_ global C++ object d'tors. 152 153 Delegated the call to "rtl_memory_fini()" into a dummy C++ object, 154 see alloc_fini.cxx . 155 */ 156 #if defined(__GNUC__) && !defined(MACOSX) 157 static void rtl_memory_fini (void) __attribute__((destructor)); 158 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) 159 #pragma fini(rtl_memory_fini) 160 static void rtl_memory_fini (void); 161 #endif /* __GNUC__ || __SUNPRO_C */ 162 163 void 164 rtl_memory_fini (void) 165 { 166 int i, n; 167 168 /* clear g_alloc_table */ 169 memset (g_alloc_table, 0, sizeof(g_alloc_table)); 170 171 /* cleanup g_alloc_caches */ 172 for (i = 0, n = RTL_MEMORY_CACHED_SIZES; i < n; i++) 173 { 174 if (g_alloc_caches[i] != 0) 175 { 176 rtl_cache_destroy (g_alloc_caches[i]); 177 g_alloc_caches[i] = 0; 178 } 179 } 180 181 /* cleanup gp_alloc_arena */ 182 if (gp_alloc_arena != 0) 183 { 184 rtl_arena_destroy (gp_alloc_arena); 185 gp_alloc_arena = 0; 186 } 187 } 188 189 /* ================================================================= * 190 * 191 * custom allocator implemenation. 192 * 193 * ================================================================= */ 194 195 void * 196 SAL_CALL rtl_allocateMemory (sal_Size n) SAL_THROW_EXTERN_C() 197 { 198 void * p = 0; 199 if (n > 0) 200 { 201 char * addr; 202 sal_Size size = RTL_MEMORY_ALIGN(n + RTL_MEMALIGN, RTL_MEMALIGN); 203 204 OSL_ASSERT(RTL_MEMALIGN >= sizeof(sal_Size)); 205 if (n >= SAL_MAX_SIZE - (RTL_MEMALIGN + RTL_MEMALIGN - 1)) 206 { 207 /* requested size too large for roundup alignment */ 208 return 0; 209 } 210 211 try_alloc: 212 if (size <= RTL_MEMORY_CACHED_LIMIT) 213 addr = (char*)rtl_cache_alloc(g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT]); 214 else 215 addr = (char*)rtl_arena_alloc (gp_alloc_arena, &size); 216 217 if (addr != 0) 218 { 219 ((sal_Size*)(addr))[0] = size; 220 p = addr + RTL_MEMALIGN; 221 } 222 else if (gp_alloc_arena == 0) 223 { 224 if (rtl_memory_init()) 225 { 226 /* try again */ 227 goto try_alloc; 228 } 229 } 230 } 231 return (p); 232 } 233 234 /* ================================================================= */ 235 236 void SAL_CALL rtl_freeMemory (void * p) SAL_THROW_EXTERN_C() 237 { 238 if (p != 0) 239 { 240 char * addr = (char*)(p) - RTL_MEMALIGN; 241 sal_Size size = ((sal_Size*)(addr))[0]; 242 243 if (size <= RTL_MEMORY_CACHED_LIMIT) 244 rtl_cache_free(g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT], addr); 245 else 246 rtl_arena_free (gp_alloc_arena, addr, size); 247 } 248 } 249 250 /* ================================================================= */ 251 252 void * SAL_CALL rtl_reallocateMemory (void * p, sal_Size n) SAL_THROW_EXTERN_C() 253 { 254 if (n > 0) 255 { 256 if (p != 0) 257 { 258 void * p_old = p; 259 sal_Size n_old = ((sal_Size*)( (char*)(p) - RTL_MEMALIGN ))[0] - RTL_MEMALIGN; 260 261 p = rtl_allocateMemory (n); 262 if (p != 0) 263 { 264 memcpy (p, p_old, SAL_MIN(n, n_old)); 265 rtl_freeMemory (p_old); 266 } 267 } 268 else 269 { 270 p = rtl_allocateMemory (n); 271 } 272 } 273 else if (p != 0) 274 { 275 rtl_freeMemory (p), p = 0; 276 } 277 return (p); 278 } 279 280 #else /* FORCE_SYSALLOC */ 281 282 /* ================================================================= * 283 * 284 * system allocator includes. 285 * 286 * ================================================================= */ 287 288 #ifndef INCLUDED_STDLIB_H 289 #include <stdlib.h> 290 #define INCLUDED_STDLIB_H 291 #endif 292 293 /* ================================================================= * 294 * 295 * system allocator implemenation. 296 * 297 * ================================================================= */ 298 299 void * SAL_CALL rtl_allocateMemory (sal_Size n) 300 { 301 return malloc (n); 302 } 303 304 /* ================================================================= */ 305 306 void SAL_CALL rtl_freeMemory (void * p) 307 { 308 free (p); 309 } 310 311 /* ================================================================= */ 312 313 void * SAL_CALL rtl_reallocateMemory (void * p, sal_Size n) 314 { 315 return realloc (p, n); 316 } 317 318 /* ================================================================= */ 319 320 void 321 rtl_memory_fini (void) 322 { 323 /* nothing to do */ 324 } 325 326 #endif /* FORCE_SYSALLOC */ 327 328 /* ================================================================= * 329 * 330 * rtl_(allocate|free)ZeroMemory() implemenation. 331 * 332 * ================================================================= */ 333 334 void * SAL_CALL rtl_allocateZeroMemory (sal_Size n) SAL_THROW_EXTERN_C() 335 { 336 void * p = rtl_allocateMemory (n); 337 if (p != 0) 338 memset (p, 0, n); 339 return (p); 340 } 341 342 /* ================================================================= */ 343 344 void SAL_CALL rtl_freeZeroMemory (void * p, sal_Size n) SAL_THROW_EXTERN_C() 345 { 346 if (p != 0) 347 { 348 memset (p, 0, n); 349 rtl_freeMemory (p); 350 } 351 } 352 353 /* ================================================================= */ 354