diff options
Diffstat (limited to 'sal/rtl/source/alloc_cache.c')
-rw-r--r-- | sal/rtl/source/alloc_cache.c | 1739 |
1 files changed, 0 insertions, 1739 deletions
diff --git a/sal/rtl/source/alloc_cache.c b/sal/rtl/source/alloc_cache.c deleted file mode 100644 index dfd86a39a..000000000 --- a/sal/rtl/source/alloc_cache.c +++ /dev/null @@ -1,1739 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -#include "alloc_cache.h" -#include "alloc_impl.h" -#include "alloc_arena.h" -#include "internal/once.h" -#include "sal/macros.h" -#include "osl/diagnose.h" - -#ifndef INCLUDED_STRING_H -#include <string.h> -#endif - -#ifndef INCLUDED_STDIO_H -#include <stdio.h> -#endif - -/* ================================================================= * - * - * cache internals. - * - * ================================================================= */ - -/** g_cache_list - * @internal - */ -struct rtl_cache_list_st -{ - rtl_memory_lock_type m_lock; - rtl_cache_type m_cache_head; - -#if defined(SAL_UNX) - pthread_t m_update_thread; - pthread_cond_t m_update_cond; -#elif defined(SAL_W32) - HANDLE m_update_thread; - HANDLE m_update_cond; -#endif /* SAL_UNX || SAL_W32 */ - int m_update_done; -}; - -static struct rtl_cache_list_st g_cache_list; - - -/** gp_cache_arena - * provided for cache_type allocations, and hash_table resizing. - * - * @internal - */ -static rtl_arena_type * gp_cache_arena = 0; - - -/** gp_cache_magazine_cache - * @internal - */ -static rtl_cache_type * gp_cache_magazine_cache = 0; - - -/** gp_cache_slab_cache - * @internal - */ -static rtl_cache_type * gp_cache_slab_cache = 0; - - -/** gp_cache_bufctl_cache - * @internal - */ -static rtl_cache_type * gp_cache_bufctl_cache = 0; - - -/* ================================================================= */ - -/** RTL_CACHE_HASH_INDEX() - */ -#define RTL_CACHE_HASH_INDEX_IMPL(a, s, q, m) \ - ((((a) + ((a) >> (s)) + ((a) >> ((s) << 1))) >> (q)) & (m)) - -#define RTL_CACHE_HASH_INDEX(cache, addr) \ - RTL_CACHE_HASH_INDEX_IMPL((addr), (cache)->m_hash_shift, (cache)->m_type_shift, ((cache)->m_hash_size - 1)) - - -/** rtl_cache_hash_rescale() - */ -static void -rtl_cache_hash_rescale ( - rtl_cache_type * cache, - sal_Size new_size -) -{ - rtl_cache_bufctl_type ** new_table; - sal_Size new_bytes; - - new_bytes = new_size * sizeof(rtl_cache_bufctl_type*); - new_table = (rtl_cache_bufctl_type**)rtl_arena_alloc(gp_cache_arena, &new_bytes); - - if (new_table != 0) - { - rtl_cache_bufctl_type ** old_table; - sal_Size old_size, i; - - memset (new_table, 0, new_bytes); - - RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_slab_lock)); - - old_table = cache->m_hash_table; - old_size = cache->m_hash_size; - - OSL_TRACE( - "rtl_cache_hash_rescale(\"%s\"): " - "nbuf: % " PRIu64 " (ave: %" PRIu64 "), frees: %" PRIu64 " " - "[old_size: %lu, new_size: %lu]", - cache->m_name, - cache->m_slab_stats.m_alloc - cache->m_slab_stats.m_free, - (cache->m_slab_stats.m_alloc - cache->m_slab_stats.m_free) >> cache->m_hash_shift, - cache->m_slab_stats.m_free, - old_size, new_size); - - cache->m_hash_table = new_table; - cache->m_hash_size = new_size; - cache->m_hash_shift = highbit(cache->m_hash_size) - 1; - - for (i = 0; i < old_size; i++) - { - rtl_cache_bufctl_type * curr = old_table[i]; - while (curr != 0) - { - rtl_cache_bufctl_type * next = curr->m_next; - rtl_cache_bufctl_type ** head; - - head = &(cache->m_hash_table[RTL_CACHE_HASH_INDEX(cache, curr->m_addr)]); - curr->m_next = (*head); - (*head) = curr; - - curr = next; - } - old_table[i] = 0; - } - - RTL_MEMORY_LOCK_RELEASE(&(cache->m_slab_lock)); - - if (old_table != cache->m_hash_table_0) - { - sal_Size old_bytes = old_size * sizeof(rtl_cache_bufctl_type*); - rtl_arena_free (gp_cache_arena, old_table, old_bytes); - } - } -} - -/** rtl_cache_hash_insert() - */ -static RTL_MEMORY_INLINE sal_uIntPtr -rtl_cache_hash_insert ( - rtl_cache_type * cache, - rtl_cache_bufctl_type * bufctl -) -{ - rtl_cache_bufctl_type ** ppHead; - - ppHead = &(cache->m_hash_table[RTL_CACHE_HASH_INDEX(cache, bufctl->m_addr)]); - - bufctl->m_next = (*ppHead); - (*ppHead) = bufctl; - - return (bufctl->m_addr); -} - -#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) -#pragma inline(rtl_cache_hash_insert) -#endif /* __SUNPRO_C */ - - -/** rtl_cache_hash_remove() - */ -static rtl_cache_bufctl_type * -rtl_cache_hash_remove ( - rtl_cache_type * cache, - sal_uIntPtr addr -) -{ - rtl_cache_bufctl_type ** ppHead; - rtl_cache_bufctl_type * bufctl; - sal_Size lookups = 0; - - ppHead = &(cache->m_hash_table[RTL_CACHE_HASH_INDEX(cache, addr)]); - while ((bufctl = *ppHead) != 0) - { - if (bufctl->m_addr == addr) - { - *ppHead = bufctl->m_next, bufctl->m_next = 0; - break; - } - - lookups += 1; - ppHead = &(bufctl->m_next); - } - - OSL_ASSERT (bufctl != 0); /* bad free */ - - if (lookups > 1) - { - sal_Size nbuf = (sal_Size)(cache->m_slab_stats.m_alloc - cache->m_slab_stats.m_free); - if (nbuf > 4 * cache->m_hash_size) - { - if (!(cache->m_features & RTL_CACHE_FEATURE_RESCALE)) - { - sal_Size ave = nbuf >> cache->m_hash_shift; - sal_Size new_size = cache->m_hash_size << (highbit(ave) - 1); - - cache->m_features |= RTL_CACHE_FEATURE_RESCALE; - RTL_MEMORY_LOCK_RELEASE(&(cache->m_slab_lock)); - rtl_cache_hash_rescale (cache, new_size); - RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_slab_lock)); - cache->m_features &= ~RTL_CACHE_FEATURE_RESCALE; - } - } - } - - return (bufctl); -} - -/* ================================================================= */ - -/** RTL_CACHE_SLAB() - */ -#define RTL_CACHE_SLAB(addr, size) \ - (((rtl_cache_slab_type*)(RTL_MEMORY_P2END((sal_uIntPtr)(addr), (size)))) - 1) - - -/** rtl_cache_slab_constructor() - */ -static int -rtl_cache_slab_constructor (void * obj, void * arg) -{ - rtl_cache_slab_type * slab = (rtl_cache_slab_type*)(obj); - - (void) arg; /* unused */ - - QUEUE_START_NAMED(slab, slab_); - slab->m_ntypes = 0; - - return (1); -} - - -/** rtl_cache_slab_destructor() - */ -static void -rtl_cache_slab_destructor (void * obj, void * arg) -{ -#if OSL_DEBUG_LEVEL == 0 - (void) obj; /* unused */ -#else /* OSL_DEBUG_LEVEL */ - rtl_cache_slab_type * slab = (rtl_cache_slab_type*)(obj); - - /* assure removed from queue(s) */ - OSL_ASSERT(QUEUE_STARTED_NAMED(slab, slab_)); - - /* assure no longer referenced */ - OSL_ASSERT(slab->m_ntypes == 0); -#endif /* OSL_DEBUG_LEVEL */ - - (void) arg; /* unused */ -} - - -/** rtl_cache_slab_create() - * - * @precond cache->m_slab_lock released. - */ -static rtl_cache_slab_type * -rtl_cache_slab_create ( - rtl_cache_type * cache -) -{ - rtl_cache_slab_type * slab = 0; - void * addr; - sal_Size size; - - size = cache->m_slab_size; - addr = rtl_arena_alloc (cache->m_source, &size); - if (addr != 0) - { - OSL_ASSERT(size >= cache->m_slab_size); - - if (cache->m_features & RTL_CACHE_FEATURE_HASH) - { - /* allocate slab struct from slab cache */ - OSL_ASSERT (cache != gp_cache_slab_cache); - slab = (rtl_cache_slab_type*)rtl_cache_alloc (gp_cache_slab_cache); - } - else - { - /* construct embedded slab struct */ - slab = RTL_CACHE_SLAB(addr, cache->m_slab_size); - (void) rtl_cache_slab_constructor (slab, 0); - } - if (slab != 0) - { - slab->m_data = (sal_uIntPtr)(addr); - - /* dynamic freelist initialization */ - slab->m_bp = slab->m_data; - slab->m_sp = 0; - } - else - { - rtl_arena_free (cache->m_source, addr, size); - } - } - return (slab); -} - - -/** rtl_cache_slab_destroy() - * - * @precond cache->m_slab_lock released. - */ -static void -rtl_cache_slab_destroy ( - rtl_cache_type * cache, - rtl_cache_slab_type * slab -) -{ - void * addr = (void*)(slab->m_data); - sal_Size refcnt = slab->m_ntypes; slab->m_ntypes = 0; - - if (cache->m_features & RTL_CACHE_FEATURE_HASH) - { - /* cleanup bufctl(s) for free buffer(s) */ - sal_Size ntypes = (slab->m_bp - slab->m_data) / cache->m_type_size; - for (ntypes -= refcnt; slab->m_sp != 0; ntypes--) - { - rtl_cache_bufctl_type * bufctl = slab->m_sp; - - /* pop from freelist */ - slab->m_sp = bufctl->m_next, bufctl->m_next = 0; - - /* return bufctl struct to bufctl cache */ - rtl_cache_free (gp_cache_bufctl_cache, bufctl); - } - OSL_ASSERT(ntypes == 0); - - /* return slab struct to slab cache */ - rtl_cache_free (gp_cache_slab_cache, slab); - } - else - { - /* destruct embedded slab struct */ - rtl_cache_slab_destructor (slab, 0); - } - - if ((refcnt == 0) || (cache->m_features & RTL_CACHE_FEATURE_BULKDESTROY)) - { - /* free memory */ - rtl_arena_free (cache->m_source, addr, cache->m_slab_size); - } -} - - -/** rtl_cache_slab_populate() - * - * @precond cache->m_slab_lock acquired. - */ -static int -rtl_cache_slab_populate ( - rtl_cache_type * cache -) -{ - rtl_cache_slab_type * slab; - - RTL_MEMORY_LOCK_RELEASE(&(cache->m_slab_lock)); - slab = rtl_cache_slab_create (cache); - RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_slab_lock)); - if (slab != 0) - { - /* update buffer start addr w/ current color */ - slab->m_bp += cache->m_ncolor; - - /* update color for next slab */ - cache->m_ncolor += cache->m_type_align; - if (cache->m_ncolor > cache->m_ncolor_max) - cache->m_ncolor = 0; - - /* update stats */ - cache->m_slab_stats.m_mem_total += cache->m_slab_size; - - /* insert onto 'free' queue */ - QUEUE_INSERT_HEAD_NAMED(&(cache->m_free_head), slab, slab_); - } - return (slab != 0); -} - -/* ================================================================= */ - -/** rtl_cache_slab_alloc() - * - * Allocate a buffer from slab layer; used by magazine layer. - */ -static void * -rtl_cache_slab_alloc ( - rtl_cache_type * cache -) -{ - void * addr = 0; - rtl_cache_slab_type * head; - - RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_slab_lock)); - - head = &(cache->m_free_head); - if ((head->m_slab_next != head) || rtl_cache_slab_populate (cache)) - { - rtl_cache_slab_type * slab; - rtl_cache_bufctl_type * bufctl; - - slab = head->m_slab_next; - OSL_ASSERT(slab->m_ntypes < cache->m_ntypes); - - if (slab->m_sp == 0) - { - /* initialize bufctl w/ current 'slab->m_bp' */ - OSL_ASSERT (slab->m_bp < slab->m_data + cache->m_ntypes * cache->m_type_size + cache->m_ncolor_max); - if (cache->m_features & RTL_CACHE_FEATURE_HASH) - { - /* allocate bufctl */ - OSL_ASSERT (cache != gp_cache_bufctl_cache); - bufctl = (rtl_cache_bufctl_type*)rtl_cache_alloc (gp_cache_bufctl_cache); - if (bufctl == 0) - { - /* out of memory */ - RTL_MEMORY_LOCK_RELEASE(&(cache->m_slab_lock)); - return (0); - } - - bufctl->m_addr = slab->m_bp; - bufctl->m_slab = (sal_uIntPtr)(slab); - } - else - { - /* embedded bufctl */ - bufctl = (rtl_cache_bufctl_type*)(slab->m_bp); - } - bufctl->m_next = 0; - - /* update 'slab->m_bp' to next free buffer */ - slab->m_bp += cache->m_type_size; - - /* assign bufctl to freelist */ - slab->m_sp = bufctl; - } - - /* pop front */ - bufctl = slab->m_sp; - slab->m_sp = bufctl->m_next; - - /* increment usage, check for full slab */ - if ((slab->m_ntypes += 1) == cache->m_ntypes) - { - /* remove from 'free' queue */ - QUEUE_REMOVE_NAMED(slab, slab_); - - /* insert onto 'used' queue (tail) */ - QUEUE_INSERT_TAIL_NAMED(&(cache->m_used_head), slab, slab_); - } - - /* update stats */ - cache->m_slab_stats.m_alloc += 1; - cache->m_slab_stats.m_mem_alloc += cache->m_type_size; - - if (cache->m_features & RTL_CACHE_FEATURE_HASH) - addr = (void*)rtl_cache_hash_insert (cache, bufctl); - else - addr = bufctl; - - /* DEBUG ONLY: mark allocated, undefined */ - OSL_DEBUG_ONLY(memset(addr, 0x77777777, cache->m_type_size)); - VALGRIND_MEMPOOL_ALLOC(cache, addr, cache->m_type_size); - } - - RTL_MEMORY_LOCK_RELEASE(&(cache->m_slab_lock)); - return (addr); -} - - -/** rtl_cache_slab_free() - * - * Return a buffer to slab layer; used by magazine layer. - */ -static void -rtl_cache_slab_free ( - rtl_cache_type * cache, - void * addr -) -{ - rtl_cache_bufctl_type * bufctl; - rtl_cache_slab_type * slab; - - RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_slab_lock)); - - /* DEBUG ONLY: mark unallocated, undefined */ - VALGRIND_MEMPOOL_FREE(cache, addr); - /* OSL_DEBUG_ONLY() */ VALGRIND_MAKE_MEM_UNDEFINED(addr, cache->m_type_size); - OSL_DEBUG_ONLY(memset(addr, 0x33333333, cache->m_type_size)); - - /* determine slab from addr */ - if (cache->m_features & RTL_CACHE_FEATURE_HASH) - { - bufctl = rtl_cache_hash_remove (cache, (sal_uIntPtr)(addr)); - slab = (bufctl != 0) ? (rtl_cache_slab_type*)(bufctl->m_slab) : 0; - } - else - { - /* embedded slab struct */ - bufctl = (rtl_cache_bufctl_type*)(addr); - slab = RTL_CACHE_SLAB(addr, cache->m_slab_size); - } - - if (slab != 0) - { - /* check for full slab */ - if (slab->m_ntypes == cache->m_ntypes) - { - /* remove from 'used' queue */ - QUEUE_REMOVE_NAMED(slab, slab_); - - /* insert onto 'free' queue (head) */ - QUEUE_INSERT_HEAD_NAMED(&(cache->m_free_head), slab, slab_); - } - - /* push front */ - bufctl->m_next = slab->m_sp; - slab->m_sp = bufctl; - - /* update stats */ - cache->m_slab_stats.m_free += 1; - cache->m_slab_stats.m_mem_alloc -= cache->m_type_size; - - /* decrement usage, check for empty slab */ - if ((slab->m_ntypes -= 1) == 0) - { - /* remove from 'free' queue */ - QUEUE_REMOVE_NAMED(slab, slab_); - - /* update stats */ - cache->m_slab_stats.m_mem_total -= cache->m_slab_size; - - /* free 'empty' slab */ - RTL_MEMORY_LOCK_RELEASE(&(cache->m_slab_lock)); - rtl_cache_slab_destroy (cache, slab); - return; - } - } - - RTL_MEMORY_LOCK_RELEASE(&(cache->m_slab_lock)); -} - -/* ================================================================= */ - -/** rtl_cache_magazine_constructor() - */ -static int -rtl_cache_magazine_constructor (void * obj, void * arg) -{ - rtl_cache_magazine_type * mag = (rtl_cache_magazine_type*)(obj); - /* @@@ sal_Size size = (sal_Size)(arg); @@@ */ - - (void) arg; /* unused */ - - mag->m_mag_next = 0; - mag->m_mag_size = RTL_CACHE_MAGAZINE_SIZE; - mag->m_mag_used = 0; - - return (1); -} - - -/** rtl_cache_magazine_destructor() - */ -static void -rtl_cache_magazine_destructor (void * obj, void * arg) -{ -#if OSL_DEBUG_LEVEL == 0 - (void) obj; /* unused */ -#else /* OSL_DEBUG_LEVEL */ - rtl_cache_magazine_type * mag = (rtl_cache_magazine_type*)(obj); - - /* assure removed from queue(s) */ - OSL_ASSERT(mag->m_mag_next == 0); - - /* assure no longer referenced */ - OSL_ASSERT(mag->m_mag_used == 0); -#endif /* OSL_DEBUG_LEVEL */ - - (void) arg; /* unused */ -} - - -/** rtl_cache_magazine_clear() - */ -static void -rtl_cache_magazine_clear ( - rtl_cache_type * cache, - rtl_cache_magazine_type * mag -) -{ - for (; mag->m_mag_used > 0; --mag->m_mag_used) - { - void * obj = mag->m_objects[mag->m_mag_used - 1]; - mag->m_objects[mag->m_mag_used - 1] = 0; - - /* DEBUG ONLY: mark cached object allocated, undefined */ - VALGRIND_MEMPOOL_ALLOC(cache, obj, cache->m_type_size); - if (cache->m_destructor != 0) - { - /* DEBUG ONLY: keep constructed object defined */ - VALGRIND_MAKE_MEM_DEFINED(obj, cache->m_type_size); - - /* destruct object */ - (cache->m_destructor)(obj, cache->m_userarg); - } - - /* return buffer to slab layer */ - rtl_cache_slab_free (cache, obj); - } -} - -/* ================================================================= */ - -/** rtl_cache_depot_enqueue() - * - * @precond cache->m_depot_lock acquired. - */ -static RTL_MEMORY_INLINE void -rtl_cache_depot_enqueue ( - rtl_cache_depot_type * depot, - rtl_cache_magazine_type * mag -) -{ - /* enqueue empty magazine */ - mag->m_mag_next = depot->m_mag_next; - depot->m_mag_next = mag; - - /* update depot stats */ - depot->m_mag_count++; -} - -#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) -#pragma inline(rtl_cache_depot_enqueue) -#endif /* __SUNPRO_C */ - - -/** rtl_cache_depot_dequeue() - * - * @precond cache->m_depot_lock acquired. - */ -static RTL_MEMORY_INLINE rtl_cache_magazine_type * -rtl_cache_depot_dequeue ( - rtl_cache_depot_type * depot -) -{ - rtl_cache_magazine_type * mag = 0; - if (depot->m_mag_count > 0) - { - /* dequeue magazine */ - OSL_ASSERT(depot->m_mag_next != 0); - - mag = depot->m_mag_next; - depot->m_mag_next = mag->m_mag_next; - mag->m_mag_next = 0; - - /* update depot stats */ - depot->m_mag_count--; - depot->m_curr_min = SAL_MIN(depot->m_curr_min, depot->m_mag_count); - } - return (mag); -} - -#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) -#pragma inline(rtl_cache_depot_dequeue) -#endif /* __SUNPRO_C */ - - -/** rtl_cache_depot_exchange_alloc() - * - * @precond cache->m_depot_lock acquired. - */ -static RTL_MEMORY_INLINE rtl_cache_magazine_type * -rtl_cache_depot_exchange_alloc ( - rtl_cache_type * cache, - rtl_cache_magazine_type * empty -) -{ - rtl_cache_magazine_type * full; - - OSL_ASSERT((empty == 0) || (empty->m_mag_used == 0)); - - /* dequeue full magazine */ - full = rtl_cache_depot_dequeue (&(cache->m_depot_full)); - if ((full != 0) && (empty != 0)) - { - /* enqueue empty magazine */ - rtl_cache_depot_enqueue (&(cache->m_depot_empty), empty); - } - - OSL_ASSERT((full == 0) || (full->m_mag_used > 0)); - - return (full); -} - -#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) -#pragma inline(rtl_cache_depot_exchange_alloc) -#endif /* __SUNPRO_C */ - - -/** rtl_cache_depot_exchange_free() - * - * @precond cache->m_depot_lock acquired. - */ -static RTL_MEMORY_INLINE rtl_cache_magazine_type * -rtl_cache_depot_exchange_free ( - rtl_cache_type * cache, - rtl_cache_magazine_type * full -) -{ - rtl_cache_magazine_type * empty; - - OSL_ASSERT((full == 0) || (full->m_mag_used > 0)); - - /* dequeue empty magazine */ - empty = rtl_cache_depot_dequeue (&(cache->m_depot_empty)); - if ((empty != 0) && (full != 0)) - { - /* enqueue full magazine */ - rtl_cache_depot_enqueue (&(cache->m_depot_full), full); - } - - OSL_ASSERT((empty == 0) || (empty->m_mag_used == 0)); - - return (empty); -} - -#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) -#pragma inline(rtl_cache_depot_exchange_free) -#endif /* __SUNPRO_C */ - - -/** rtl_cache_depot_populate() - * - * @precond cache->m_depot_lock acquired. - */ -static int -rtl_cache_depot_populate ( - rtl_cache_type * cache -) -{ - rtl_cache_magazine_type * empty = 0; - - if (cache->m_magazine_cache != 0) - { - /* allocate new empty magazine */ - RTL_MEMORY_LOCK_RELEASE(&(cache->m_depot_lock)); - empty = (rtl_cache_magazine_type*)rtl_cache_alloc (cache->m_magazine_cache); - RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_depot_lock)); - if (empty != 0) - { - /* enqueue (new) empty magazine */ - rtl_cache_depot_enqueue (&(cache->m_depot_empty), empty); - } - } - return (empty != 0); -} - -/* ================================================================= */ - -/** rtl_cache_constructor() - */ -static int -rtl_cache_constructor (void * obj) -{ - rtl_cache_type * cache = (rtl_cache_type*)(obj); - - memset (cache, 0, sizeof(rtl_cache_type)); - - /* linkage */ - QUEUE_START_NAMED(cache, cache_); - - /* slab layer */ - (void)RTL_MEMORY_LOCK_INIT(&(cache->m_slab_lock)); - - QUEUE_START_NAMED(&(cache->m_free_head), slab_); - QUEUE_START_NAMED(&(cache->m_used_head), slab_); - - cache->m_hash_table = cache->m_hash_table_0; - cache->m_hash_size = RTL_CACHE_HASH_SIZE; - cache->m_hash_shift = highbit(cache->m_hash_size) - 1; - - /* depot layer */ - (void)RTL_MEMORY_LOCK_INIT(&(cache->m_depot_lock)); - - return (1); -} - -/** rtl_cache_destructor() - */ -static void -rtl_cache_destructor (void * obj) -{ - rtl_cache_type * cache = (rtl_cache_type*)(obj); - - /* linkage */ - OSL_ASSERT(QUEUE_STARTED_NAMED(cache, cache_)); - - /* slab layer */ - (void)RTL_MEMORY_LOCK_DESTROY(&(cache->m_slab_lock)); - - OSL_ASSERT(QUEUE_STARTED_NAMED(&(cache->m_free_head), slab_)); - OSL_ASSERT(QUEUE_STARTED_NAMED(&(cache->m_used_head), slab_)); - - OSL_ASSERT(cache->m_hash_table == cache->m_hash_table_0); - OSL_ASSERT(cache->m_hash_size == RTL_CACHE_HASH_SIZE); - OSL_ASSERT(cache->m_hash_shift == (sal_Size)(highbit(cache->m_hash_size) - 1)); - - /* depot layer */ - (void)RTL_MEMORY_LOCK_DESTROY(&(cache->m_depot_lock)); -} - -/* ================================================================= */ - -/** rtl_cache_activate() - */ -static rtl_cache_type * -rtl_cache_activate ( - rtl_cache_type * cache, - const char * name, - size_t objsize, - size_t objalign, - int (SAL_CALL * constructor)(void * obj, void * userarg), - void (SAL_CALL * destructor) (void * obj, void * userarg), - void (SAL_CALL * reclaim) (void * userarg), - void * userarg, - rtl_arena_type * source, - int flags -) -{ - OSL_ASSERT(cache != 0); - if (cache != 0) - { - sal_Size slabsize; - - snprintf (cache->m_name, sizeof(cache->m_name), "%s", name); - - /* ensure minimum size (embedded bufctl linkage) */ - objsize = SAL_MAX(objsize, sizeof(rtl_cache_bufctl_type*)); - - if (objalign == 0) - { - /* determine default alignment */ - if (objsize >= RTL_MEMORY_ALIGNMENT_8) - objalign = RTL_MEMORY_ALIGNMENT_8; - else - objalign = RTL_MEMORY_ALIGNMENT_4; - } - else - { - /* ensure minimum alignment */ - objalign = SAL_MAX(objalign, RTL_MEMORY_ALIGNMENT_4); - } - OSL_ASSERT(RTL_MEMORY_ISP2(objalign)); - - cache->m_type_size = objsize = RTL_MEMORY_P2ROUNDUP(objsize, objalign); - cache->m_type_align = objalign; - cache->m_type_shift = highbit(cache->m_type_size) - 1; - - cache->m_constructor = constructor; - cache->m_destructor = destructor; - cache->m_reclaim = reclaim; - cache->m_userarg = userarg; - - /* slab layer */ - cache->m_source = source; - - slabsize = source->m_quantum; /* minimum slab size */ - if (flags & RTL_CACHE_FLAG_QUANTUMCACHE) - { - /* next power of 2 above 3 * qcache_max */ - slabsize = SAL_MAX(slabsize, (1UL << highbit(3 * source->m_qcache_max))); - } - else - { - /* waste at most 1/8 of slab */ - slabsize = SAL_MAX(slabsize, cache->m_type_size * 8); - } - - slabsize = RTL_MEMORY_P2ROUNDUP(slabsize, source->m_quantum); - if (!RTL_MEMORY_ISP2(slabsize)) - slabsize = 1UL << highbit(slabsize); - cache->m_slab_size = slabsize; - - if (cache->m_slab_size > source->m_quantum) - { - OSL_ASSERT(gp_cache_slab_cache != 0); - OSL_ASSERT(gp_cache_bufctl_cache != 0); - - cache->m_features |= RTL_CACHE_FEATURE_HASH; - cache->m_ntypes = cache->m_slab_size / cache->m_type_size; - cache->m_ncolor_max = cache->m_slab_size % cache->m_type_size; - } - else - { - /* embedded slab struct */ - cache->m_ntypes = (cache->m_slab_size - sizeof(rtl_cache_slab_type)) / cache->m_type_size; - cache->m_ncolor_max = (cache->m_slab_size - sizeof(rtl_cache_slab_type)) % cache->m_type_size; - } - - OSL_ASSERT(cache->m_ntypes > 0); - cache->m_ncolor = 0; - - if (flags & RTL_CACHE_FLAG_BULKDESTROY) - { - /* allow bulk slab delete upon cache deactivation */ - cache->m_features |= RTL_CACHE_FEATURE_BULKDESTROY; - } - - /* magazine layer */ - if (!(flags & RTL_CACHE_FLAG_NOMAGAZINE)) - { - OSL_ASSERT(gp_cache_magazine_cache != 0); - cache->m_magazine_cache = gp_cache_magazine_cache; - } - - /* insert into cache list */ - RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock)); - QUEUE_INSERT_TAIL_NAMED(&(g_cache_list.m_cache_head), cache, cache_); - RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock)); - } - return (cache); -} - -/** rtl_cache_deactivate() - */ -static void -rtl_cache_deactivate ( - rtl_cache_type * cache -) -{ - int active = 1; - - /* remove from cache list */ - RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock)); - active = QUEUE_STARTED_NAMED(cache, cache_) == 0; - QUEUE_REMOVE_NAMED(cache, cache_); - RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock)); - - OSL_PRECOND(active, "rtl_cache_deactivate(): orphaned cache."); - (void)active; - - /* cleanup magazine layer */ - if (cache->m_magazine_cache != 0) - { - rtl_cache_type * mag_cache; - rtl_cache_magazine_type * mag; - - /* prevent recursion */ - mag_cache = cache->m_magazine_cache, cache->m_magazine_cache = 0; - - /* cleanup cpu layer */ - if ((mag = cache->m_cpu_curr) != 0) - { - cache->m_cpu_curr = 0; - rtl_cache_magazine_clear (cache, mag); - rtl_cache_free (mag_cache, mag); - } - if ((mag = cache->m_cpu_prev) != 0) - { - cache->m_cpu_prev = 0; - rtl_cache_magazine_clear (cache, mag); - rtl_cache_free (mag_cache, mag); - } - - /* cleanup depot layer */ - while ((mag = rtl_cache_depot_dequeue(&(cache->m_depot_full))) != 0) - { - rtl_cache_magazine_clear (cache, mag); - rtl_cache_free (mag_cache, mag); - } - while ((mag = rtl_cache_depot_dequeue(&(cache->m_depot_empty))) != 0) - { - rtl_cache_magazine_clear (cache, mag); - rtl_cache_free (mag_cache, mag); - } - } - - OSL_TRACE( - "rtl_cache_deactivate(\"%s\"): " - "[slab]: allocs: %"PRIu64", frees: %"PRIu64"; total: %lu, used: %lu; " - "[cpu]: allocs: %"PRIu64", frees: %"PRIu64"; " - "[total]: allocs: %"PRIu64", frees: %"PRIu64"", - cache->m_name, - cache->m_slab_stats.m_alloc, cache->m_slab_stats.m_free, - cache->m_slab_stats.m_mem_total, cache->m_slab_stats.m_mem_alloc, - cache->m_cpu_stats.m_alloc, cache->m_cpu_stats.m_free, - cache->m_slab_stats.m_alloc + cache->m_cpu_stats.m_alloc, - cache->m_slab_stats.m_free + cache->m_cpu_stats.m_free - ); - - /* cleanup slab layer */ - if (cache->m_slab_stats.m_alloc > cache->m_slab_stats.m_free) - { - OSL_TRACE( - "rtl_cache_deactivate(\"%s\"): " - "cleaning up %"PRIu64" leaked buffer(s) [%lu bytes] [%lu total]", - cache->m_name, - cache->m_slab_stats.m_alloc - cache->m_slab_stats.m_free, - cache->m_slab_stats.m_mem_alloc, cache->m_slab_stats.m_mem_total - ); - - if (cache->m_features & RTL_CACHE_FEATURE_HASH) - { - /* cleanup bufctl(s) for leaking buffer(s) */ - sal_Size i, n = cache->m_hash_size; - for (i = 0; i < n; i++) - { - rtl_cache_bufctl_type * bufctl; - while ((bufctl = cache->m_hash_table[i]) != 0) - { - /* pop from hash table */ - cache->m_hash_table[i] = bufctl->m_next, bufctl->m_next = 0; - - /* return to bufctl cache */ - rtl_cache_free (gp_cache_bufctl_cache, bufctl); - } - } - } - { - /* force cleanup of remaining slabs */ - rtl_cache_slab_type *head, *slab; - - head = &(cache->m_used_head); - for (slab = head->m_slab_next; slab != head; slab = head->m_slab_next) - { - /* remove from 'used' queue */ - QUEUE_REMOVE_NAMED(slab, slab_); - - /* update stats */ - cache->m_slab_stats.m_mem_total -= cache->m_slab_size; - - /* free slab */ - rtl_cache_slab_destroy (cache, slab); - } - - head = &(cache->m_free_head); - for (slab = head->m_slab_next; slab != head; slab = head->m_slab_next) - { - /* remove from 'free' queue */ - QUEUE_REMOVE_NAMED(slab, slab_); - - /* update stats */ - cache->m_slab_stats.m_mem_total -= cache->m_slab_size; - - /* free slab */ - rtl_cache_slab_destroy (cache, slab); - } - } - } - - if (cache->m_hash_table != cache->m_hash_table_0) - { - rtl_arena_free ( - gp_cache_arena, - cache->m_hash_table, - cache->m_hash_size * sizeof(rtl_cache_bufctl_type*)); - - cache->m_hash_table = cache->m_hash_table_0; - cache->m_hash_size = RTL_CACHE_HASH_SIZE; - cache->m_hash_shift = highbit(cache->m_hash_size) - 1; - } -} - -/* ================================================================= * - * - * cache implementation. - * - * ================================================================= */ - -extern void ensureCacheSingleton(); - -/** rtl_cache_create() - */ -rtl_cache_type * -SAL_CALL rtl_cache_create ( - const char * name, - sal_Size objsize, - sal_Size objalign, - int (SAL_CALL * constructor)(void * obj, void * userarg), - void (SAL_CALL * destructor) (void * obj, void * userarg), - void (SAL_CALL * reclaim) (void * userarg), - void * userarg, - rtl_arena_type * source, - int flags -) SAL_THROW_EXTERN_C() -{ - rtl_cache_type * result = 0; - sal_Size size = sizeof(rtl_cache_type); - -try_alloc: - result = (rtl_cache_type*)rtl_arena_alloc (gp_cache_arena, &size); - if (result != 0) - { - rtl_cache_type * cache = result; - VALGRIND_CREATE_MEMPOOL(cache, 0, 0); - (void) rtl_cache_constructor (cache); - - if (!source) - { - /* use default arena */ - OSL_ASSERT(gp_default_arena != 0); - source = gp_default_arena; - } - - result = rtl_cache_activate ( - cache, - name, - objsize, - objalign, - constructor, - destructor, - reclaim, - userarg, - source, - flags - ); - - if (result == 0) - { - /* activation failed */ - rtl_cache_deactivate (cache); - rtl_cache_destructor (cache); - VALGRIND_DESTROY_MEMPOOL(cache); - rtl_arena_free (gp_cache_arena, cache, size); - } - } - else if (gp_cache_arena == 0) - { - ensureCacheSingleton(); - if (gp_cache_arena) - { - /* try again */ - goto try_alloc; - } - } - return (result); -} - -/** rtl_cache_destroy() - */ -void SAL_CALL rtl_cache_destroy ( - rtl_cache_type * cache -) SAL_THROW_EXTERN_C() -{ - if (cache != 0) - { - rtl_cache_deactivate (cache); - rtl_cache_destructor (cache); - VALGRIND_DESTROY_MEMPOOL(cache); - rtl_arena_free (gp_cache_arena, cache, sizeof(rtl_cache_type)); - } -} - -/** rtl_cache_alloc() - */ -void * -SAL_CALL rtl_cache_alloc ( - rtl_cache_type * cache -) SAL_THROW_EXTERN_C() -{ - void * obj = 0; - - if (cache == 0) - return (0); - - RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_depot_lock)); - if (cache->m_cpu_curr != 0) - { - for (;;) - { - /* take object from magazine layer */ - rtl_cache_magazine_type *curr, *prev, *temp; - - curr = cache->m_cpu_curr; - if ((curr != 0) && (curr->m_mag_used > 0)) - { - obj = curr->m_objects[--curr->m_mag_used]; -#if defined(HAVE_VALGRIND_MEMCHECK_H) - VALGRIND_MEMPOOL_ALLOC(cache, obj, cache->m_type_size); - if (cache->m_constructor != 0) - { - /* keep constructed object defined */ - VALGRIND_MAKE_MEM_DEFINED(obj, cache->m_type_size); - } -#endif /* HAVE_VALGRIND_MEMCHECK_H */ - cache->m_cpu_stats.m_alloc += 1; - RTL_MEMORY_LOCK_RELEASE(&(cache->m_depot_lock)); - - return (obj); - } - - prev = cache->m_cpu_prev; - if ((prev != 0) && (prev->m_mag_used > 0)) - { - temp = cache->m_cpu_curr; - cache->m_cpu_curr = cache->m_cpu_prev; - cache->m_cpu_prev = temp; - - continue; - } - - temp = rtl_cache_depot_exchange_alloc (cache, prev); - if (temp != 0) - { - cache->m_cpu_prev = cache->m_cpu_curr; - cache->m_cpu_curr = temp; - - continue; - } - - /* no full magazine: fall through to slab layer */ - break; - } - } - RTL_MEMORY_LOCK_RELEASE(&(cache->m_depot_lock)); - - /* alloc buffer from slab layer */ - obj = rtl_cache_slab_alloc (cache); - if ((obj != 0) && (cache->m_constructor != 0)) - { - /* construct object */ - if (!((cache->m_constructor)(obj, cache->m_userarg))) - { - /* construction failure */ - rtl_cache_slab_free (cache, obj), obj = 0; - } - } - return (obj); -} - -/** rtl_cache_free() - */ -void -SAL_CALL rtl_cache_free ( - rtl_cache_type * cache, - void * obj -) SAL_THROW_EXTERN_C() -{ - if ((obj != 0) && (cache != 0)) - { - RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_depot_lock)); - - for (;;) - { - /* return object to magazine layer */ - rtl_cache_magazine_type *curr, *prev, *temp; - - curr = cache->m_cpu_curr; - if ((curr != 0) && (curr->m_mag_used < curr->m_mag_size)) - { - curr->m_objects[curr->m_mag_used++] = obj; -#if defined(HAVE_VALGRIND_MEMCHECK_H) - VALGRIND_MEMPOOL_FREE(cache, obj); -#endif /* HAVE_VALGRIND_MEMCHECK_H */ - cache->m_cpu_stats.m_free += 1; - RTL_MEMORY_LOCK_RELEASE(&(cache->m_depot_lock)); - - return; - } - - prev = cache->m_cpu_prev; - if ((prev != 0) && (prev->m_mag_used == 0)) - { - temp = cache->m_cpu_curr; - cache->m_cpu_curr = cache->m_cpu_prev; - cache->m_cpu_prev = temp; - - continue; - } - - temp = rtl_cache_depot_exchange_free (cache, prev); - if (temp != 0) - { - cache->m_cpu_prev = cache->m_cpu_curr; - cache->m_cpu_curr = temp; - - continue; - } - - if (rtl_cache_depot_populate(cache) != 0) - { - continue; - } - - /* no empty magazine: fall through to slab layer */ - break; - } - - RTL_MEMORY_LOCK_RELEASE(&(cache->m_depot_lock)); - - /* no space for constructed object in magazine layer */ - if (cache->m_destructor != 0) - { - /* destruct object */ - (cache->m_destructor)(obj, cache->m_userarg); - } - - /* return buffer to slab layer */ - rtl_cache_slab_free (cache, obj); - } -} - -/* ================================================================= * - * - * cache wsupdate (machdep) internals. - * - * ================================================================= */ - -/** rtl_cache_wsupdate_init() - * - * @precond g_cache_list.m_lock initialized - */ -static void -rtl_cache_wsupdate_init (void); - - -/** rtl_cache_wsupdate_wait() - * - * @precond g_cache_list.m_lock acquired - */ -static void -rtl_cache_wsupdate_wait ( - unsigned int seconds -); - -/** rtl_cache_wsupdate_fini() - * - */ -static void -rtl_cache_wsupdate_fini (void); - -/* ================================================================= */ - -#if defined(SAL_UNX) - -#include <sys/time.h> - -static void * -rtl_cache_wsupdate_all (void * arg); - -static void -rtl_cache_wsupdate_init (void) -{ - RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock)); - g_cache_list.m_update_done = 0; - (void) pthread_cond_init (&(g_cache_list.m_update_cond), NULL); - if (pthread_create ( - &(g_cache_list.m_update_thread), NULL, rtl_cache_wsupdate_all, (void*)(10)) != 0) - { - /* failure */ - g_cache_list.m_update_thread = (pthread_t)(0); - } - RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock)); -} - -static void -rtl_cache_wsupdate_wait (unsigned int seconds) -{ - if (seconds > 0) - { - struct timeval now; - struct timespec wakeup; - - gettimeofday(&now, 0); - wakeup.tv_sec = now.tv_sec + (seconds); - wakeup.tv_nsec = now.tv_usec * 1000; - - (void) pthread_cond_timedwait ( - &(g_cache_list.m_update_cond), - &(g_cache_list.m_lock), - &wakeup); - } -} - -static void -rtl_cache_wsupdate_fini (void) -{ - RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock)); - g_cache_list.m_update_done = 1; - pthread_cond_signal (&(g_cache_list.m_update_cond)); - RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock)); - - if (g_cache_list.m_update_thread != (pthread_t)(0)) - pthread_join (g_cache_list.m_update_thread, NULL); -} - -/* ================================================================= */ - -#elif defined(SAL_W32) - -static DWORD WINAPI -rtl_cache_wsupdate_all (void * arg); - -static void -rtl_cache_wsupdate_init (void) -{ - DWORD dwThreadId; - - RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock)); - g_cache_list.m_update_done = 0; - g_cache_list.m_update_cond = CreateEvent (0, TRUE, FALSE, 0); - - g_cache_list.m_update_thread = - CreateThread (NULL, 0, rtl_cache_wsupdate_all, (LPVOID)(10), 0, &dwThreadId); - RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock)); -} - -static void -rtl_cache_wsupdate_wait (unsigned int seconds) -{ - if (seconds > 0) - { - RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock)); - WaitForSingleObject (g_cache_list.m_update_cond, (DWORD)(seconds * 1000)); - RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock)); - } -} - -static void -rtl_cache_wsupdate_fini (void) -{ - RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock)); - g_cache_list.m_update_done = 1; - SetEvent (g_cache_list.m_update_cond); - RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock)); - - WaitForSingleObject (g_cache_list.m_update_thread, INFINITE); -} - -#endif /* SAL_UNX || SAL_W32 */ - -/* ================================================================= */ - -/** rtl_cache_depot_wsupdate() - * update depot stats and purge excess magazines. - * - * @precond cache->m_depot_lock acquired - */ -static void -rtl_cache_depot_wsupdate ( - rtl_cache_type * cache, - rtl_cache_depot_type * depot -) -{ - sal_Size npurge; - - depot->m_prev_min = depot->m_curr_min; - depot->m_curr_min = depot->m_mag_count; - - npurge = SAL_MIN(depot->m_curr_min, depot->m_prev_min); - for (; npurge > 0; npurge--) - { - rtl_cache_magazine_type * mag = rtl_cache_depot_dequeue (depot); - if (mag != 0) - { - RTL_MEMORY_LOCK_RELEASE(&(cache->m_depot_lock)); - rtl_cache_magazine_clear (cache, mag); - rtl_cache_free (cache->m_magazine_cache, mag); - RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_depot_lock)); - } - } -} - -/** rtl_cache_wsupdate() - * - * @precond cache->m_depot_lock released - */ -static void -rtl_cache_wsupdate ( - rtl_cache_type * cache -) -{ - if (cache->m_magazine_cache != 0) - { - RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_depot_lock)); - - OSL_TRACE( - "rtl_cache_wsupdate(\"%s\") " - "[depot: count, curr_min, prev_min] " - "full: %lu, %lu, %lu; empty: %lu, %lu, %lu", - cache->m_name, - cache->m_depot_full.m_mag_count, - cache->m_depot_full.m_curr_min, - cache->m_depot_full.m_prev_min, - cache->m_depot_empty.m_mag_count, - cache->m_depot_empty.m_curr_min, - cache->m_depot_empty.m_prev_min - ); - - rtl_cache_depot_wsupdate (cache, &(cache->m_depot_full)); - rtl_cache_depot_wsupdate (cache, &(cache->m_depot_empty)); - - RTL_MEMORY_LOCK_RELEASE(&(cache->m_depot_lock)); - } -} - -/** rtl_cache_wsupdate_all() - * - */ -#if defined(SAL_UNX) -static void * -#elif defined(SAL_W32) -static DWORD WINAPI -#endif /* SAL_UNX || SAL_W32 */ -rtl_cache_wsupdate_all (void * arg) -{ - unsigned int seconds = (unsigned int)SAL_INT_CAST(sal_uIntPtr, arg); - - RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock)); - while (!g_cache_list.m_update_done) - { - rtl_cache_wsupdate_wait (seconds); - if (!g_cache_list.m_update_done) - { - rtl_cache_type * head, * cache; - - head = &(g_cache_list.m_cache_head); - for (cache = head->m_cache_next; - cache != head; - cache = cache->m_cache_next) - { - rtl_cache_wsupdate (cache); - } - } - } - RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock)); - - return (0); -} - -/* ================================================================= * - * - * cache initialization. - * - * ================================================================= */ - -void -rtl_cache_init (void) -{ - { - /* list of caches */ - RTL_MEMORY_LOCK_INIT(&(g_cache_list.m_lock)); - (void) rtl_cache_constructor (&(g_cache_list.m_cache_head)); - } - { - /* cache: internal arena */ - OSL_ASSERT(gp_cache_arena == 0); - - gp_cache_arena = rtl_arena_create ( - "rtl_cache_internal_arena", - 64, /* quantum */ - 0, /* no quantum caching */ - NULL, /* default source */ - rtl_arena_alloc, - rtl_arena_free, - 0 /* flags */ - ); - OSL_ASSERT(gp_cache_arena != 0); - - /* check 'gp_default_arena' initialization */ - OSL_ASSERT(gp_default_arena != 0); - } - { - /* cache: magazine cache */ - static rtl_cache_type g_cache_magazine_cache; - - OSL_ASSERT(gp_cache_magazine_cache == 0); - VALGRIND_CREATE_MEMPOOL(&g_cache_magazine_cache, 0, 0); - (void) rtl_cache_constructor (&g_cache_magazine_cache); - - gp_cache_magazine_cache = rtl_cache_activate ( - &g_cache_magazine_cache, - "rtl_cache_magazine_cache", - sizeof(rtl_cache_magazine_type), /* objsize */ - 0, /* objalign */ - rtl_cache_magazine_constructor, - rtl_cache_magazine_destructor, - 0, /* reclaim */ - 0, /* userarg: NYI */ - gp_default_arena, /* source */ - RTL_CACHE_FLAG_NOMAGAZINE /* during bootstrap; activated below */ - ); - OSL_ASSERT(gp_cache_magazine_cache != 0); - - /* activate magazine layer */ - g_cache_magazine_cache.m_magazine_cache = gp_cache_magazine_cache; - } - { - /* cache: slab (struct) cache */ - static rtl_cache_type g_cache_slab_cache; - - OSL_ASSERT(gp_cache_slab_cache == 0); - VALGRIND_CREATE_MEMPOOL(&g_cache_slab_cache, 0, 0); - (void) rtl_cache_constructor (&g_cache_slab_cache); - - gp_cache_slab_cache = rtl_cache_activate ( - &g_cache_slab_cache, - "rtl_cache_slab_cache", - sizeof(rtl_cache_slab_type), /* objsize */ - 0, /* objalign */ - rtl_cache_slab_constructor, - rtl_cache_slab_destructor, - 0, /* reclaim */ - 0, /* userarg: none */ - gp_default_arena, /* source */ - 0 /* flags: none */ - ); - OSL_ASSERT(gp_cache_slab_cache != 0); - } - { - /* cache: bufctl cache */ - static rtl_cache_type g_cache_bufctl_cache; - - OSL_ASSERT(gp_cache_bufctl_cache == 0); - VALGRIND_CREATE_MEMPOOL(&g_cache_bufctl_cache, 0, 0); - (void) rtl_cache_constructor (&g_cache_bufctl_cache); - - gp_cache_bufctl_cache = rtl_cache_activate ( - &g_cache_bufctl_cache, - "rtl_cache_bufctl_cache", - sizeof(rtl_cache_bufctl_type), /* objsize */ - 0, /* objalign */ - 0, /* constructor */ - 0, /* destructor */ - 0, /* reclaim */ - 0, /* userarg */ - gp_default_arena, /* source */ - 0 /* flags: none */ - ); - OSL_ASSERT(gp_cache_bufctl_cache != 0); - } - - rtl_cache_wsupdate_init(); - OSL_TRACE("rtl_cache_init completed"); -} - -/* ================================================================= */ - -void -rtl_cache_fini (void) -{ - if (gp_cache_arena != 0) - { - rtl_cache_type * cache, * head; - - rtl_cache_wsupdate_fini(); - - if (gp_cache_bufctl_cache != 0) - { - cache = gp_cache_bufctl_cache, gp_cache_bufctl_cache = 0; - rtl_cache_deactivate (cache); - rtl_cache_destructor (cache); - VALGRIND_DESTROY_MEMPOOL(cache); - } - if (gp_cache_slab_cache != 0) - { - cache = gp_cache_slab_cache, gp_cache_slab_cache = 0; - rtl_cache_deactivate (cache); - rtl_cache_destructor (cache); - VALGRIND_DESTROY_MEMPOOL(cache); - } - if (gp_cache_magazine_cache != 0) - { - cache = gp_cache_magazine_cache, gp_cache_magazine_cache = 0; - rtl_cache_deactivate (cache); - rtl_cache_destructor (cache); - VALGRIND_DESTROY_MEMPOOL(cache); - } - if (gp_cache_arena != 0) - { - rtl_arena_destroy (gp_cache_arena); - gp_cache_arena = 0; - } - - RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock)); - head = &(g_cache_list.m_cache_head); - for (cache = head->m_cache_next; cache != head; cache = cache->m_cache_next) - { - OSL_TRACE( - "rtl_cache_fini(\"%s\") " - "[slab]: allocs: %"PRIu64", frees: %"PRIu64"; total: %lu, used: %lu; " - "[cpu]: allocs: %"PRIu64", frees: %"PRIu64"; " - "[total]: allocs: %"PRIu64", frees: %"PRIu64"", - cache->m_name, - cache->m_slab_stats.m_alloc, cache->m_slab_stats.m_free, - cache->m_slab_stats.m_mem_total, cache->m_slab_stats.m_mem_alloc, - cache->m_cpu_stats.m_alloc, cache->m_cpu_stats.m_free, - cache->m_slab_stats.m_alloc + cache->m_cpu_stats.m_alloc, - cache->m_slab_stats.m_free + cache->m_cpu_stats.m_free - ); - } - RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock)); - } - OSL_TRACE("rtl_cache_fini completed"); -} - -/* ================================================================= */ - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |