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