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