LCOV - code coverage report
Current view: top level - sal/rtl - alloc_cache.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 480 499 96.2 %
Date: 2015-06-13 12:38:46 Functions: 35 35 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11