1647f063dSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3647f063dSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4647f063dSAndrew Rist * or more contributor license agreements. See the NOTICE file 5647f063dSAndrew Rist * distributed with this work for additional information 6647f063dSAndrew Rist * regarding copyright ownership. The ASF licenses this file 7647f063dSAndrew Rist * to you under the Apache License, Version 2.0 (the 8647f063dSAndrew Rist * "License"); you may not use this file except in compliance 9647f063dSAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11647f063dSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13647f063dSAndrew Rist * Unless required by applicable law or agreed to in writing, 14647f063dSAndrew Rist * software distributed under the License is distributed on an 15647f063dSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16647f063dSAndrew Rist * KIND, either express or implied. See the License for the 17647f063dSAndrew Rist * specific language governing permissions and limitations 18647f063dSAndrew Rist * under the License. 19cdf0e10cSrcweir * 20647f063dSAndrew Rist *************************************************************/ 21647f063dSAndrew Rist 22647f063dSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir #include "alloc_cache.h" 25cdf0e10cSrcweir #include "alloc_impl.h" 26cdf0e10cSrcweir #include "alloc_arena.h" 27cdf0e10cSrcweir #include "internal/once.h" 28cdf0e10cSrcweir #include "sal/macros.h" 29cdf0e10cSrcweir #include "osl/diagnose.h" 30cdf0e10cSrcweir 31cdf0e10cSrcweir #ifndef INCLUDED_STRING_H 32cdf0e10cSrcweir #include <string.h> 33cdf0e10cSrcweir #endif 34cdf0e10cSrcweir 35cdf0e10cSrcweir #ifndef INCLUDED_STDIO_H 36cdf0e10cSrcweir #include <stdio.h> 37cdf0e10cSrcweir #endif 38cdf0e10cSrcweir 39cdf0e10cSrcweir #ifdef OS2 40cdf0e10cSrcweir #undef OSL_TRACE 41cdf0e10cSrcweir #define OSL_TRACE 1 ? ((void)0) : _OSL_GLOBAL osl_trace 42*87c0c1b4SYuri Dario 43*87c0c1b4SYuri Dario #define INCL_DOS 44*87c0c1b4SYuri Dario #include <os2.h> 45*87c0c1b4SYuri Dario 46cdf0e10cSrcweir #endif 47cdf0e10cSrcweir 48cdf0e10cSrcweir /* ================================================================= * 49cdf0e10cSrcweir * 50cdf0e10cSrcweir * cache internals. 51cdf0e10cSrcweir * 52cdf0e10cSrcweir * ================================================================= */ 53cdf0e10cSrcweir 54cdf0e10cSrcweir /** g_cache_list 55cdf0e10cSrcweir * @internal 56cdf0e10cSrcweir */ 57cdf0e10cSrcweir struct rtl_cache_list_st 58cdf0e10cSrcweir { 59cdf0e10cSrcweir rtl_memory_lock_type m_lock; 60cdf0e10cSrcweir rtl_cache_type m_cache_head; 61cdf0e10cSrcweir 62*87c0c1b4SYuri Dario #if defined(SAL_UNX) 63cdf0e10cSrcweir pthread_t m_update_thread; 64cdf0e10cSrcweir pthread_cond_t m_update_cond; 65*87c0c1b4SYuri Dario #elif defined(SAL_OS2) 66*87c0c1b4SYuri Dario TID m_update_thread; 67*87c0c1b4SYuri Dario HEV m_update_cond; 68cdf0e10cSrcweir #elif defined(SAL_W32) 69cdf0e10cSrcweir HANDLE m_update_thread; 70cdf0e10cSrcweir HANDLE m_update_cond; 71cdf0e10cSrcweir #endif /* SAL_UNX || SAL_W32 */ 72cdf0e10cSrcweir int m_update_done; 73cdf0e10cSrcweir }; 74cdf0e10cSrcweir 75cdf0e10cSrcweir static struct rtl_cache_list_st g_cache_list; 76cdf0e10cSrcweir 77cdf0e10cSrcweir 78cdf0e10cSrcweir /** gp_cache_arena 79cdf0e10cSrcweir * provided for cache_type allocations, and hash_table resizing. 80cdf0e10cSrcweir * 81cdf0e10cSrcweir * @internal 82cdf0e10cSrcweir */ 83cdf0e10cSrcweir static rtl_arena_type * gp_cache_arena = 0; 84cdf0e10cSrcweir 85cdf0e10cSrcweir 86cdf0e10cSrcweir /** gp_cache_magazine_cache 87cdf0e10cSrcweir * @internal 88cdf0e10cSrcweir */ 89cdf0e10cSrcweir static rtl_cache_type * gp_cache_magazine_cache = 0; 90cdf0e10cSrcweir 91cdf0e10cSrcweir 92cdf0e10cSrcweir /** gp_cache_slab_cache 93cdf0e10cSrcweir * @internal 94cdf0e10cSrcweir */ 95cdf0e10cSrcweir static rtl_cache_type * gp_cache_slab_cache = 0; 96cdf0e10cSrcweir 97cdf0e10cSrcweir 98cdf0e10cSrcweir /** gp_cache_bufctl_cache 99cdf0e10cSrcweir * @internal 100cdf0e10cSrcweir */ 101cdf0e10cSrcweir static rtl_cache_type * gp_cache_bufctl_cache = 0; 102cdf0e10cSrcweir 103cdf0e10cSrcweir 104cdf0e10cSrcweir /** rtl_cache_init() 105cdf0e10cSrcweir * @internal 106cdf0e10cSrcweir */ 107cdf0e10cSrcweir static int 108cdf0e10cSrcweir rtl_cache_init (void); 109cdf0e10cSrcweir 110cdf0e10cSrcweir 111cdf0e10cSrcweir /* ================================================================= */ 112cdf0e10cSrcweir 113cdf0e10cSrcweir /** RTL_CACHE_HASH_INDEX() 114cdf0e10cSrcweir */ 115cdf0e10cSrcweir #define RTL_CACHE_HASH_INDEX_IMPL(a, s, q, m) \ 116cdf0e10cSrcweir ((((a) + ((a) >> (s)) + ((a) >> ((s) << 1))) >> (q)) & (m)) 117cdf0e10cSrcweir 118cdf0e10cSrcweir #define RTL_CACHE_HASH_INDEX(cache, addr) \ 119cdf0e10cSrcweir RTL_CACHE_HASH_INDEX_IMPL((addr), (cache)->m_hash_shift, (cache)->m_type_shift, ((cache)->m_hash_size - 1)) 120cdf0e10cSrcweir 121cdf0e10cSrcweir 122cdf0e10cSrcweir /** rtl_cache_hash_rescale() 123cdf0e10cSrcweir */ 124cdf0e10cSrcweir static void 125cdf0e10cSrcweir rtl_cache_hash_rescale ( 126cdf0e10cSrcweir rtl_cache_type * cache, 127cdf0e10cSrcweir sal_Size new_size 128cdf0e10cSrcweir ) 129cdf0e10cSrcweir { 130cdf0e10cSrcweir rtl_cache_bufctl_type ** new_table; 131cdf0e10cSrcweir sal_Size new_bytes; 132cdf0e10cSrcweir 133cdf0e10cSrcweir new_bytes = new_size * sizeof(rtl_cache_bufctl_type*); 134cdf0e10cSrcweir new_table = (rtl_cache_bufctl_type**)rtl_arena_alloc(gp_cache_arena, &new_bytes); 135cdf0e10cSrcweir 136cdf0e10cSrcweir if (new_table != 0) 137cdf0e10cSrcweir { 138cdf0e10cSrcweir rtl_cache_bufctl_type ** old_table; 139cdf0e10cSrcweir sal_Size old_size, i; 140cdf0e10cSrcweir 141cdf0e10cSrcweir memset (new_table, 0, new_bytes); 142cdf0e10cSrcweir 143cdf0e10cSrcweir RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_slab_lock)); 144cdf0e10cSrcweir 145cdf0e10cSrcweir old_table = cache->m_hash_table; 146cdf0e10cSrcweir old_size = cache->m_hash_size; 147cdf0e10cSrcweir 148cdf0e10cSrcweir OSL_TRACE( 149cdf0e10cSrcweir "rtl_cache_hash_rescale(\"%s\"): " 150cdf0e10cSrcweir "nbuf: % " PRIu64 " (ave: %" PRIu64 "), frees: %" PRIu64 " " 151cdf0e10cSrcweir "[old_size: %lu, new_size: %lu]", 152cdf0e10cSrcweir cache->m_name, 153cdf0e10cSrcweir cache->m_slab_stats.m_alloc - cache->m_slab_stats.m_free, 154cdf0e10cSrcweir (cache->m_slab_stats.m_alloc - cache->m_slab_stats.m_free) >> cache->m_hash_shift, 155cdf0e10cSrcweir cache->m_slab_stats.m_free, 156cdf0e10cSrcweir old_size, new_size); 157cdf0e10cSrcweir 158cdf0e10cSrcweir cache->m_hash_table = new_table; 159cdf0e10cSrcweir cache->m_hash_size = new_size; 160cdf0e10cSrcweir cache->m_hash_shift = highbit(cache->m_hash_size) - 1; 161cdf0e10cSrcweir 162cdf0e10cSrcweir for (i = 0; i < old_size; i++) 163cdf0e10cSrcweir { 164cdf0e10cSrcweir rtl_cache_bufctl_type * curr = old_table[i]; 165cdf0e10cSrcweir while (curr != 0) 166cdf0e10cSrcweir { 167cdf0e10cSrcweir rtl_cache_bufctl_type * next = curr->m_next; 168cdf0e10cSrcweir rtl_cache_bufctl_type ** head; 169cdf0e10cSrcweir 170cdf0e10cSrcweir head = &(cache->m_hash_table[RTL_CACHE_HASH_INDEX(cache, curr->m_addr)]); 171cdf0e10cSrcweir curr->m_next = (*head); 172cdf0e10cSrcweir (*head) = curr; 173cdf0e10cSrcweir 174cdf0e10cSrcweir curr = next; 175cdf0e10cSrcweir } 176cdf0e10cSrcweir old_table[i] = 0; 177cdf0e10cSrcweir } 178cdf0e10cSrcweir 179cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(cache->m_slab_lock)); 180cdf0e10cSrcweir 181cdf0e10cSrcweir if (old_table != cache->m_hash_table_0) 182cdf0e10cSrcweir { 183cdf0e10cSrcweir sal_Size old_bytes = old_size * sizeof(rtl_cache_bufctl_type*); 184cdf0e10cSrcweir rtl_arena_free (gp_cache_arena, old_table, old_bytes); 185cdf0e10cSrcweir } 186cdf0e10cSrcweir } 187cdf0e10cSrcweir } 188cdf0e10cSrcweir 189cdf0e10cSrcweir /** rtl_cache_hash_insert() 190cdf0e10cSrcweir */ 191cdf0e10cSrcweir static RTL_MEMORY_INLINE sal_uIntPtr 192cdf0e10cSrcweir rtl_cache_hash_insert ( 193cdf0e10cSrcweir rtl_cache_type * cache, 194cdf0e10cSrcweir rtl_cache_bufctl_type * bufctl 195cdf0e10cSrcweir ) 196cdf0e10cSrcweir { 197cdf0e10cSrcweir rtl_cache_bufctl_type ** ppHead; 198cdf0e10cSrcweir 199cdf0e10cSrcweir ppHead = &(cache->m_hash_table[RTL_CACHE_HASH_INDEX(cache, bufctl->m_addr)]); 200cdf0e10cSrcweir 201cdf0e10cSrcweir bufctl->m_next = (*ppHead); 202cdf0e10cSrcweir (*ppHead) = bufctl; 203cdf0e10cSrcweir 204cdf0e10cSrcweir return (bufctl->m_addr); 205cdf0e10cSrcweir } 206cdf0e10cSrcweir 207cdf0e10cSrcweir #if defined(__SUNPRO_C) || defined(__SUNPRO_CC) 208cdf0e10cSrcweir #pragma inline(rtl_cache_hash_insert) 209cdf0e10cSrcweir #endif /* __SUNPRO_C */ 210cdf0e10cSrcweir 211cdf0e10cSrcweir 212cdf0e10cSrcweir /** rtl_cache_hash_remove() 213cdf0e10cSrcweir */ 214cdf0e10cSrcweir static rtl_cache_bufctl_type * 215cdf0e10cSrcweir rtl_cache_hash_remove ( 216cdf0e10cSrcweir rtl_cache_type * cache, 217cdf0e10cSrcweir sal_uIntPtr addr 218cdf0e10cSrcweir ) 219cdf0e10cSrcweir { 220cdf0e10cSrcweir rtl_cache_bufctl_type ** ppHead; 221cdf0e10cSrcweir rtl_cache_bufctl_type * bufctl; 222cdf0e10cSrcweir sal_Size lookups = 0; 223cdf0e10cSrcweir 224cdf0e10cSrcweir ppHead = &(cache->m_hash_table[RTL_CACHE_HASH_INDEX(cache, addr)]); 225cdf0e10cSrcweir while ((bufctl = *ppHead) != 0) 226cdf0e10cSrcweir { 227cdf0e10cSrcweir if (bufctl->m_addr == addr) 228cdf0e10cSrcweir { 229cdf0e10cSrcweir *ppHead = bufctl->m_next, bufctl->m_next = 0; 230cdf0e10cSrcweir break; 231cdf0e10cSrcweir } 232cdf0e10cSrcweir 233cdf0e10cSrcweir lookups += 1; 234cdf0e10cSrcweir ppHead = &(bufctl->m_next); 235cdf0e10cSrcweir } 236cdf0e10cSrcweir 237cdf0e10cSrcweir OSL_ASSERT (bufctl != 0); /* bad free */ 238cdf0e10cSrcweir 239cdf0e10cSrcweir if (lookups > 1) 240cdf0e10cSrcweir { 241cdf0e10cSrcweir sal_Size nbuf = (sal_Size)(cache->m_slab_stats.m_alloc - cache->m_slab_stats.m_free); 242cdf0e10cSrcweir if (nbuf > 4 * cache->m_hash_size) 243cdf0e10cSrcweir { 244cdf0e10cSrcweir if (!(cache->m_features & RTL_CACHE_FEATURE_RESCALE)) 245cdf0e10cSrcweir { 246cdf0e10cSrcweir sal_Size ave = nbuf >> cache->m_hash_shift; 247cdf0e10cSrcweir sal_Size new_size = cache->m_hash_size << (highbit(ave) - 1); 248cdf0e10cSrcweir 249cdf0e10cSrcweir cache->m_features |= RTL_CACHE_FEATURE_RESCALE; 250cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(cache->m_slab_lock)); 251cdf0e10cSrcweir rtl_cache_hash_rescale (cache, new_size); 252cdf0e10cSrcweir RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_slab_lock)); 253cdf0e10cSrcweir cache->m_features &= ~RTL_CACHE_FEATURE_RESCALE; 254cdf0e10cSrcweir } 255cdf0e10cSrcweir } 256cdf0e10cSrcweir } 257cdf0e10cSrcweir 258cdf0e10cSrcweir return (bufctl); 259cdf0e10cSrcweir } 260cdf0e10cSrcweir 261cdf0e10cSrcweir /* ================================================================= */ 262cdf0e10cSrcweir 263cdf0e10cSrcweir /** RTL_CACHE_SLAB() 264cdf0e10cSrcweir */ 265cdf0e10cSrcweir #define RTL_CACHE_SLAB(addr, size) \ 266cdf0e10cSrcweir (((rtl_cache_slab_type*)(RTL_MEMORY_P2END((sal_uIntPtr)(addr), (size)))) - 1) 267cdf0e10cSrcweir 268cdf0e10cSrcweir 269cdf0e10cSrcweir /** rtl_cache_slab_constructor() 270cdf0e10cSrcweir */ 271cdf0e10cSrcweir static int 272cdf0e10cSrcweir rtl_cache_slab_constructor (void * obj, void * arg) 273cdf0e10cSrcweir { 274cdf0e10cSrcweir rtl_cache_slab_type * slab = (rtl_cache_slab_type*)(obj); 275cdf0e10cSrcweir 276cdf0e10cSrcweir (void) arg; /* unused */ 277cdf0e10cSrcweir 278cdf0e10cSrcweir QUEUE_START_NAMED(slab, slab_); 279cdf0e10cSrcweir slab->m_ntypes = 0; 280cdf0e10cSrcweir 281cdf0e10cSrcweir return (1); 282cdf0e10cSrcweir } 283cdf0e10cSrcweir 284cdf0e10cSrcweir 285cdf0e10cSrcweir /** rtl_cache_slab_destructor() 286cdf0e10cSrcweir */ 287cdf0e10cSrcweir static void 288cdf0e10cSrcweir rtl_cache_slab_destructor (void * obj, void * arg) 289cdf0e10cSrcweir { 290cdf0e10cSrcweir #if OSL_DEBUG_LEVEL == 0 291cdf0e10cSrcweir (void) obj; /* unused */ 292cdf0e10cSrcweir #else /* OSL_DEBUG_LEVEL */ 293cdf0e10cSrcweir rtl_cache_slab_type * slab = (rtl_cache_slab_type*)(obj); 294cdf0e10cSrcweir 295cdf0e10cSrcweir /* assure removed from queue(s) */ 296cdf0e10cSrcweir OSL_ASSERT(QUEUE_STARTED_NAMED(slab, slab_)); 297cdf0e10cSrcweir 298cdf0e10cSrcweir /* assure no longer referenced */ 299cdf0e10cSrcweir OSL_ASSERT(slab->m_ntypes == 0); 300cdf0e10cSrcweir #endif /* OSL_DEBUG_LEVEL */ 301cdf0e10cSrcweir 302cdf0e10cSrcweir (void) arg; /* unused */ 303cdf0e10cSrcweir } 304cdf0e10cSrcweir 305cdf0e10cSrcweir 306cdf0e10cSrcweir /** rtl_cache_slab_create() 307cdf0e10cSrcweir * 308cdf0e10cSrcweir * @precond cache->m_slab_lock released. 309cdf0e10cSrcweir */ 310cdf0e10cSrcweir static rtl_cache_slab_type * 311cdf0e10cSrcweir rtl_cache_slab_create ( 312cdf0e10cSrcweir rtl_cache_type * cache 313cdf0e10cSrcweir ) 314cdf0e10cSrcweir { 315cdf0e10cSrcweir rtl_cache_slab_type * slab = 0; 316cdf0e10cSrcweir void * addr; 317cdf0e10cSrcweir sal_Size size; 318cdf0e10cSrcweir 319cdf0e10cSrcweir size = cache->m_slab_size; 320cdf0e10cSrcweir addr = rtl_arena_alloc (cache->m_source, &size); 321cdf0e10cSrcweir if (addr != 0) 322cdf0e10cSrcweir { 323cdf0e10cSrcweir OSL_ASSERT(size >= cache->m_slab_size); 324cdf0e10cSrcweir 325cdf0e10cSrcweir if (cache->m_features & RTL_CACHE_FEATURE_HASH) 326cdf0e10cSrcweir { 327cdf0e10cSrcweir /* allocate slab struct from slab cache */ 328cdf0e10cSrcweir OSL_ASSERT (cache != gp_cache_slab_cache); 329cdf0e10cSrcweir slab = (rtl_cache_slab_type*)rtl_cache_alloc (gp_cache_slab_cache); 330cdf0e10cSrcweir } 331cdf0e10cSrcweir else 332cdf0e10cSrcweir { 333cdf0e10cSrcweir /* construct embedded slab struct */ 334cdf0e10cSrcweir slab = RTL_CACHE_SLAB(addr, cache->m_slab_size); 335cdf0e10cSrcweir (void) rtl_cache_slab_constructor (slab, 0); 336cdf0e10cSrcweir } 337cdf0e10cSrcweir if (slab != 0) 338cdf0e10cSrcweir { 339cdf0e10cSrcweir slab->m_data = (sal_uIntPtr)(addr); 340cdf0e10cSrcweir 341cdf0e10cSrcweir /* dynamic freelist initialization */ 342cdf0e10cSrcweir slab->m_bp = slab->m_data; 343cdf0e10cSrcweir slab->m_sp = 0; 344cdf0e10cSrcweir } 345cdf0e10cSrcweir else 346cdf0e10cSrcweir { 347cdf0e10cSrcweir rtl_arena_free (cache->m_source, addr, size); 348cdf0e10cSrcweir } 349cdf0e10cSrcweir } 350cdf0e10cSrcweir return (slab); 351cdf0e10cSrcweir } 352cdf0e10cSrcweir 353cdf0e10cSrcweir 354cdf0e10cSrcweir /** rtl_cache_slab_destroy() 355cdf0e10cSrcweir * 356cdf0e10cSrcweir * @precond cache->m_slab_lock released. 357cdf0e10cSrcweir */ 358cdf0e10cSrcweir static void 359cdf0e10cSrcweir rtl_cache_slab_destroy ( 360cdf0e10cSrcweir rtl_cache_type * cache, 361cdf0e10cSrcweir rtl_cache_slab_type * slab 362cdf0e10cSrcweir ) 363cdf0e10cSrcweir { 364cdf0e10cSrcweir void * addr = (void*)(slab->m_data); 365cdf0e10cSrcweir sal_Size refcnt = slab->m_ntypes; slab->m_ntypes = 0; 366cdf0e10cSrcweir 367cdf0e10cSrcweir if (cache->m_features & RTL_CACHE_FEATURE_HASH) 368cdf0e10cSrcweir { 369cdf0e10cSrcweir /* cleanup bufctl(s) for free buffer(s) */ 370cdf0e10cSrcweir sal_Size ntypes = (slab->m_bp - slab->m_data) / cache->m_type_size; 371cdf0e10cSrcweir for (ntypes -= refcnt; slab->m_sp != 0; ntypes--) 372cdf0e10cSrcweir { 373cdf0e10cSrcweir rtl_cache_bufctl_type * bufctl = slab->m_sp; 374cdf0e10cSrcweir 375cdf0e10cSrcweir /* pop from freelist */ 376cdf0e10cSrcweir slab->m_sp = bufctl->m_next, bufctl->m_next = 0; 377cdf0e10cSrcweir 378cdf0e10cSrcweir /* return bufctl struct to bufctl cache */ 379cdf0e10cSrcweir rtl_cache_free (gp_cache_bufctl_cache, bufctl); 380cdf0e10cSrcweir } 381cdf0e10cSrcweir OSL_ASSERT(ntypes == 0); 382cdf0e10cSrcweir 383cdf0e10cSrcweir /* return slab struct to slab cache */ 384cdf0e10cSrcweir rtl_cache_free (gp_cache_slab_cache, slab); 385cdf0e10cSrcweir } 386cdf0e10cSrcweir else 387cdf0e10cSrcweir { 388cdf0e10cSrcweir /* destruct embedded slab struct */ 389cdf0e10cSrcweir rtl_cache_slab_destructor (slab, 0); 390cdf0e10cSrcweir } 391cdf0e10cSrcweir 392cdf0e10cSrcweir if ((refcnt == 0) || (cache->m_features & RTL_CACHE_FEATURE_BULKDESTROY)) 393cdf0e10cSrcweir { 394cdf0e10cSrcweir /* free memory */ 395cdf0e10cSrcweir rtl_arena_free (cache->m_source, addr, cache->m_slab_size); 396cdf0e10cSrcweir } 397cdf0e10cSrcweir } 398cdf0e10cSrcweir 399cdf0e10cSrcweir 400cdf0e10cSrcweir /** rtl_cache_slab_populate() 401cdf0e10cSrcweir * 402cdf0e10cSrcweir * @precond cache->m_slab_lock acquired. 403cdf0e10cSrcweir */ 404cdf0e10cSrcweir static int 405cdf0e10cSrcweir rtl_cache_slab_populate ( 406cdf0e10cSrcweir rtl_cache_type * cache 407cdf0e10cSrcweir ) 408cdf0e10cSrcweir { 409cdf0e10cSrcweir rtl_cache_slab_type * slab; 410cdf0e10cSrcweir 411cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(cache->m_slab_lock)); 412cdf0e10cSrcweir slab = rtl_cache_slab_create (cache); 413cdf0e10cSrcweir RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_slab_lock)); 414cdf0e10cSrcweir if (slab != 0) 415cdf0e10cSrcweir { 416cdf0e10cSrcweir /* update buffer start addr w/ current color */ 417cdf0e10cSrcweir slab->m_bp += cache->m_ncolor; 418cdf0e10cSrcweir 419cdf0e10cSrcweir /* update color for next slab */ 420cdf0e10cSrcweir cache->m_ncolor += cache->m_type_align; 421cdf0e10cSrcweir if (cache->m_ncolor > cache->m_ncolor_max) 422cdf0e10cSrcweir cache->m_ncolor = 0; 423cdf0e10cSrcweir 424cdf0e10cSrcweir /* update stats */ 425cdf0e10cSrcweir cache->m_slab_stats.m_mem_total += cache->m_slab_size; 426cdf0e10cSrcweir 427cdf0e10cSrcweir /* insert onto 'free' queue */ 428cdf0e10cSrcweir QUEUE_INSERT_HEAD_NAMED(&(cache->m_free_head), slab, slab_); 429cdf0e10cSrcweir } 430cdf0e10cSrcweir return (slab != 0); 431cdf0e10cSrcweir } 432cdf0e10cSrcweir 433cdf0e10cSrcweir /* ================================================================= */ 434cdf0e10cSrcweir 435cdf0e10cSrcweir /** rtl_cache_slab_alloc() 436cdf0e10cSrcweir * 437cdf0e10cSrcweir * Allocate a buffer from slab layer; used by magazine layer. 438cdf0e10cSrcweir */ 439cdf0e10cSrcweir static void * 440cdf0e10cSrcweir rtl_cache_slab_alloc ( 441cdf0e10cSrcweir rtl_cache_type * cache 442cdf0e10cSrcweir ) 443cdf0e10cSrcweir { 444cdf0e10cSrcweir void * addr = 0; 445cdf0e10cSrcweir rtl_cache_slab_type * head; 446cdf0e10cSrcweir 447cdf0e10cSrcweir RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_slab_lock)); 448cdf0e10cSrcweir 449cdf0e10cSrcweir head = &(cache->m_free_head); 450cdf0e10cSrcweir if ((head->m_slab_next != head) || rtl_cache_slab_populate (cache)) 451cdf0e10cSrcweir { 452cdf0e10cSrcweir rtl_cache_slab_type * slab; 453cdf0e10cSrcweir rtl_cache_bufctl_type * bufctl; 454cdf0e10cSrcweir 455cdf0e10cSrcweir slab = head->m_slab_next; 456cdf0e10cSrcweir OSL_ASSERT(slab->m_ntypes < cache->m_ntypes); 457cdf0e10cSrcweir 458cdf0e10cSrcweir if (slab->m_sp == 0) 459cdf0e10cSrcweir { 460cdf0e10cSrcweir /* initialize bufctl w/ current 'slab->m_bp' */ 461cdf0e10cSrcweir OSL_ASSERT (slab->m_bp < slab->m_data + cache->m_ntypes * cache->m_type_size + cache->m_ncolor_max); 462cdf0e10cSrcweir if (cache->m_features & RTL_CACHE_FEATURE_HASH) 463cdf0e10cSrcweir { 464cdf0e10cSrcweir /* allocate bufctl */ 465cdf0e10cSrcweir OSL_ASSERT (cache != gp_cache_bufctl_cache); 466cdf0e10cSrcweir bufctl = (rtl_cache_bufctl_type*)rtl_cache_alloc (gp_cache_bufctl_cache); 467cdf0e10cSrcweir if (bufctl == 0) 468cdf0e10cSrcweir { 469cdf0e10cSrcweir /* out of memory */ 470cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(cache->m_slab_lock)); 471cdf0e10cSrcweir return (0); 472cdf0e10cSrcweir } 473cdf0e10cSrcweir 474cdf0e10cSrcweir bufctl->m_addr = slab->m_bp; 475cdf0e10cSrcweir bufctl->m_slab = (sal_uIntPtr)(slab); 476cdf0e10cSrcweir } 477cdf0e10cSrcweir else 478cdf0e10cSrcweir { 479cdf0e10cSrcweir /* embedded bufctl */ 480cdf0e10cSrcweir bufctl = (rtl_cache_bufctl_type*)(slab->m_bp); 481cdf0e10cSrcweir } 482cdf0e10cSrcweir bufctl->m_next = 0; 483cdf0e10cSrcweir 484cdf0e10cSrcweir /* update 'slab->m_bp' to next free buffer */ 485cdf0e10cSrcweir slab->m_bp += cache->m_type_size; 486cdf0e10cSrcweir 487cdf0e10cSrcweir /* assign bufctl to freelist */ 488cdf0e10cSrcweir slab->m_sp = bufctl; 489cdf0e10cSrcweir } 490cdf0e10cSrcweir 491cdf0e10cSrcweir /* pop front */ 492cdf0e10cSrcweir bufctl = slab->m_sp; 493cdf0e10cSrcweir slab->m_sp = bufctl->m_next; 494cdf0e10cSrcweir 495cdf0e10cSrcweir /* increment usage, check for full slab */ 496cdf0e10cSrcweir if ((slab->m_ntypes += 1) == cache->m_ntypes) 497cdf0e10cSrcweir { 498cdf0e10cSrcweir /* remove from 'free' queue */ 499cdf0e10cSrcweir QUEUE_REMOVE_NAMED(slab, slab_); 500cdf0e10cSrcweir 501cdf0e10cSrcweir /* insert onto 'used' queue (tail) */ 502cdf0e10cSrcweir QUEUE_INSERT_TAIL_NAMED(&(cache->m_used_head), slab, slab_); 503cdf0e10cSrcweir } 504cdf0e10cSrcweir 505cdf0e10cSrcweir /* update stats */ 506cdf0e10cSrcweir cache->m_slab_stats.m_alloc += 1; 507cdf0e10cSrcweir cache->m_slab_stats.m_mem_alloc += cache->m_type_size; 508cdf0e10cSrcweir 509cdf0e10cSrcweir if (cache->m_features & RTL_CACHE_FEATURE_HASH) 510cdf0e10cSrcweir addr = (void*)rtl_cache_hash_insert (cache, bufctl); 511cdf0e10cSrcweir else 512cdf0e10cSrcweir addr = bufctl; 513cdf0e10cSrcweir 514cdf0e10cSrcweir /* DEBUG ONLY: mark allocated, undefined */ 515cdf0e10cSrcweir OSL_DEBUG_ONLY(memset(addr, 0x77777777, cache->m_type_size)); 516cdf0e10cSrcweir VALGRIND_MEMPOOL_ALLOC(cache, addr, cache->m_type_size); 517cdf0e10cSrcweir } 518cdf0e10cSrcweir 519cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(cache->m_slab_lock)); 520cdf0e10cSrcweir return (addr); 521cdf0e10cSrcweir } 522cdf0e10cSrcweir 523cdf0e10cSrcweir 524cdf0e10cSrcweir /** rtl_cache_slab_free() 525cdf0e10cSrcweir * 526cdf0e10cSrcweir * Return a buffer to slab layer; used by magazine layer. 527cdf0e10cSrcweir */ 528cdf0e10cSrcweir static void 529cdf0e10cSrcweir rtl_cache_slab_free ( 530cdf0e10cSrcweir rtl_cache_type * cache, 531cdf0e10cSrcweir void * addr 532cdf0e10cSrcweir ) 533cdf0e10cSrcweir { 534cdf0e10cSrcweir rtl_cache_bufctl_type * bufctl; 535cdf0e10cSrcweir rtl_cache_slab_type * slab; 536cdf0e10cSrcweir 537cdf0e10cSrcweir RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_slab_lock)); 538cdf0e10cSrcweir 539cdf0e10cSrcweir /* DEBUG ONLY: mark unallocated, undefined */ 540cdf0e10cSrcweir VALGRIND_MEMPOOL_FREE(cache, addr); 541cdf0e10cSrcweir /* OSL_DEBUG_ONLY() */ VALGRIND_MAKE_MEM_UNDEFINED(addr, cache->m_type_size); 542cdf0e10cSrcweir OSL_DEBUG_ONLY(memset(addr, 0x33333333, cache->m_type_size)); 543cdf0e10cSrcweir 544cdf0e10cSrcweir /* determine slab from addr */ 545cdf0e10cSrcweir if (cache->m_features & RTL_CACHE_FEATURE_HASH) 546cdf0e10cSrcweir { 547cdf0e10cSrcweir bufctl = rtl_cache_hash_remove (cache, (sal_uIntPtr)(addr)); 548cdf0e10cSrcweir slab = (bufctl != 0) ? (rtl_cache_slab_type*)(bufctl->m_slab) : 0; 549cdf0e10cSrcweir } 550cdf0e10cSrcweir else 551cdf0e10cSrcweir { 552cdf0e10cSrcweir /* embedded slab struct */ 553cdf0e10cSrcweir bufctl = (rtl_cache_bufctl_type*)(addr); 554cdf0e10cSrcweir slab = RTL_CACHE_SLAB(addr, cache->m_slab_size); 555cdf0e10cSrcweir } 556cdf0e10cSrcweir 557cdf0e10cSrcweir if (slab != 0) 558cdf0e10cSrcweir { 559cdf0e10cSrcweir /* check for full slab */ 560cdf0e10cSrcweir if (slab->m_ntypes == cache->m_ntypes) 561cdf0e10cSrcweir { 562cdf0e10cSrcweir /* remove from 'used' queue */ 563cdf0e10cSrcweir QUEUE_REMOVE_NAMED(slab, slab_); 564cdf0e10cSrcweir 565cdf0e10cSrcweir /* insert onto 'free' queue (head) */ 566cdf0e10cSrcweir QUEUE_INSERT_HEAD_NAMED(&(cache->m_free_head), slab, slab_); 567cdf0e10cSrcweir } 568cdf0e10cSrcweir 569cdf0e10cSrcweir /* push front */ 570cdf0e10cSrcweir bufctl->m_next = slab->m_sp; 571cdf0e10cSrcweir slab->m_sp = bufctl; 572cdf0e10cSrcweir 573cdf0e10cSrcweir /* update stats */ 574cdf0e10cSrcweir cache->m_slab_stats.m_free += 1; 575cdf0e10cSrcweir cache->m_slab_stats.m_mem_alloc -= cache->m_type_size; 576cdf0e10cSrcweir 577cdf0e10cSrcweir /* decrement usage, check for empty slab */ 578cdf0e10cSrcweir if ((slab->m_ntypes -= 1) == 0) 579cdf0e10cSrcweir { 580cdf0e10cSrcweir /* remove from 'free' queue */ 581cdf0e10cSrcweir QUEUE_REMOVE_NAMED(slab, slab_); 582cdf0e10cSrcweir 583cdf0e10cSrcweir /* update stats */ 584cdf0e10cSrcweir cache->m_slab_stats.m_mem_total -= cache->m_slab_size; 585cdf0e10cSrcweir 586cdf0e10cSrcweir /* free 'empty' slab */ 587cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(cache->m_slab_lock)); 588cdf0e10cSrcweir rtl_cache_slab_destroy (cache, slab); 589cdf0e10cSrcweir return; 590cdf0e10cSrcweir } 591cdf0e10cSrcweir } 592cdf0e10cSrcweir 593cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(cache->m_slab_lock)); 594cdf0e10cSrcweir } 595cdf0e10cSrcweir 596cdf0e10cSrcweir /* ================================================================= */ 597cdf0e10cSrcweir 598cdf0e10cSrcweir /** rtl_cache_magazine_constructor() 599cdf0e10cSrcweir */ 600cdf0e10cSrcweir static int 601cdf0e10cSrcweir rtl_cache_magazine_constructor (void * obj, void * arg) 602cdf0e10cSrcweir { 603cdf0e10cSrcweir rtl_cache_magazine_type * mag = (rtl_cache_magazine_type*)(obj); 604cdf0e10cSrcweir /* @@@ sal_Size size = (sal_Size)(arg); @@@ */ 605cdf0e10cSrcweir 606cdf0e10cSrcweir (void) arg; /* unused */ 607cdf0e10cSrcweir 608cdf0e10cSrcweir mag->m_mag_next = 0; 609cdf0e10cSrcweir mag->m_mag_size = RTL_CACHE_MAGAZINE_SIZE; 610cdf0e10cSrcweir mag->m_mag_used = 0; 611cdf0e10cSrcweir 612cdf0e10cSrcweir return (1); 613cdf0e10cSrcweir } 614cdf0e10cSrcweir 615cdf0e10cSrcweir 616cdf0e10cSrcweir /** rtl_cache_magazine_destructor() 617cdf0e10cSrcweir */ 618cdf0e10cSrcweir static void 619cdf0e10cSrcweir rtl_cache_magazine_destructor (void * obj, void * arg) 620cdf0e10cSrcweir { 621cdf0e10cSrcweir #if OSL_DEBUG_LEVEL == 0 622cdf0e10cSrcweir (void) obj; /* unused */ 623cdf0e10cSrcweir #else /* OSL_DEBUG_LEVEL */ 624cdf0e10cSrcweir rtl_cache_magazine_type * mag = (rtl_cache_magazine_type*)(obj); 625cdf0e10cSrcweir 626cdf0e10cSrcweir /* assure removed from queue(s) */ 627cdf0e10cSrcweir OSL_ASSERT(mag->m_mag_next == 0); 628cdf0e10cSrcweir 629cdf0e10cSrcweir /* assure no longer referenced */ 630cdf0e10cSrcweir OSL_ASSERT(mag->m_mag_used == 0); 631cdf0e10cSrcweir #endif /* OSL_DEBUG_LEVEL */ 632cdf0e10cSrcweir 633cdf0e10cSrcweir (void) arg; /* unused */ 634cdf0e10cSrcweir } 635cdf0e10cSrcweir 636cdf0e10cSrcweir 637cdf0e10cSrcweir /** rtl_cache_magazine_clear() 638cdf0e10cSrcweir */ 639cdf0e10cSrcweir static void 640cdf0e10cSrcweir rtl_cache_magazine_clear ( 641cdf0e10cSrcweir rtl_cache_type * cache, 642cdf0e10cSrcweir rtl_cache_magazine_type * mag 643cdf0e10cSrcweir ) 644cdf0e10cSrcweir { 645cdf0e10cSrcweir for (; mag->m_mag_used > 0; --mag->m_mag_used) 646cdf0e10cSrcweir { 647cdf0e10cSrcweir void * obj = mag->m_objects[mag->m_mag_used - 1]; 648cdf0e10cSrcweir mag->m_objects[mag->m_mag_used - 1] = 0; 649cdf0e10cSrcweir 650cdf0e10cSrcweir /* DEBUG ONLY: mark cached object allocated, undefined */ 651cdf0e10cSrcweir VALGRIND_MEMPOOL_ALLOC(cache, obj, cache->m_type_size); 652cdf0e10cSrcweir if (cache->m_destructor != 0) 653cdf0e10cSrcweir { 654cdf0e10cSrcweir /* DEBUG ONLY: keep constructed object defined */ 655cdf0e10cSrcweir VALGRIND_MAKE_MEM_DEFINED(obj, cache->m_type_size); 656cdf0e10cSrcweir 657cdf0e10cSrcweir /* destruct object */ 658cdf0e10cSrcweir (cache->m_destructor)(obj, cache->m_userarg); 659cdf0e10cSrcweir } 660cdf0e10cSrcweir 661cdf0e10cSrcweir /* return buffer to slab layer */ 662cdf0e10cSrcweir rtl_cache_slab_free (cache, obj); 663cdf0e10cSrcweir } 664cdf0e10cSrcweir } 665cdf0e10cSrcweir 666cdf0e10cSrcweir /* ================================================================= */ 667cdf0e10cSrcweir 668cdf0e10cSrcweir /** rtl_cache_depot_enqueue() 669cdf0e10cSrcweir * 670cdf0e10cSrcweir * @precond cache->m_depot_lock acquired. 671cdf0e10cSrcweir */ 672cdf0e10cSrcweir static RTL_MEMORY_INLINE void 673cdf0e10cSrcweir rtl_cache_depot_enqueue ( 674cdf0e10cSrcweir rtl_cache_depot_type * depot, 675cdf0e10cSrcweir rtl_cache_magazine_type * mag 676cdf0e10cSrcweir ) 677cdf0e10cSrcweir { 678cdf0e10cSrcweir /* enqueue empty magazine */ 679cdf0e10cSrcweir mag->m_mag_next = depot->m_mag_next; 680cdf0e10cSrcweir depot->m_mag_next = mag; 681cdf0e10cSrcweir 682cdf0e10cSrcweir /* update depot stats */ 683cdf0e10cSrcweir depot->m_mag_count++; 684cdf0e10cSrcweir } 685cdf0e10cSrcweir 686cdf0e10cSrcweir #if defined(__SUNPRO_C) || defined(__SUNPRO_CC) 687cdf0e10cSrcweir #pragma inline(rtl_cache_depot_enqueue) 688cdf0e10cSrcweir #endif /* __SUNPRO_C */ 689cdf0e10cSrcweir 690cdf0e10cSrcweir 691cdf0e10cSrcweir /** rtl_cache_depot_dequeue() 692cdf0e10cSrcweir * 693cdf0e10cSrcweir * @precond cache->m_depot_lock acquired. 694cdf0e10cSrcweir */ 695cdf0e10cSrcweir static RTL_MEMORY_INLINE rtl_cache_magazine_type * 696cdf0e10cSrcweir rtl_cache_depot_dequeue ( 697cdf0e10cSrcweir rtl_cache_depot_type * depot 698cdf0e10cSrcweir ) 699cdf0e10cSrcweir { 700cdf0e10cSrcweir rtl_cache_magazine_type * mag = 0; 701cdf0e10cSrcweir if (depot->m_mag_count > 0) 702cdf0e10cSrcweir { 703cdf0e10cSrcweir /* dequeue magazine */ 704cdf0e10cSrcweir OSL_ASSERT(depot->m_mag_next != 0); 705cdf0e10cSrcweir 706cdf0e10cSrcweir mag = depot->m_mag_next; 707cdf0e10cSrcweir depot->m_mag_next = mag->m_mag_next; 708cdf0e10cSrcweir mag->m_mag_next = 0; 709cdf0e10cSrcweir 710cdf0e10cSrcweir /* update depot stats */ 711cdf0e10cSrcweir depot->m_mag_count--; 712cdf0e10cSrcweir depot->m_curr_min = SAL_MIN(depot->m_curr_min, depot->m_mag_count); 713cdf0e10cSrcweir } 714cdf0e10cSrcweir return (mag); 715cdf0e10cSrcweir } 716cdf0e10cSrcweir 717cdf0e10cSrcweir #if defined(__SUNPRO_C) || defined(__SUNPRO_CC) 718cdf0e10cSrcweir #pragma inline(rtl_cache_depot_dequeue) 719cdf0e10cSrcweir #endif /* __SUNPRO_C */ 720cdf0e10cSrcweir 721cdf0e10cSrcweir 722cdf0e10cSrcweir /** rtl_cache_depot_exchange_alloc() 723cdf0e10cSrcweir * 724cdf0e10cSrcweir * @precond cache->m_depot_lock acquired. 725cdf0e10cSrcweir */ 726cdf0e10cSrcweir static RTL_MEMORY_INLINE rtl_cache_magazine_type * 727cdf0e10cSrcweir rtl_cache_depot_exchange_alloc ( 728cdf0e10cSrcweir rtl_cache_type * cache, 729cdf0e10cSrcweir rtl_cache_magazine_type * empty 730cdf0e10cSrcweir ) 731cdf0e10cSrcweir { 732cdf0e10cSrcweir rtl_cache_magazine_type * full; 733cdf0e10cSrcweir 734cdf0e10cSrcweir OSL_ASSERT((empty == 0) || (empty->m_mag_used == 0)); 735cdf0e10cSrcweir 736cdf0e10cSrcweir /* dequeue full magazine */ 737cdf0e10cSrcweir full = rtl_cache_depot_dequeue (&(cache->m_depot_full)); 738cdf0e10cSrcweir if ((full != 0) && (empty != 0)) 739cdf0e10cSrcweir { 740cdf0e10cSrcweir /* enqueue empty magazine */ 741cdf0e10cSrcweir rtl_cache_depot_enqueue (&(cache->m_depot_empty), empty); 742cdf0e10cSrcweir } 743cdf0e10cSrcweir 744cdf0e10cSrcweir OSL_ASSERT((full == 0) || (full->m_mag_used > 0)); 745cdf0e10cSrcweir 746cdf0e10cSrcweir return (full); 747cdf0e10cSrcweir } 748cdf0e10cSrcweir 749cdf0e10cSrcweir #if defined(__SUNPRO_C) || defined(__SUNPRO_CC) 750cdf0e10cSrcweir #pragma inline(rtl_cache_depot_exchange_alloc) 751cdf0e10cSrcweir #endif /* __SUNPRO_C */ 752cdf0e10cSrcweir 753cdf0e10cSrcweir 754cdf0e10cSrcweir /** rtl_cache_depot_exchange_free() 755cdf0e10cSrcweir * 756cdf0e10cSrcweir * @precond cache->m_depot_lock acquired. 757cdf0e10cSrcweir */ 758cdf0e10cSrcweir static RTL_MEMORY_INLINE rtl_cache_magazine_type * 759cdf0e10cSrcweir rtl_cache_depot_exchange_free ( 760cdf0e10cSrcweir rtl_cache_type * cache, 761cdf0e10cSrcweir rtl_cache_magazine_type * full 762cdf0e10cSrcweir ) 763cdf0e10cSrcweir { 764cdf0e10cSrcweir rtl_cache_magazine_type * empty; 765cdf0e10cSrcweir 766cdf0e10cSrcweir OSL_ASSERT((full == 0) || (full->m_mag_used > 0)); 767cdf0e10cSrcweir 768cdf0e10cSrcweir /* dequeue empty magazine */ 769cdf0e10cSrcweir empty = rtl_cache_depot_dequeue (&(cache->m_depot_empty)); 770cdf0e10cSrcweir if ((empty != 0) && (full != 0)) 771cdf0e10cSrcweir { 772cdf0e10cSrcweir /* enqueue full magazine */ 773cdf0e10cSrcweir rtl_cache_depot_enqueue (&(cache->m_depot_full), full); 774cdf0e10cSrcweir } 775cdf0e10cSrcweir 776cdf0e10cSrcweir OSL_ASSERT((empty == 0) || (empty->m_mag_used == 0)); 777cdf0e10cSrcweir 778cdf0e10cSrcweir return (empty); 779cdf0e10cSrcweir } 780cdf0e10cSrcweir 781cdf0e10cSrcweir #if defined(__SUNPRO_C) || defined(__SUNPRO_CC) 782cdf0e10cSrcweir #pragma inline(rtl_cache_depot_exchange_free) 783cdf0e10cSrcweir #endif /* __SUNPRO_C */ 784cdf0e10cSrcweir 785cdf0e10cSrcweir 786cdf0e10cSrcweir /** rtl_cache_depot_populate() 787cdf0e10cSrcweir * 788cdf0e10cSrcweir * @precond cache->m_depot_lock acquired. 789cdf0e10cSrcweir */ 790cdf0e10cSrcweir static int 791cdf0e10cSrcweir rtl_cache_depot_populate ( 792cdf0e10cSrcweir rtl_cache_type * cache 793cdf0e10cSrcweir ) 794cdf0e10cSrcweir { 795cdf0e10cSrcweir rtl_cache_magazine_type * empty = 0; 796cdf0e10cSrcweir 797cdf0e10cSrcweir if (cache->m_magazine_cache != 0) 798cdf0e10cSrcweir { 799cdf0e10cSrcweir /* allocate new empty magazine */ 800cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(cache->m_depot_lock)); 801cdf0e10cSrcweir empty = (rtl_cache_magazine_type*)rtl_cache_alloc (cache->m_magazine_cache); 802cdf0e10cSrcweir RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_depot_lock)); 803cdf0e10cSrcweir if (empty != 0) 804cdf0e10cSrcweir { 805cdf0e10cSrcweir /* enqueue (new) empty magazine */ 806cdf0e10cSrcweir rtl_cache_depot_enqueue (&(cache->m_depot_empty), empty); 807cdf0e10cSrcweir } 808cdf0e10cSrcweir } 809cdf0e10cSrcweir return (empty != 0); 810cdf0e10cSrcweir } 811cdf0e10cSrcweir 812cdf0e10cSrcweir /* ================================================================= */ 813cdf0e10cSrcweir 814cdf0e10cSrcweir /** rtl_cache_constructor() 815cdf0e10cSrcweir */ 816cdf0e10cSrcweir static int 817cdf0e10cSrcweir rtl_cache_constructor (void * obj) 818cdf0e10cSrcweir { 819cdf0e10cSrcweir rtl_cache_type * cache = (rtl_cache_type*)(obj); 820cdf0e10cSrcweir 821cdf0e10cSrcweir memset (cache, 0, sizeof(rtl_cache_type)); 822cdf0e10cSrcweir 823cdf0e10cSrcweir /* linkage */ 824cdf0e10cSrcweir QUEUE_START_NAMED(cache, cache_); 825cdf0e10cSrcweir 826cdf0e10cSrcweir /* slab layer */ 827cdf0e10cSrcweir (void)RTL_MEMORY_LOCK_INIT(&(cache->m_slab_lock)); 828cdf0e10cSrcweir 829cdf0e10cSrcweir QUEUE_START_NAMED(&(cache->m_free_head), slab_); 830cdf0e10cSrcweir QUEUE_START_NAMED(&(cache->m_used_head), slab_); 831cdf0e10cSrcweir 832cdf0e10cSrcweir cache->m_hash_table = cache->m_hash_table_0; 833cdf0e10cSrcweir cache->m_hash_size = RTL_CACHE_HASH_SIZE; 834cdf0e10cSrcweir cache->m_hash_shift = highbit(cache->m_hash_size) - 1; 835cdf0e10cSrcweir 836cdf0e10cSrcweir /* depot layer */ 837cdf0e10cSrcweir (void)RTL_MEMORY_LOCK_INIT(&(cache->m_depot_lock)); 838cdf0e10cSrcweir 839cdf0e10cSrcweir return (1); 840cdf0e10cSrcweir } 841cdf0e10cSrcweir 842cdf0e10cSrcweir /** rtl_cache_destructor() 843cdf0e10cSrcweir */ 844cdf0e10cSrcweir static void 845cdf0e10cSrcweir rtl_cache_destructor (void * obj) 846cdf0e10cSrcweir { 847cdf0e10cSrcweir rtl_cache_type * cache = (rtl_cache_type*)(obj); 848cdf0e10cSrcweir 849cdf0e10cSrcweir /* linkage */ 850cdf0e10cSrcweir OSL_ASSERT(QUEUE_STARTED_NAMED(cache, cache_)); 851cdf0e10cSrcweir 852cdf0e10cSrcweir /* slab layer */ 853cdf0e10cSrcweir (void)RTL_MEMORY_LOCK_DESTROY(&(cache->m_slab_lock)); 854cdf0e10cSrcweir 855cdf0e10cSrcweir OSL_ASSERT(QUEUE_STARTED_NAMED(&(cache->m_free_head), slab_)); 856cdf0e10cSrcweir OSL_ASSERT(QUEUE_STARTED_NAMED(&(cache->m_used_head), slab_)); 857cdf0e10cSrcweir 858cdf0e10cSrcweir OSL_ASSERT(cache->m_hash_table == cache->m_hash_table_0); 859cdf0e10cSrcweir OSL_ASSERT(cache->m_hash_size == RTL_CACHE_HASH_SIZE); 860cdf0e10cSrcweir OSL_ASSERT(cache->m_hash_shift == (sal_Size)(highbit(cache->m_hash_size) - 1)); 861cdf0e10cSrcweir 862cdf0e10cSrcweir /* depot layer */ 863cdf0e10cSrcweir (void)RTL_MEMORY_LOCK_DESTROY(&(cache->m_depot_lock)); 864cdf0e10cSrcweir } 865cdf0e10cSrcweir 866cdf0e10cSrcweir /* ================================================================= */ 867cdf0e10cSrcweir 868cdf0e10cSrcweir /** rtl_cache_activate() 869cdf0e10cSrcweir */ 870cdf0e10cSrcweir static rtl_cache_type * 871cdf0e10cSrcweir rtl_cache_activate ( 872cdf0e10cSrcweir rtl_cache_type * cache, 873cdf0e10cSrcweir const char * name, 874cdf0e10cSrcweir size_t objsize, 875cdf0e10cSrcweir size_t objalign, 876cdf0e10cSrcweir int (SAL_CALL * constructor)(void * obj, void * userarg), 877cdf0e10cSrcweir void (SAL_CALL * destructor) (void * obj, void * userarg), 878cdf0e10cSrcweir void (SAL_CALL * reclaim) (void * userarg), 879cdf0e10cSrcweir void * userarg, 880cdf0e10cSrcweir rtl_arena_type * source, 881cdf0e10cSrcweir int flags 882cdf0e10cSrcweir ) 883cdf0e10cSrcweir { 884cdf0e10cSrcweir OSL_ASSERT(cache != 0); 885cdf0e10cSrcweir if (cache != 0) 886cdf0e10cSrcweir { 887cdf0e10cSrcweir sal_Size slabsize; 888cdf0e10cSrcweir 889cdf0e10cSrcweir snprintf (cache->m_name, sizeof(cache->m_name), "%s", name); 890cdf0e10cSrcweir 891cdf0e10cSrcweir /* ensure minimum size (embedded bufctl linkage) */ 892cdf0e10cSrcweir objsize = SAL_MAX(objsize, sizeof(rtl_cache_bufctl_type*)); 893cdf0e10cSrcweir 894cdf0e10cSrcweir if (objalign == 0) 895cdf0e10cSrcweir { 896cdf0e10cSrcweir /* determine default alignment */ 897cdf0e10cSrcweir if (objsize >= RTL_MEMORY_ALIGNMENT_8) 898cdf0e10cSrcweir objalign = RTL_MEMORY_ALIGNMENT_8; 899cdf0e10cSrcweir else 900cdf0e10cSrcweir objalign = RTL_MEMORY_ALIGNMENT_4; 901cdf0e10cSrcweir } 902cdf0e10cSrcweir else 903cdf0e10cSrcweir { 904cdf0e10cSrcweir /* ensure minimum alignment */ 905cdf0e10cSrcweir objalign = SAL_MAX(objalign, RTL_MEMORY_ALIGNMENT_4); 906cdf0e10cSrcweir } 907cdf0e10cSrcweir OSL_ASSERT(RTL_MEMORY_ISP2(objalign)); 908cdf0e10cSrcweir 909cdf0e10cSrcweir cache->m_type_size = objsize = RTL_MEMORY_P2ROUNDUP(objsize, objalign); 910cdf0e10cSrcweir cache->m_type_align = objalign; 911cdf0e10cSrcweir cache->m_type_shift = highbit(cache->m_type_size) - 1; 912cdf0e10cSrcweir 913cdf0e10cSrcweir cache->m_constructor = constructor; 914cdf0e10cSrcweir cache->m_destructor = destructor; 915cdf0e10cSrcweir cache->m_reclaim = reclaim; 916cdf0e10cSrcweir cache->m_userarg = userarg; 917cdf0e10cSrcweir 918cdf0e10cSrcweir /* slab layer */ 919cdf0e10cSrcweir cache->m_source = source; 920cdf0e10cSrcweir 921cdf0e10cSrcweir slabsize = source->m_quantum; /* minimum slab size */ 922cdf0e10cSrcweir if (flags & RTL_CACHE_FLAG_QUANTUMCACHE) 923cdf0e10cSrcweir { 924cdf0e10cSrcweir /* next power of 2 above 3 * qcache_max */ 925cdf0e10cSrcweir slabsize = SAL_MAX(slabsize, (1UL << highbit(3 * source->m_qcache_max))); 926cdf0e10cSrcweir } 927cdf0e10cSrcweir else 928cdf0e10cSrcweir { 929cdf0e10cSrcweir /* waste at most 1/8 of slab */ 930cdf0e10cSrcweir slabsize = SAL_MAX(slabsize, cache->m_type_size * 8); 931cdf0e10cSrcweir } 932cdf0e10cSrcweir 933cdf0e10cSrcweir slabsize = RTL_MEMORY_P2ROUNDUP(slabsize, source->m_quantum); 934cdf0e10cSrcweir if (!RTL_MEMORY_ISP2(slabsize)) 935cdf0e10cSrcweir slabsize = 1UL << highbit(slabsize); 936cdf0e10cSrcweir cache->m_slab_size = slabsize; 937cdf0e10cSrcweir 938cdf0e10cSrcweir if (cache->m_slab_size > source->m_quantum) 939cdf0e10cSrcweir { 940cdf0e10cSrcweir OSL_ASSERT(gp_cache_slab_cache != 0); 941cdf0e10cSrcweir OSL_ASSERT(gp_cache_bufctl_cache != 0); 942cdf0e10cSrcweir 943cdf0e10cSrcweir cache->m_features |= RTL_CACHE_FEATURE_HASH; 944cdf0e10cSrcweir cache->m_ntypes = cache->m_slab_size / cache->m_type_size; 945cdf0e10cSrcweir cache->m_ncolor_max = cache->m_slab_size % cache->m_type_size; 946cdf0e10cSrcweir } 947cdf0e10cSrcweir else 948cdf0e10cSrcweir { 949cdf0e10cSrcweir /* embedded slab struct */ 950cdf0e10cSrcweir cache->m_ntypes = (cache->m_slab_size - sizeof(rtl_cache_slab_type)) / cache->m_type_size; 951cdf0e10cSrcweir cache->m_ncolor_max = (cache->m_slab_size - sizeof(rtl_cache_slab_type)) % cache->m_type_size; 952cdf0e10cSrcweir } 953cdf0e10cSrcweir 954cdf0e10cSrcweir OSL_ASSERT(cache->m_ntypes > 0); 955cdf0e10cSrcweir cache->m_ncolor = 0; 956cdf0e10cSrcweir 957cdf0e10cSrcweir if (flags & RTL_CACHE_FLAG_BULKDESTROY) 958cdf0e10cSrcweir { 959cdf0e10cSrcweir /* allow bulk slab delete upon cache deactivation */ 960cdf0e10cSrcweir cache->m_features |= RTL_CACHE_FEATURE_BULKDESTROY; 961cdf0e10cSrcweir } 962cdf0e10cSrcweir 963cdf0e10cSrcweir /* magazine layer */ 964cdf0e10cSrcweir if (!(flags & RTL_CACHE_FLAG_NOMAGAZINE)) 965cdf0e10cSrcweir { 966cdf0e10cSrcweir OSL_ASSERT(gp_cache_magazine_cache != 0); 967cdf0e10cSrcweir cache->m_magazine_cache = gp_cache_magazine_cache; 968cdf0e10cSrcweir } 969cdf0e10cSrcweir 970cdf0e10cSrcweir /* insert into cache list */ 971cdf0e10cSrcweir RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock)); 972cdf0e10cSrcweir QUEUE_INSERT_TAIL_NAMED(&(g_cache_list.m_cache_head), cache, cache_); 973cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock)); 974cdf0e10cSrcweir } 975cdf0e10cSrcweir return (cache); 976cdf0e10cSrcweir } 977cdf0e10cSrcweir 978cdf0e10cSrcweir /** rtl_cache_deactivate() 979cdf0e10cSrcweir */ 980cdf0e10cSrcweir static void 981cdf0e10cSrcweir rtl_cache_deactivate ( 982cdf0e10cSrcweir rtl_cache_type * cache 983cdf0e10cSrcweir ) 984cdf0e10cSrcweir { 985cdf0e10cSrcweir int active = 1; 986cdf0e10cSrcweir 987cdf0e10cSrcweir /* remove from cache list */ 988cdf0e10cSrcweir RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock)); 989cdf0e10cSrcweir active = QUEUE_STARTED_NAMED(cache, cache_) == 0; 990cdf0e10cSrcweir QUEUE_REMOVE_NAMED(cache, cache_); 991cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock)); 992cdf0e10cSrcweir 993cdf0e10cSrcweir OSL_PRECOND(active, "rtl_cache_deactivate(): orphaned cache."); 994cdf0e10cSrcweir 995cdf0e10cSrcweir /* cleanup magazine layer */ 996cdf0e10cSrcweir if (cache->m_magazine_cache != 0) 997cdf0e10cSrcweir { 998cdf0e10cSrcweir rtl_cache_type * mag_cache; 999cdf0e10cSrcweir rtl_cache_magazine_type * mag; 1000cdf0e10cSrcweir 1001cdf0e10cSrcweir /* prevent recursion */ 1002cdf0e10cSrcweir mag_cache = cache->m_magazine_cache, cache->m_magazine_cache = 0; 1003cdf0e10cSrcweir 1004cdf0e10cSrcweir /* cleanup cpu layer */ 1005cdf0e10cSrcweir if ((mag = cache->m_cpu_curr) != 0) 1006cdf0e10cSrcweir { 1007cdf0e10cSrcweir cache->m_cpu_curr = 0; 1008cdf0e10cSrcweir rtl_cache_magazine_clear (cache, mag); 1009cdf0e10cSrcweir rtl_cache_free (mag_cache, mag); 1010cdf0e10cSrcweir } 1011cdf0e10cSrcweir if ((mag = cache->m_cpu_prev) != 0) 1012cdf0e10cSrcweir { 1013cdf0e10cSrcweir cache->m_cpu_prev = 0; 1014cdf0e10cSrcweir rtl_cache_magazine_clear (cache, mag); 1015cdf0e10cSrcweir rtl_cache_free (mag_cache, mag); 1016cdf0e10cSrcweir } 1017cdf0e10cSrcweir 1018cdf0e10cSrcweir /* cleanup depot layer */ 1019cdf0e10cSrcweir while ((mag = rtl_cache_depot_dequeue(&(cache->m_depot_full))) != 0) 1020cdf0e10cSrcweir { 1021cdf0e10cSrcweir rtl_cache_magazine_clear (cache, mag); 1022cdf0e10cSrcweir rtl_cache_free (mag_cache, mag); 1023cdf0e10cSrcweir } 1024cdf0e10cSrcweir while ((mag = rtl_cache_depot_dequeue(&(cache->m_depot_empty))) != 0) 1025cdf0e10cSrcweir { 1026cdf0e10cSrcweir rtl_cache_magazine_clear (cache, mag); 1027cdf0e10cSrcweir rtl_cache_free (mag_cache, mag); 1028cdf0e10cSrcweir } 1029cdf0e10cSrcweir } 1030cdf0e10cSrcweir 1031cdf0e10cSrcweir OSL_TRACE( 1032cdf0e10cSrcweir "rtl_cache_deactivate(\"%s\"): " 1033cdf0e10cSrcweir "[slab]: allocs: %"PRIu64", frees: %"PRIu64"; total: %lu, used: %lu; " 1034cdf0e10cSrcweir "[cpu]: allocs: %"PRIu64", frees: %"PRIu64"; " 1035cdf0e10cSrcweir "[total]: allocs: %"PRIu64", frees: %"PRIu64"", 1036cdf0e10cSrcweir cache->m_name, 1037cdf0e10cSrcweir cache->m_slab_stats.m_alloc, cache->m_slab_stats.m_free, 1038cdf0e10cSrcweir cache->m_slab_stats.m_mem_total, cache->m_slab_stats.m_mem_alloc, 1039cdf0e10cSrcweir cache->m_cpu_stats.m_alloc, cache->m_cpu_stats.m_free, 1040cdf0e10cSrcweir cache->m_slab_stats.m_alloc + cache->m_cpu_stats.m_alloc, 1041cdf0e10cSrcweir cache->m_slab_stats.m_free + cache->m_cpu_stats.m_free 1042cdf0e10cSrcweir ); 1043cdf0e10cSrcweir 1044cdf0e10cSrcweir /* cleanup slab layer */ 1045cdf0e10cSrcweir if (cache->m_slab_stats.m_alloc > cache->m_slab_stats.m_free) 1046cdf0e10cSrcweir { 1047cdf0e10cSrcweir OSL_TRACE( 1048cdf0e10cSrcweir "rtl_cache_deactivate(\"%s\"): " 1049cdf0e10cSrcweir "cleaning up %"PRIu64" leaked buffer(s) [%lu bytes] [%lu total]", 1050cdf0e10cSrcweir cache->m_name, 1051cdf0e10cSrcweir cache->m_slab_stats.m_alloc - cache->m_slab_stats.m_free, 1052cdf0e10cSrcweir cache->m_slab_stats.m_mem_alloc, cache->m_slab_stats.m_mem_total 1053cdf0e10cSrcweir ); 1054cdf0e10cSrcweir 1055cdf0e10cSrcweir if (cache->m_features & RTL_CACHE_FEATURE_HASH) 1056cdf0e10cSrcweir { 1057cdf0e10cSrcweir /* cleanup bufctl(s) for leaking buffer(s) */ 1058cdf0e10cSrcweir sal_Size i, n = cache->m_hash_size; 1059cdf0e10cSrcweir for (i = 0; i < n; i++) 1060cdf0e10cSrcweir { 1061cdf0e10cSrcweir rtl_cache_bufctl_type * bufctl; 1062cdf0e10cSrcweir while ((bufctl = cache->m_hash_table[i]) != 0) 1063cdf0e10cSrcweir { 1064cdf0e10cSrcweir /* pop from hash table */ 1065cdf0e10cSrcweir cache->m_hash_table[i] = bufctl->m_next, bufctl->m_next = 0; 1066cdf0e10cSrcweir 1067cdf0e10cSrcweir /* return to bufctl cache */ 1068cdf0e10cSrcweir rtl_cache_free (gp_cache_bufctl_cache, bufctl); 1069cdf0e10cSrcweir } 1070cdf0e10cSrcweir } 1071cdf0e10cSrcweir } 1072cdf0e10cSrcweir { 1073cdf0e10cSrcweir /* force cleanup of remaining slabs */ 1074cdf0e10cSrcweir rtl_cache_slab_type *head, *slab; 1075cdf0e10cSrcweir 1076cdf0e10cSrcweir head = &(cache->m_used_head); 1077cdf0e10cSrcweir for (slab = head->m_slab_next; slab != head; slab = head->m_slab_next) 1078cdf0e10cSrcweir { 1079cdf0e10cSrcweir /* remove from 'used' queue */ 1080cdf0e10cSrcweir QUEUE_REMOVE_NAMED(slab, slab_); 1081cdf0e10cSrcweir 1082cdf0e10cSrcweir /* update stats */ 1083cdf0e10cSrcweir cache->m_slab_stats.m_mem_total -= cache->m_slab_size; 1084cdf0e10cSrcweir 1085cdf0e10cSrcweir /* free slab */ 1086cdf0e10cSrcweir rtl_cache_slab_destroy (cache, slab); 1087cdf0e10cSrcweir } 1088cdf0e10cSrcweir 1089cdf0e10cSrcweir head = &(cache->m_free_head); 1090cdf0e10cSrcweir for (slab = head->m_slab_next; slab != head; slab = head->m_slab_next) 1091cdf0e10cSrcweir { 1092cdf0e10cSrcweir /* remove from 'free' queue */ 1093cdf0e10cSrcweir QUEUE_REMOVE_NAMED(slab, slab_); 1094cdf0e10cSrcweir 1095cdf0e10cSrcweir /* update stats */ 1096cdf0e10cSrcweir cache->m_slab_stats.m_mem_total -= cache->m_slab_size; 1097cdf0e10cSrcweir 1098cdf0e10cSrcweir /* free slab */ 1099cdf0e10cSrcweir rtl_cache_slab_destroy (cache, slab); 1100cdf0e10cSrcweir } 1101cdf0e10cSrcweir } 1102cdf0e10cSrcweir } 1103cdf0e10cSrcweir 1104cdf0e10cSrcweir if (cache->m_hash_table != cache->m_hash_table_0) 1105cdf0e10cSrcweir { 1106cdf0e10cSrcweir rtl_arena_free ( 1107cdf0e10cSrcweir gp_cache_arena, 1108cdf0e10cSrcweir cache->m_hash_table, 1109cdf0e10cSrcweir cache->m_hash_size * sizeof(rtl_cache_bufctl_type*)); 1110cdf0e10cSrcweir 1111cdf0e10cSrcweir cache->m_hash_table = cache->m_hash_table_0; 1112cdf0e10cSrcweir cache->m_hash_size = RTL_CACHE_HASH_SIZE; 1113cdf0e10cSrcweir cache->m_hash_shift = highbit(cache->m_hash_size) - 1; 1114cdf0e10cSrcweir } 1115cdf0e10cSrcweir } 1116cdf0e10cSrcweir 1117cdf0e10cSrcweir /* ================================================================= * 1118cdf0e10cSrcweir * 1119cdf0e10cSrcweir * cache implementation. 1120cdf0e10cSrcweir * 1121cdf0e10cSrcweir * ================================================================= */ 1122cdf0e10cSrcweir 1123cdf0e10cSrcweir /** rtl_cache_create() 1124cdf0e10cSrcweir */ 1125cdf0e10cSrcweir rtl_cache_type * 1126cdf0e10cSrcweir SAL_CALL rtl_cache_create ( 1127cdf0e10cSrcweir const char * name, 1128cdf0e10cSrcweir sal_Size objsize, 1129cdf0e10cSrcweir sal_Size objalign, 1130cdf0e10cSrcweir int (SAL_CALL * constructor)(void * obj, void * userarg), 1131cdf0e10cSrcweir void (SAL_CALL * destructor) (void * obj, void * userarg), 1132cdf0e10cSrcweir void (SAL_CALL * reclaim) (void * userarg), 1133cdf0e10cSrcweir void * userarg, 1134cdf0e10cSrcweir rtl_arena_type * source, 1135cdf0e10cSrcweir int flags 1136cdf0e10cSrcweir ) SAL_THROW_EXTERN_C() 1137cdf0e10cSrcweir { 1138cdf0e10cSrcweir rtl_cache_type * result = 0; 1139cdf0e10cSrcweir sal_Size size = sizeof(rtl_cache_type); 1140cdf0e10cSrcweir 1141cdf0e10cSrcweir try_alloc: 1142cdf0e10cSrcweir result = (rtl_cache_type*)rtl_arena_alloc (gp_cache_arena, &size); 1143cdf0e10cSrcweir if (result != 0) 1144cdf0e10cSrcweir { 1145cdf0e10cSrcweir rtl_cache_type * cache = result; 1146cdf0e10cSrcweir VALGRIND_CREATE_MEMPOOL(cache, 0, 0); 1147cdf0e10cSrcweir (void) rtl_cache_constructor (cache); 1148cdf0e10cSrcweir 1149cdf0e10cSrcweir if (!source) 1150cdf0e10cSrcweir { 1151cdf0e10cSrcweir /* use default arena */ 1152cdf0e10cSrcweir OSL_ASSERT(gp_default_arena != 0); 1153cdf0e10cSrcweir source = gp_default_arena; 1154cdf0e10cSrcweir } 1155cdf0e10cSrcweir 1156cdf0e10cSrcweir result = rtl_cache_activate ( 1157cdf0e10cSrcweir cache, 1158cdf0e10cSrcweir name, 1159cdf0e10cSrcweir objsize, 1160cdf0e10cSrcweir objalign, 1161cdf0e10cSrcweir constructor, 1162cdf0e10cSrcweir destructor, 1163cdf0e10cSrcweir reclaim, 1164cdf0e10cSrcweir userarg, 1165cdf0e10cSrcweir source, 1166cdf0e10cSrcweir flags 1167cdf0e10cSrcweir ); 1168cdf0e10cSrcweir 1169cdf0e10cSrcweir if (result == 0) 1170cdf0e10cSrcweir { 1171cdf0e10cSrcweir /* activation failed */ 1172cdf0e10cSrcweir rtl_cache_deactivate (cache); 1173cdf0e10cSrcweir rtl_cache_destructor (cache); 1174cdf0e10cSrcweir VALGRIND_DESTROY_MEMPOOL(cache); 1175cdf0e10cSrcweir rtl_arena_free (gp_cache_arena, cache, size); 1176cdf0e10cSrcweir } 1177cdf0e10cSrcweir } 1178cdf0e10cSrcweir else if (gp_cache_arena == 0) 1179cdf0e10cSrcweir { 1180cdf0e10cSrcweir if (rtl_cache_init()) 1181cdf0e10cSrcweir { 1182cdf0e10cSrcweir /* try again */ 1183cdf0e10cSrcweir goto try_alloc; 1184cdf0e10cSrcweir } 1185cdf0e10cSrcweir } 1186cdf0e10cSrcweir return (result); 1187cdf0e10cSrcweir } 1188cdf0e10cSrcweir 1189cdf0e10cSrcweir /** rtl_cache_destroy() 1190cdf0e10cSrcweir */ 1191cdf0e10cSrcweir void SAL_CALL rtl_cache_destroy ( 1192cdf0e10cSrcweir rtl_cache_type * cache 1193cdf0e10cSrcweir ) SAL_THROW_EXTERN_C() 1194cdf0e10cSrcweir { 1195cdf0e10cSrcweir if (cache != 0) 1196cdf0e10cSrcweir { 1197cdf0e10cSrcweir rtl_cache_deactivate (cache); 1198cdf0e10cSrcweir rtl_cache_destructor (cache); 1199cdf0e10cSrcweir VALGRIND_DESTROY_MEMPOOL(cache); 1200cdf0e10cSrcweir rtl_arena_free (gp_cache_arena, cache, sizeof(rtl_cache_type)); 1201cdf0e10cSrcweir } 1202cdf0e10cSrcweir } 1203cdf0e10cSrcweir 1204cdf0e10cSrcweir /** rtl_cache_alloc() 1205cdf0e10cSrcweir */ 1206cdf0e10cSrcweir void * 1207cdf0e10cSrcweir SAL_CALL rtl_cache_alloc ( 1208cdf0e10cSrcweir rtl_cache_type * cache 1209cdf0e10cSrcweir ) SAL_THROW_EXTERN_C() 1210cdf0e10cSrcweir { 1211cdf0e10cSrcweir void * obj = 0; 1212cdf0e10cSrcweir 1213cdf0e10cSrcweir if (cache == 0) 1214cdf0e10cSrcweir return (0); 1215cdf0e10cSrcweir 1216cdf0e10cSrcweir if (cache->m_cpu_curr != 0) 1217cdf0e10cSrcweir { 1218cdf0e10cSrcweir RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_depot_lock)); 1219cdf0e10cSrcweir 1220cdf0e10cSrcweir for (;;) 1221cdf0e10cSrcweir { 1222cdf0e10cSrcweir /* take object from magazine layer */ 1223cdf0e10cSrcweir rtl_cache_magazine_type *curr, *prev, *temp; 1224cdf0e10cSrcweir 1225cdf0e10cSrcweir curr = cache->m_cpu_curr; 1226cdf0e10cSrcweir if ((curr != 0) && (curr->m_mag_used > 0)) 1227cdf0e10cSrcweir { 1228cdf0e10cSrcweir obj = curr->m_objects[--curr->m_mag_used]; 1229cdf0e10cSrcweir #if defined(HAVE_VALGRIND_MEMCHECK_H) 1230cdf0e10cSrcweir VALGRIND_MEMPOOL_ALLOC(cache, obj, cache->m_type_size); 1231cdf0e10cSrcweir if (cache->m_constructor != 0) 1232cdf0e10cSrcweir { 1233cdf0e10cSrcweir /* keep constructed object defined */ 1234cdf0e10cSrcweir VALGRIND_MAKE_MEM_DEFINED(obj, cache->m_type_size); 1235cdf0e10cSrcweir } 1236cdf0e10cSrcweir #endif /* HAVE_VALGRIND_MEMCHECK_H */ 1237cdf0e10cSrcweir cache->m_cpu_stats.m_alloc += 1; 1238cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(cache->m_depot_lock)); 1239cdf0e10cSrcweir 1240cdf0e10cSrcweir return (obj); 1241cdf0e10cSrcweir } 1242cdf0e10cSrcweir 1243cdf0e10cSrcweir prev = cache->m_cpu_prev; 1244cdf0e10cSrcweir if ((prev != 0) && (prev->m_mag_used > 0)) 1245cdf0e10cSrcweir { 1246cdf0e10cSrcweir temp = cache->m_cpu_curr; 1247cdf0e10cSrcweir cache->m_cpu_curr = cache->m_cpu_prev; 1248cdf0e10cSrcweir cache->m_cpu_prev = temp; 1249cdf0e10cSrcweir 1250cdf0e10cSrcweir continue; 1251cdf0e10cSrcweir } 1252cdf0e10cSrcweir 1253cdf0e10cSrcweir temp = rtl_cache_depot_exchange_alloc (cache, prev); 1254cdf0e10cSrcweir if (temp != 0) 1255cdf0e10cSrcweir { 1256cdf0e10cSrcweir cache->m_cpu_prev = cache->m_cpu_curr; 1257cdf0e10cSrcweir cache->m_cpu_curr = temp; 1258cdf0e10cSrcweir 1259cdf0e10cSrcweir continue; 1260cdf0e10cSrcweir } 1261cdf0e10cSrcweir 1262cdf0e10cSrcweir /* no full magazine: fall through to slab layer */ 1263cdf0e10cSrcweir break; 1264cdf0e10cSrcweir } 1265cdf0e10cSrcweir 1266cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(cache->m_depot_lock)); 1267cdf0e10cSrcweir } 1268cdf0e10cSrcweir 1269cdf0e10cSrcweir /* alloc buffer from slab layer */ 1270cdf0e10cSrcweir obj = rtl_cache_slab_alloc (cache); 1271cdf0e10cSrcweir if ((obj != 0) && (cache->m_constructor != 0)) 1272cdf0e10cSrcweir { 1273cdf0e10cSrcweir /* construct object */ 1274cdf0e10cSrcweir if (!((cache->m_constructor)(obj, cache->m_userarg))) 1275cdf0e10cSrcweir { 1276cdf0e10cSrcweir /* construction failure */ 1277cdf0e10cSrcweir rtl_cache_slab_free (cache, obj), obj = 0; 1278cdf0e10cSrcweir } 1279cdf0e10cSrcweir } 1280cdf0e10cSrcweir return (obj); 1281cdf0e10cSrcweir } 1282cdf0e10cSrcweir 1283cdf0e10cSrcweir /** rtl_cache_free() 1284cdf0e10cSrcweir */ 1285cdf0e10cSrcweir void 1286cdf0e10cSrcweir SAL_CALL rtl_cache_free ( 1287cdf0e10cSrcweir rtl_cache_type * cache, 1288cdf0e10cSrcweir void * obj 1289cdf0e10cSrcweir ) SAL_THROW_EXTERN_C() 1290cdf0e10cSrcweir { 1291cdf0e10cSrcweir if ((obj != 0) && (cache != 0)) 1292cdf0e10cSrcweir { 1293cdf0e10cSrcweir RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_depot_lock)); 1294cdf0e10cSrcweir 1295cdf0e10cSrcweir for (;;) 1296cdf0e10cSrcweir { 1297cdf0e10cSrcweir /* return object to magazine layer */ 1298cdf0e10cSrcweir rtl_cache_magazine_type *curr, *prev, *temp; 1299cdf0e10cSrcweir 1300cdf0e10cSrcweir curr = cache->m_cpu_curr; 1301cdf0e10cSrcweir if ((curr != 0) && (curr->m_mag_used < curr->m_mag_size)) 1302cdf0e10cSrcweir { 1303cdf0e10cSrcweir curr->m_objects[curr->m_mag_used++] = obj; 1304cdf0e10cSrcweir #if defined(HAVE_VALGRIND_MEMCHECK_H) 1305cdf0e10cSrcweir VALGRIND_MEMPOOL_FREE(cache, obj); 1306cdf0e10cSrcweir #endif /* HAVE_VALGRIND_MEMCHECK_H */ 1307cdf0e10cSrcweir cache->m_cpu_stats.m_free += 1; 1308cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(cache->m_depot_lock)); 1309cdf0e10cSrcweir 1310cdf0e10cSrcweir return; 1311cdf0e10cSrcweir } 1312cdf0e10cSrcweir 1313cdf0e10cSrcweir prev = cache->m_cpu_prev; 1314cdf0e10cSrcweir if ((prev != 0) && (prev->m_mag_used == 0)) 1315cdf0e10cSrcweir { 1316cdf0e10cSrcweir temp = cache->m_cpu_curr; 1317cdf0e10cSrcweir cache->m_cpu_curr = cache->m_cpu_prev; 1318cdf0e10cSrcweir cache->m_cpu_prev = temp; 1319cdf0e10cSrcweir 1320cdf0e10cSrcweir continue; 1321cdf0e10cSrcweir } 1322cdf0e10cSrcweir 1323cdf0e10cSrcweir temp = rtl_cache_depot_exchange_free (cache, prev); 1324cdf0e10cSrcweir if (temp != 0) 1325cdf0e10cSrcweir { 1326cdf0e10cSrcweir cache->m_cpu_prev = cache->m_cpu_curr; 1327cdf0e10cSrcweir cache->m_cpu_curr = temp; 1328cdf0e10cSrcweir 1329cdf0e10cSrcweir continue; 1330cdf0e10cSrcweir } 1331cdf0e10cSrcweir 1332cdf0e10cSrcweir if (rtl_cache_depot_populate(cache) != 0) 1333cdf0e10cSrcweir { 1334cdf0e10cSrcweir continue; 1335cdf0e10cSrcweir } 1336cdf0e10cSrcweir 1337cdf0e10cSrcweir /* no empty magazine: fall through to slab layer */ 1338cdf0e10cSrcweir break; 1339cdf0e10cSrcweir } 1340cdf0e10cSrcweir 1341cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(cache->m_depot_lock)); 1342cdf0e10cSrcweir 1343cdf0e10cSrcweir /* no space for constructed object in magazine layer */ 1344cdf0e10cSrcweir if (cache->m_destructor != 0) 1345cdf0e10cSrcweir { 1346cdf0e10cSrcweir /* destruct object */ 1347cdf0e10cSrcweir (cache->m_destructor)(obj, cache->m_userarg); 1348cdf0e10cSrcweir } 1349cdf0e10cSrcweir 1350cdf0e10cSrcweir /* return buffer to slab layer */ 1351cdf0e10cSrcweir rtl_cache_slab_free (cache, obj); 1352cdf0e10cSrcweir } 1353cdf0e10cSrcweir } 1354cdf0e10cSrcweir 1355cdf0e10cSrcweir /* ================================================================= * 1356cdf0e10cSrcweir * 1357cdf0e10cSrcweir * cache wsupdate (machdep) internals. 1358cdf0e10cSrcweir * 1359cdf0e10cSrcweir * ================================================================= */ 1360cdf0e10cSrcweir 1361cdf0e10cSrcweir /** rtl_cache_wsupdate_init() 1362cdf0e10cSrcweir * 1363cdf0e10cSrcweir * @precond g_cache_list.m_lock initialized 1364cdf0e10cSrcweir */ 1365cdf0e10cSrcweir static void 1366cdf0e10cSrcweir rtl_cache_wsupdate_init (void); 1367cdf0e10cSrcweir 1368cdf0e10cSrcweir 1369cdf0e10cSrcweir /** rtl_cache_wsupdate_wait() 1370cdf0e10cSrcweir * 1371cdf0e10cSrcweir * @precond g_cache_list.m_lock acquired 1372cdf0e10cSrcweir */ 1373cdf0e10cSrcweir static void 1374cdf0e10cSrcweir rtl_cache_wsupdate_wait ( 1375cdf0e10cSrcweir unsigned int seconds 1376cdf0e10cSrcweir ); 1377cdf0e10cSrcweir 1378cdf0e10cSrcweir /** rtl_cache_wsupdate_fini() 1379cdf0e10cSrcweir * 1380cdf0e10cSrcweir */ 1381cdf0e10cSrcweir static void 1382cdf0e10cSrcweir rtl_cache_wsupdate_fini (void); 1383cdf0e10cSrcweir 1384cdf0e10cSrcweir /* ================================================================= */ 1385cdf0e10cSrcweir 1386*87c0c1b4SYuri Dario #if defined(SAL_UNX) 1387cdf0e10cSrcweir 1388cdf0e10cSrcweir #include <sys/time.h> 1389cdf0e10cSrcweir 1390cdf0e10cSrcweir static void * 1391cdf0e10cSrcweir rtl_cache_wsupdate_all (void * arg); 1392cdf0e10cSrcweir 1393cdf0e10cSrcweir static void 1394cdf0e10cSrcweir rtl_cache_wsupdate_init (void) 1395cdf0e10cSrcweir { 1396cdf0e10cSrcweir RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock)); 1397cdf0e10cSrcweir g_cache_list.m_update_done = 0; 1398cdf0e10cSrcweir (void) pthread_cond_init (&(g_cache_list.m_update_cond), NULL); 1399cdf0e10cSrcweir if (pthread_create ( 1400cdf0e10cSrcweir &(g_cache_list.m_update_thread), NULL, rtl_cache_wsupdate_all, (void*)(10)) != 0) 1401cdf0e10cSrcweir { 1402cdf0e10cSrcweir /* failure */ 1403cdf0e10cSrcweir g_cache_list.m_update_thread = (pthread_t)(0); 1404cdf0e10cSrcweir } 1405cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock)); 1406cdf0e10cSrcweir } 1407cdf0e10cSrcweir 1408cdf0e10cSrcweir static void 1409cdf0e10cSrcweir rtl_cache_wsupdate_wait (unsigned int seconds) 1410cdf0e10cSrcweir { 1411cdf0e10cSrcweir if (seconds > 0) 1412cdf0e10cSrcweir { 1413cdf0e10cSrcweir struct timeval now; 1414cdf0e10cSrcweir struct timespec wakeup; 1415cdf0e10cSrcweir 1416cdf0e10cSrcweir gettimeofday(&now, 0); 1417cdf0e10cSrcweir wakeup.tv_sec = now.tv_sec + (seconds); 1418cdf0e10cSrcweir wakeup.tv_nsec = now.tv_usec * 1000; 1419cdf0e10cSrcweir 1420cdf0e10cSrcweir (void) pthread_cond_timedwait ( 1421cdf0e10cSrcweir &(g_cache_list.m_update_cond), 1422cdf0e10cSrcweir &(g_cache_list.m_lock), 1423cdf0e10cSrcweir &wakeup); 1424cdf0e10cSrcweir } 1425cdf0e10cSrcweir } 1426cdf0e10cSrcweir 1427cdf0e10cSrcweir static void 1428cdf0e10cSrcweir rtl_cache_wsupdate_fini (void) 1429cdf0e10cSrcweir { 1430cdf0e10cSrcweir RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock)); 1431cdf0e10cSrcweir g_cache_list.m_update_done = 1; 1432cdf0e10cSrcweir pthread_cond_signal (&(g_cache_list.m_update_cond)); 1433cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock)); 1434cdf0e10cSrcweir 1435cdf0e10cSrcweir if (g_cache_list.m_update_thread != (pthread_t)(0)) 1436cdf0e10cSrcweir pthread_join (g_cache_list.m_update_thread, NULL); 1437cdf0e10cSrcweir } 1438cdf0e10cSrcweir 1439cdf0e10cSrcweir /* ================================================================= */ 1440cdf0e10cSrcweir 1441*87c0c1b4SYuri Dario #elif defined(SAL_OS2) 1442*87c0c1b4SYuri Dario 1443*87c0c1b4SYuri Dario static void 1444*87c0c1b4SYuri Dario rtl_cache_wsupdate_all (void * arg); 1445*87c0c1b4SYuri Dario 1446*87c0c1b4SYuri Dario static void rtl_cache_fini (void); 1447*87c0c1b4SYuri Dario 1448*87c0c1b4SYuri Dario static void 1449*87c0c1b4SYuri Dario rtl_cache_wsupdate_init (void) 1450*87c0c1b4SYuri Dario { 1451*87c0c1b4SYuri Dario ULONG ulThreadId; 1452*87c0c1b4SYuri Dario APIRET rc; 1453*87c0c1b4SYuri Dario 1454*87c0c1b4SYuri Dario RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock)); 1455*87c0c1b4SYuri Dario g_cache_list.m_update_done = 0; 1456*87c0c1b4SYuri Dario 1457*87c0c1b4SYuri Dario // we use atexit() because this allows CRT exit to process handler before 1458*87c0c1b4SYuri Dario // threads are killed. Otherwise with __attribute__(destructor) this 1459*87c0c1b4SYuri Dario // function is called when DosExit starts processing DLL destruction 1460*87c0c1b4SYuri Dario // which happens after ALL threads have been killed... 1461*87c0c1b4SYuri Dario atexit( rtl_cache_fini); 1462*87c0c1b4SYuri Dario 1463*87c0c1b4SYuri Dario //g_cache_list.m_update_cond = CreateEvent (0, TRUE, FALSE, 0); 1464*87c0c1b4SYuri Dario /* Warp3 FP29 or Warp4 FP4 or better required */ 1465*87c0c1b4SYuri Dario rc = DosCreateEventSem( NULL, &g_cache_list.m_update_cond, 0x0800, 0); 1466*87c0c1b4SYuri Dario 1467*87c0c1b4SYuri Dario g_cache_list.m_update_thread = (ULONG) _beginthread( rtl_cache_wsupdate_all, NULL, 1468*87c0c1b4SYuri Dario 65*1024, (void*) 10); 1469*87c0c1b4SYuri Dario RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock)); 1470*87c0c1b4SYuri Dario } 1471*87c0c1b4SYuri Dario 1472*87c0c1b4SYuri Dario static void 1473*87c0c1b4SYuri Dario rtl_cache_wsupdate_wait (unsigned int seconds) 1474*87c0c1b4SYuri Dario { 1475*87c0c1b4SYuri Dario APIRET rc; 1476*87c0c1b4SYuri Dario if (seconds > 0) 1477*87c0c1b4SYuri Dario { 1478*87c0c1b4SYuri Dario RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock)); 1479*87c0c1b4SYuri Dario rc = DosWaitEventSem(g_cache_list.m_update_cond, seconds*1000); 1480*87c0c1b4SYuri Dario RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock)); 1481*87c0c1b4SYuri Dario } 1482*87c0c1b4SYuri Dario } 1483*87c0c1b4SYuri Dario 1484*87c0c1b4SYuri Dario static void 1485*87c0c1b4SYuri Dario rtl_cache_wsupdate_fini (void) 1486*87c0c1b4SYuri Dario { 1487*87c0c1b4SYuri Dario APIRET rc; 1488*87c0c1b4SYuri Dario RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock)); 1489*87c0c1b4SYuri Dario g_cache_list.m_update_done = 1; 1490*87c0c1b4SYuri Dario rc = DosPostEventSem(g_cache_list.m_update_cond); 1491*87c0c1b4SYuri Dario RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock)); 1492*87c0c1b4SYuri Dario rc = DosWaitThread(&g_cache_list.m_update_thread, DCWW_WAIT); 1493*87c0c1b4SYuri Dario } 1494*87c0c1b4SYuri Dario 1495*87c0c1b4SYuri Dario /* ================================================================= */ 1496*87c0c1b4SYuri Dario 1497cdf0e10cSrcweir #elif defined(SAL_W32) 1498cdf0e10cSrcweir 1499cdf0e10cSrcweir static DWORD WINAPI 1500cdf0e10cSrcweir rtl_cache_wsupdate_all (void * arg); 1501cdf0e10cSrcweir 1502cdf0e10cSrcweir static void 1503cdf0e10cSrcweir rtl_cache_wsupdate_init (void) 1504cdf0e10cSrcweir { 1505cdf0e10cSrcweir DWORD dwThreadId; 1506cdf0e10cSrcweir 1507cdf0e10cSrcweir RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock)); 1508cdf0e10cSrcweir g_cache_list.m_update_done = 0; 1509cdf0e10cSrcweir g_cache_list.m_update_cond = CreateEvent (0, TRUE, FALSE, 0); 1510cdf0e10cSrcweir 1511cdf0e10cSrcweir g_cache_list.m_update_thread = 1512cdf0e10cSrcweir CreateThread (NULL, 0, rtl_cache_wsupdate_all, (LPVOID)(10), 0, &dwThreadId); 1513cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock)); 1514cdf0e10cSrcweir } 1515cdf0e10cSrcweir 1516cdf0e10cSrcweir static void 1517cdf0e10cSrcweir rtl_cache_wsupdate_wait (unsigned int seconds) 1518cdf0e10cSrcweir { 1519cdf0e10cSrcweir if (seconds > 0) 1520cdf0e10cSrcweir { 1521cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock)); 1522cdf0e10cSrcweir WaitForSingleObject (g_cache_list.m_update_cond, (DWORD)(seconds * 1000)); 1523cdf0e10cSrcweir RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock)); 1524cdf0e10cSrcweir } 1525cdf0e10cSrcweir } 1526cdf0e10cSrcweir 1527cdf0e10cSrcweir static void 1528cdf0e10cSrcweir rtl_cache_wsupdate_fini (void) 1529cdf0e10cSrcweir { 1530cdf0e10cSrcweir RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock)); 1531cdf0e10cSrcweir g_cache_list.m_update_done = 1; 1532cdf0e10cSrcweir SetEvent (g_cache_list.m_update_cond); 1533cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock)); 1534cdf0e10cSrcweir 1535cdf0e10cSrcweir WaitForSingleObject (g_cache_list.m_update_thread, INFINITE); 1536cdf0e10cSrcweir } 1537cdf0e10cSrcweir 1538cdf0e10cSrcweir #endif /* SAL_UNX || SAL_W32 */ 1539cdf0e10cSrcweir 1540cdf0e10cSrcweir /* ================================================================= */ 1541cdf0e10cSrcweir 1542cdf0e10cSrcweir /** rtl_cache_depot_wsupdate() 1543cdf0e10cSrcweir * update depot stats and purge excess magazines. 1544cdf0e10cSrcweir * 1545cdf0e10cSrcweir * @precond cache->m_depot_lock acquired 1546cdf0e10cSrcweir */ 1547cdf0e10cSrcweir static void 1548cdf0e10cSrcweir rtl_cache_depot_wsupdate ( 1549cdf0e10cSrcweir rtl_cache_type * cache, 1550cdf0e10cSrcweir rtl_cache_depot_type * depot 1551cdf0e10cSrcweir ) 1552cdf0e10cSrcweir { 1553cdf0e10cSrcweir sal_Size npurge; 1554cdf0e10cSrcweir 1555cdf0e10cSrcweir depot->m_prev_min = depot->m_curr_min; 1556cdf0e10cSrcweir depot->m_curr_min = depot->m_mag_count; 1557cdf0e10cSrcweir 1558cdf0e10cSrcweir npurge = SAL_MIN(depot->m_curr_min, depot->m_prev_min); 1559cdf0e10cSrcweir for (; npurge > 0; npurge--) 1560cdf0e10cSrcweir { 1561cdf0e10cSrcweir rtl_cache_magazine_type * mag = rtl_cache_depot_dequeue (depot); 1562cdf0e10cSrcweir if (mag != 0) 1563cdf0e10cSrcweir { 1564cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(cache->m_depot_lock)); 1565cdf0e10cSrcweir rtl_cache_magazine_clear (cache, mag); 1566cdf0e10cSrcweir rtl_cache_free (cache->m_magazine_cache, mag); 1567cdf0e10cSrcweir RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_depot_lock)); 1568cdf0e10cSrcweir } 1569cdf0e10cSrcweir } 1570cdf0e10cSrcweir } 1571cdf0e10cSrcweir 1572cdf0e10cSrcweir /** rtl_cache_wsupdate() 1573cdf0e10cSrcweir * 1574cdf0e10cSrcweir * @precond cache->m_depot_lock released 1575cdf0e10cSrcweir */ 1576cdf0e10cSrcweir static void 1577cdf0e10cSrcweir rtl_cache_wsupdate ( 1578cdf0e10cSrcweir rtl_cache_type * cache 1579cdf0e10cSrcweir ) 1580cdf0e10cSrcweir { 1581cdf0e10cSrcweir if (cache->m_magazine_cache != 0) 1582cdf0e10cSrcweir { 1583cdf0e10cSrcweir RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_depot_lock)); 1584cdf0e10cSrcweir 1585cdf0e10cSrcweir OSL_TRACE( 1586cdf0e10cSrcweir "rtl_cache_wsupdate(\"%s\") " 1587cdf0e10cSrcweir "[depot: count, curr_min, prev_min] " 1588cdf0e10cSrcweir "full: %lu, %lu, %lu; empty: %lu, %lu, %lu", 1589cdf0e10cSrcweir cache->m_name, 1590cdf0e10cSrcweir cache->m_depot_full.m_mag_count, 1591cdf0e10cSrcweir cache->m_depot_full.m_curr_min, 1592cdf0e10cSrcweir cache->m_depot_full.m_prev_min, 1593cdf0e10cSrcweir cache->m_depot_empty.m_mag_count, 1594cdf0e10cSrcweir cache->m_depot_empty.m_curr_min, 1595cdf0e10cSrcweir cache->m_depot_empty.m_prev_min 1596cdf0e10cSrcweir ); 1597cdf0e10cSrcweir 1598cdf0e10cSrcweir rtl_cache_depot_wsupdate (cache, &(cache->m_depot_full)); 1599cdf0e10cSrcweir rtl_cache_depot_wsupdate (cache, &(cache->m_depot_empty)); 1600cdf0e10cSrcweir 1601cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(cache->m_depot_lock)); 1602cdf0e10cSrcweir } 1603cdf0e10cSrcweir } 1604cdf0e10cSrcweir 1605cdf0e10cSrcweir /** rtl_cache_wsupdate_all() 1606cdf0e10cSrcweir * 1607cdf0e10cSrcweir */ 1608*87c0c1b4SYuri Dario #if defined(SAL_UNX) 1609cdf0e10cSrcweir static void * 1610*87c0c1b4SYuri Dario #elif defined(SAL_OS2) 1611*87c0c1b4SYuri Dario static void 1612cdf0e10cSrcweir #elif defined(SAL_W32) 1613cdf0e10cSrcweir static DWORD WINAPI 1614cdf0e10cSrcweir #endif /* SAL_UNX || SAL_W32 */ 1615cdf0e10cSrcweir rtl_cache_wsupdate_all (void * arg) 1616cdf0e10cSrcweir { 1617cdf0e10cSrcweir unsigned int seconds = (unsigned int)SAL_INT_CAST(sal_uIntPtr, arg); 1618cdf0e10cSrcweir 1619cdf0e10cSrcweir RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock)); 1620cdf0e10cSrcweir while (!g_cache_list.m_update_done) 1621cdf0e10cSrcweir { 1622cdf0e10cSrcweir rtl_cache_wsupdate_wait (seconds); 1623cdf0e10cSrcweir if (!g_cache_list.m_update_done) 1624cdf0e10cSrcweir { 1625cdf0e10cSrcweir rtl_cache_type * head, * cache; 1626cdf0e10cSrcweir 1627cdf0e10cSrcweir head = &(g_cache_list.m_cache_head); 1628cdf0e10cSrcweir for (cache = head->m_cache_next; 1629cdf0e10cSrcweir cache != head; 1630cdf0e10cSrcweir cache = cache->m_cache_next) 1631cdf0e10cSrcweir { 1632cdf0e10cSrcweir rtl_cache_wsupdate (cache); 1633cdf0e10cSrcweir } 1634cdf0e10cSrcweir } 1635cdf0e10cSrcweir } 1636cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock)); 1637cdf0e10cSrcweir 1638*87c0c1b4SYuri Dario #if !defined(SAL_OS2) 1639cdf0e10cSrcweir return (0); 1640*87c0c1b4SYuri Dario #endif 1641cdf0e10cSrcweir } 1642cdf0e10cSrcweir 1643cdf0e10cSrcweir /* ================================================================= * 1644cdf0e10cSrcweir * 1645cdf0e10cSrcweir * cache initialization. 1646cdf0e10cSrcweir * 1647cdf0e10cSrcweir * ================================================================= */ 1648cdf0e10cSrcweir 1649cdf0e10cSrcweir static void 1650cdf0e10cSrcweir rtl_cache_once_init (void) 1651cdf0e10cSrcweir { 1652cdf0e10cSrcweir { 1653cdf0e10cSrcweir /* list of caches */ 1654cdf0e10cSrcweir RTL_MEMORY_LOCK_INIT(&(g_cache_list.m_lock)); 1655cdf0e10cSrcweir (void) rtl_cache_constructor (&(g_cache_list.m_cache_head)); 1656cdf0e10cSrcweir } 1657cdf0e10cSrcweir { 1658cdf0e10cSrcweir /* cache: internal arena */ 1659cdf0e10cSrcweir OSL_ASSERT(gp_cache_arena == 0); 1660cdf0e10cSrcweir 1661cdf0e10cSrcweir gp_cache_arena = rtl_arena_create ( 1662cdf0e10cSrcweir "rtl_cache_internal_arena", 1663cdf0e10cSrcweir 64, /* quantum */ 1664cdf0e10cSrcweir 0, /* no quantum caching */ 1665cdf0e10cSrcweir NULL, /* default source */ 1666cdf0e10cSrcweir rtl_arena_alloc, 1667cdf0e10cSrcweir rtl_arena_free, 1668cdf0e10cSrcweir 0 /* flags */ 1669cdf0e10cSrcweir ); 1670cdf0e10cSrcweir OSL_ASSERT(gp_cache_arena != 0); 1671cdf0e10cSrcweir 1672cdf0e10cSrcweir /* check 'gp_default_arena' initialization */ 1673cdf0e10cSrcweir OSL_ASSERT(gp_default_arena != 0); 1674cdf0e10cSrcweir } 1675cdf0e10cSrcweir { 1676cdf0e10cSrcweir /* cache: magazine cache */ 1677cdf0e10cSrcweir static rtl_cache_type g_cache_magazine_cache; 1678cdf0e10cSrcweir 1679cdf0e10cSrcweir OSL_ASSERT(gp_cache_magazine_cache == 0); 1680cdf0e10cSrcweir VALGRIND_CREATE_MEMPOOL(&g_cache_magazine_cache, 0, 0); 1681cdf0e10cSrcweir (void) rtl_cache_constructor (&g_cache_magazine_cache); 1682cdf0e10cSrcweir 1683cdf0e10cSrcweir gp_cache_magazine_cache = rtl_cache_activate ( 1684cdf0e10cSrcweir &g_cache_magazine_cache, 1685cdf0e10cSrcweir "rtl_cache_magazine_cache", 1686cdf0e10cSrcweir sizeof(rtl_cache_magazine_type), /* objsize */ 1687cdf0e10cSrcweir 0, /* objalign */ 1688cdf0e10cSrcweir rtl_cache_magazine_constructor, 1689cdf0e10cSrcweir rtl_cache_magazine_destructor, 1690cdf0e10cSrcweir 0, /* reclaim */ 1691cdf0e10cSrcweir 0, /* userarg: NYI */ 1692cdf0e10cSrcweir gp_default_arena, /* source */ 1693cdf0e10cSrcweir RTL_CACHE_FLAG_NOMAGAZINE /* during bootstrap; activated below */ 1694cdf0e10cSrcweir ); 1695cdf0e10cSrcweir OSL_ASSERT(gp_cache_magazine_cache != 0); 1696cdf0e10cSrcweir 1697cdf0e10cSrcweir /* activate magazine layer */ 1698cdf0e10cSrcweir g_cache_magazine_cache.m_magazine_cache = gp_cache_magazine_cache; 1699cdf0e10cSrcweir } 1700cdf0e10cSrcweir { 1701cdf0e10cSrcweir /* cache: slab (struct) cache */ 1702cdf0e10cSrcweir static rtl_cache_type g_cache_slab_cache; 1703cdf0e10cSrcweir 1704cdf0e10cSrcweir OSL_ASSERT(gp_cache_slab_cache == 0); 1705cdf0e10cSrcweir VALGRIND_CREATE_MEMPOOL(&g_cache_slab_cache, 0, 0); 1706cdf0e10cSrcweir (void) rtl_cache_constructor (&g_cache_slab_cache); 1707cdf0e10cSrcweir 1708cdf0e10cSrcweir gp_cache_slab_cache = rtl_cache_activate ( 1709cdf0e10cSrcweir &g_cache_slab_cache, 1710cdf0e10cSrcweir "rtl_cache_slab_cache", 1711cdf0e10cSrcweir sizeof(rtl_cache_slab_type), /* objsize */ 1712cdf0e10cSrcweir 0, /* objalign */ 1713cdf0e10cSrcweir rtl_cache_slab_constructor, 1714cdf0e10cSrcweir rtl_cache_slab_destructor, 1715cdf0e10cSrcweir 0, /* reclaim */ 1716cdf0e10cSrcweir 0, /* userarg: none */ 1717cdf0e10cSrcweir gp_default_arena, /* source */ 1718cdf0e10cSrcweir 0 /* flags: none */ 1719cdf0e10cSrcweir ); 1720cdf0e10cSrcweir OSL_ASSERT(gp_cache_slab_cache != 0); 1721cdf0e10cSrcweir } 1722cdf0e10cSrcweir { 1723cdf0e10cSrcweir /* cache: bufctl cache */ 1724cdf0e10cSrcweir static rtl_cache_type g_cache_bufctl_cache; 1725cdf0e10cSrcweir 1726cdf0e10cSrcweir OSL_ASSERT(gp_cache_bufctl_cache == 0); 1727cdf0e10cSrcweir VALGRIND_CREATE_MEMPOOL(&g_cache_bufctl_cache, 0, 0); 1728cdf0e10cSrcweir (void) rtl_cache_constructor (&g_cache_bufctl_cache); 1729cdf0e10cSrcweir 1730cdf0e10cSrcweir gp_cache_bufctl_cache = rtl_cache_activate ( 1731cdf0e10cSrcweir &g_cache_bufctl_cache, 1732cdf0e10cSrcweir "rtl_cache_bufctl_cache", 1733cdf0e10cSrcweir sizeof(rtl_cache_bufctl_type), /* objsize */ 1734cdf0e10cSrcweir 0, /* objalign */ 1735cdf0e10cSrcweir 0, /* constructor */ 1736cdf0e10cSrcweir 0, /* destructor */ 1737cdf0e10cSrcweir 0, /* reclaim */ 1738cdf0e10cSrcweir 0, /* userarg */ 1739cdf0e10cSrcweir gp_default_arena, /* source */ 1740cdf0e10cSrcweir 0 /* flags: none */ 1741cdf0e10cSrcweir ); 1742cdf0e10cSrcweir OSL_ASSERT(gp_cache_bufctl_cache != 0); 1743cdf0e10cSrcweir } 1744cdf0e10cSrcweir 1745cdf0e10cSrcweir rtl_cache_wsupdate_init(); 1746cdf0e10cSrcweir } 1747cdf0e10cSrcweir 1748cdf0e10cSrcweir static int 1749cdf0e10cSrcweir rtl_cache_init (void) 1750cdf0e10cSrcweir { 1751cdf0e10cSrcweir static sal_once_type g_once = SAL_ONCE_INIT; 1752cdf0e10cSrcweir SAL_ONCE(&g_once, rtl_cache_once_init); 1753cdf0e10cSrcweir return (gp_cache_arena != 0); 1754cdf0e10cSrcweir } 1755cdf0e10cSrcweir 1756cdf0e10cSrcweir /* ================================================================= */ 1757cdf0e10cSrcweir 1758cdf0e10cSrcweir /* 1759cdf0e10cSrcweir Issue http://udk.openoffice.org/issues/show_bug.cgi?id=92388 1760cdf0e10cSrcweir 1761cdf0e10cSrcweir Mac OS X does not seem to support "__cxa__atexit", thus leading 1762cdf0e10cSrcweir to the situation that "__attribute__((destructor))__" functions 1763cdf0e10cSrcweir (in particular "rtl_{memory|cache|arena}_fini") become called 1764cdf0e10cSrcweir _before_ global C++ object d'tors. 1765cdf0e10cSrcweir 1766cdf0e10cSrcweir Delegated the call to "rtl_cache_fini()" into a dummy C++ object, 1767cdf0e10cSrcweir see alloc_fini.cxx . 1768cdf0e10cSrcweir */ 1769*87c0c1b4SYuri Dario #if defined(__GNUC__) && !defined(MACOSX) && !defined(SAL_OS2) 1770cdf0e10cSrcweir static void rtl_cache_fini (void) __attribute__((destructor)); 1771cdf0e10cSrcweir #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) 1772cdf0e10cSrcweir #pragma fini(rtl_cache_fini) 1773cdf0e10cSrcweir static void rtl_cache_fini (void); 1774cdf0e10cSrcweir #endif /* __GNUC__ || __SUNPRO_C */ 1775cdf0e10cSrcweir 1776cdf0e10cSrcweir void 1777cdf0e10cSrcweir rtl_cache_fini (void) 1778cdf0e10cSrcweir { 1779cdf0e10cSrcweir if (gp_cache_arena != 0) 1780cdf0e10cSrcweir { 1781cdf0e10cSrcweir rtl_cache_type * cache, * head; 1782cdf0e10cSrcweir 1783cdf0e10cSrcweir rtl_cache_wsupdate_fini(); 1784cdf0e10cSrcweir 1785cdf0e10cSrcweir if (gp_cache_bufctl_cache != 0) 1786cdf0e10cSrcweir { 1787cdf0e10cSrcweir cache = gp_cache_bufctl_cache, gp_cache_bufctl_cache = 0; 1788cdf0e10cSrcweir rtl_cache_deactivate (cache); 1789cdf0e10cSrcweir rtl_cache_destructor (cache); 1790cdf0e10cSrcweir VALGRIND_DESTROY_MEMPOOL(cache); 1791cdf0e10cSrcweir } 1792cdf0e10cSrcweir if (gp_cache_slab_cache != 0) 1793cdf0e10cSrcweir { 1794cdf0e10cSrcweir cache = gp_cache_slab_cache, gp_cache_slab_cache = 0; 1795cdf0e10cSrcweir rtl_cache_deactivate (cache); 1796cdf0e10cSrcweir rtl_cache_destructor (cache); 1797cdf0e10cSrcweir VALGRIND_DESTROY_MEMPOOL(cache); 1798cdf0e10cSrcweir } 1799cdf0e10cSrcweir if (gp_cache_magazine_cache != 0) 1800cdf0e10cSrcweir { 1801cdf0e10cSrcweir cache = gp_cache_magazine_cache, gp_cache_magazine_cache = 0; 1802cdf0e10cSrcweir rtl_cache_deactivate (cache); 1803cdf0e10cSrcweir rtl_cache_destructor (cache); 1804cdf0e10cSrcweir VALGRIND_DESTROY_MEMPOOL(cache); 1805cdf0e10cSrcweir } 1806cdf0e10cSrcweir if (gp_cache_arena != 0) 1807cdf0e10cSrcweir { 1808cdf0e10cSrcweir rtl_arena_destroy (gp_cache_arena); 1809cdf0e10cSrcweir gp_cache_arena = 0; 1810cdf0e10cSrcweir } 1811cdf0e10cSrcweir 1812cdf0e10cSrcweir RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock)); 1813cdf0e10cSrcweir head = &(g_cache_list.m_cache_head); 1814cdf0e10cSrcweir for (cache = head->m_cache_next; cache != head; cache = cache->m_cache_next) 1815cdf0e10cSrcweir { 1816cdf0e10cSrcweir OSL_TRACE( 1817cdf0e10cSrcweir "rtl_cache_fini(\"%s\") " 1818cdf0e10cSrcweir "[slab]: allocs: %"PRIu64", frees: %"PRIu64"; total: %lu, used: %lu; " 1819cdf0e10cSrcweir "[cpu]: allocs: %"PRIu64", frees: %"PRIu64"; " 1820cdf0e10cSrcweir "[total]: allocs: %"PRIu64", frees: %"PRIu64"", 1821cdf0e10cSrcweir cache->m_name, 1822cdf0e10cSrcweir cache->m_slab_stats.m_alloc, cache->m_slab_stats.m_free, 1823cdf0e10cSrcweir cache->m_slab_stats.m_mem_total, cache->m_slab_stats.m_mem_alloc, 1824cdf0e10cSrcweir cache->m_cpu_stats.m_alloc, cache->m_cpu_stats.m_free, 1825cdf0e10cSrcweir cache->m_slab_stats.m_alloc + cache->m_cpu_stats.m_alloc, 1826cdf0e10cSrcweir cache->m_slab_stats.m_free + cache->m_cpu_stats.m_free 1827cdf0e10cSrcweir ); 1828cdf0e10cSrcweir } 1829cdf0e10cSrcweir RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock)); 1830cdf0e10cSrcweir } 1831cdf0e10cSrcweir } 1832cdf0e10cSrcweir 1833cdf0e10cSrcweir /* ================================================================= */ 1834