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