Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "alloc_arena.hxx"
21 :
22 : #include "alloc_impl.hxx"
23 : #include "internal/rtllifecycle.h"
24 : #include "sal/macros.h"
25 : #include "osl/diagnose.h"
26 :
27 : #include <cassert>
28 : #include <string.h>
29 : #include <stdio.h>
30 :
31 : extern AllocMode alloc_mode;
32 :
33 : /* ================================================================= *
34 : *
35 : * arena internals.
36 : *
37 : * ================================================================= */
38 :
39 : /** g_arena_list
40 : * @internal
41 : */
42 : struct rtl_arena_list_st
43 : {
44 : rtl_memory_lock_type m_lock;
45 : rtl_arena_type m_arena_head;
46 : };
47 :
48 : static rtl_arena_list_st g_arena_list;
49 :
50 : /** gp_arena_arena
51 : * provided for arena_type allocations, and hash_table resizing.
52 : *
53 : * @internal
54 : */
55 : static rtl_arena_type * gp_arena_arena = 0;
56 :
57 : /** gp_machdep_arena
58 : *
59 : * Low level virtual memory (pseudo) arena
60 : * (platform dependent implementation)
61 : *
62 : * @internal
63 : */
64 : static rtl_arena_type * gp_machdep_arena = 0;
65 :
66 : /** gp_default_arena
67 : */
68 : rtl_arena_type * gp_default_arena = 0;
69 :
70 : namespace
71 : {
72 :
73 : void *
74 : SAL_CALL rtl_machdep_alloc (
75 : rtl_arena_type * pArena,
76 : sal_Size * pSize
77 : );
78 :
79 : void
80 : SAL_CALL rtl_machdep_free (
81 : rtl_arena_type * pArena,
82 : void * pAddr,
83 : sal_Size nSize
84 : );
85 :
86 : sal_Size
87 : rtl_machdep_pagesize();
88 :
89 : /* ================================================================= */
90 :
91 : /** rtl_arena_segment_constructor()
92 : */
93 : int
94 1160038 : rtl_arena_segment_constructor (void * obj)
95 : {
96 1160038 : rtl_arena_segment_type * segment = (rtl_arena_segment_type*)(obj);
97 :
98 1160038 : QUEUE_START_NAMED(segment, s);
99 1160038 : QUEUE_START_NAMED(segment, f);
100 :
101 1160038 : return (1);
102 : }
103 :
104 : /** rtl_arena_segment_destructor()
105 : */
106 : void
107 399186 : rtl_arena_segment_destructor (void * obj)
108 : {
109 : rtl_arena_segment_type * segment = static_cast< rtl_arena_segment_type * >(
110 399186 : obj);
111 : assert(QUEUE_STARTED_NAMED(segment, s));
112 : assert(QUEUE_STARTED_NAMED(segment, f));
113 : (void) segment; // avoid warnings
114 399186 : }
115 :
116 : /* ================================================================= */
117 :
118 : /** rtl_arena_segment_populate()
119 : *
120 : * @precond arena->m_lock acquired.
121 : */
122 : bool
123 8432 : rtl_arena_segment_populate (
124 : rtl_arena_type * arena
125 : )
126 : {
127 : rtl_arena_segment_type *span;
128 8432 : sal_Size size = rtl_machdep_pagesize();
129 :
130 : span = static_cast< rtl_arena_segment_type * >(
131 8432 : rtl_machdep_alloc(gp_machdep_arena, &size));
132 8432 : if (span != 0)
133 : {
134 : rtl_arena_segment_type *first, *last, *head;
135 8432 : sal_Size count = size / sizeof(rtl_arena_segment_type);
136 :
137 : /* insert onto reserve span list */
138 8432 : QUEUE_INSERT_TAIL_NAMED(&(arena->m_segment_reserve_span_head), span, s);
139 8432 : QUEUE_START_NAMED(span, f);
140 8432 : span->m_addr = (sal_uIntPtr)(span);
141 8432 : span->m_size = size;
142 8432 : span->m_type = RTL_ARENA_SEGMENT_TYPE_SPAN;
143 :
144 : /* insert onto reserve list */
145 8432 : head = &(arena->m_segment_reserve_head);
146 9865440 : for (first = span + 1, last = span + count; first < last; ++first)
147 : {
148 9857008 : QUEUE_INSERT_TAIL_NAMED(head, first, s);
149 9857008 : QUEUE_START_NAMED(first, f);
150 9857008 : first->m_addr = 0;
151 9857008 : first->m_size = 0;
152 9857008 : first->m_type = 0;
153 : }
154 : }
155 8432 : return (span != 0);
156 : }
157 :
158 : /** rtl_arena_segment_get()
159 : *
160 : * @precond arena->m_lock acquired.
161 : * @precond (*ppSegment == 0)
162 : */
163 : inline void
164 3164133 : rtl_arena_segment_get (
165 : rtl_arena_type * arena,
166 : rtl_arena_segment_type ** ppSegment
167 : )
168 : {
169 : rtl_arena_segment_type * head;
170 :
171 : assert(*ppSegment == 0);
172 :
173 3164133 : head = &(arena->m_segment_reserve_head);
174 3164133 : if ((head->m_snext != head) || rtl_arena_segment_populate (arena))
175 : {
176 3164133 : (*ppSegment) = head->m_snext;
177 3164133 : QUEUE_REMOVE_NAMED((*ppSegment), s);
178 : }
179 3164133 : }
180 :
181 : /** rtl_arena_segment_put()
182 : *
183 : * @precond arena->m_lock acquired.
184 : * @postcond (*ppSegment == 0)
185 : */
186 : inline void
187 3008134 : rtl_arena_segment_put (
188 : rtl_arena_type * arena,
189 : rtl_arena_segment_type ** ppSegment
190 : )
191 : {
192 : rtl_arena_segment_type * head;
193 :
194 : assert(QUEUE_STARTED_NAMED((*ppSegment), s));
195 : assert(QUEUE_STARTED_NAMED((*ppSegment), f));
196 :
197 3008134 : (*ppSegment)->m_addr = 0;
198 3008134 : (*ppSegment)->m_size = 0;
199 :
200 : assert((*ppSegment)->m_type != RTL_ARENA_SEGMENT_TYPE_HEAD);
201 3008134 : (*ppSegment)->m_type = 0;
202 :
203 : /* keep as reserve */
204 3008134 : head = &(arena->m_segment_reserve_head);
205 3008134 : QUEUE_INSERT_HEAD_NAMED(head, (*ppSegment), s);
206 :
207 : /* clear */
208 3008134 : (*ppSegment) = 0;
209 3008134 : }
210 :
211 : /** rtl_arena_freelist_insert()
212 : *
213 : * @precond arena->m_lock acquired.
214 : */
215 : inline void
216 2144236 : rtl_arena_freelist_insert (
217 : rtl_arena_type * arena,
218 : rtl_arena_segment_type * segment
219 : )
220 : {
221 : rtl_arena_segment_type * head;
222 :
223 2144236 : head = &(arena->m_freelist_head[highbit(segment->m_size) - 1]);
224 2144236 : QUEUE_INSERT_TAIL_NAMED(head, segment, f);
225 :
226 2144236 : arena->m_freelist_bitmap |= head->m_size;
227 2144236 : }
228 :
229 : /** rtl_arena_freelist_remove()
230 : *
231 : * @precond arena->m_lock acquired.
232 : */
233 : inline void
234 2102704 : rtl_arena_freelist_remove (
235 : rtl_arena_type * arena,
236 : rtl_arena_segment_type * segment
237 : )
238 : {
239 3536843 : if ((segment->m_fnext->m_type == RTL_ARENA_SEGMENT_TYPE_HEAD) &&
240 1434139 : (segment->m_fprev->m_type == RTL_ARENA_SEGMENT_TYPE_HEAD) )
241 : {
242 : rtl_arena_segment_type * head;
243 :
244 944914 : head = segment->m_fprev;
245 : assert(arena->m_freelist_bitmap & head->m_size);
246 944914 : arena->m_freelist_bitmap ^= head->m_size;
247 : }
248 2102704 : QUEUE_REMOVE_NAMED(segment, f);
249 2102704 : }
250 :
251 : /* ================================================================= */
252 :
253 : /** RTL_ARENA_HASH_INDEX()
254 : */
255 : #define RTL_ARENA_HASH_INDEX_IMPL(a, s, q, m) \
256 : ((((a) + ((a) >> (s)) + ((a) >> ((s) << 1))) >> (q)) & (m))
257 :
258 : #define RTL_ARENA_HASH_INDEX(arena, addr) \
259 : RTL_ARENA_HASH_INDEX_IMPL((addr), (arena)->m_hash_shift, (arena)->m_quantum_shift, ((arena)->m_hash_size - 1))
260 :
261 : /** rtl_arena_hash_rescale()
262 : *
263 : * @precond arena->m_lock released.
264 : */
265 : void
266 228 : rtl_arena_hash_rescale (
267 : rtl_arena_type * arena,
268 : sal_Size new_size
269 : )
270 : {
271 : assert(new_size != 0);
272 :
273 : rtl_arena_segment_type ** new_table;
274 : sal_Size new_bytes;
275 :
276 228 : new_bytes = new_size * sizeof(rtl_arena_segment_type*);
277 228 : new_table = (rtl_arena_segment_type **)rtl_arena_alloc (gp_arena_arena, &new_bytes);
278 :
279 228 : if (new_table != 0)
280 : {
281 : rtl_arena_segment_type ** old_table;
282 : sal_Size old_size, i;
283 :
284 228 : memset (new_table, 0, new_bytes);
285 :
286 228 : RTL_MEMORY_LOCK_ACQUIRE(&(arena->m_lock));
287 :
288 228 : old_table = arena->m_hash_table;
289 228 : old_size = arena->m_hash_size;
290 :
291 : // SAL_INFO(
292 : // "sal.rtl",
293 : // "rtl_arena_hash_rescale(" << arena->m_name << "): nseg: "
294 : // << (arena->m_stats.m_alloc - arena->m_stats.m_free) << " (ave: "
295 : // << ((arena->m_stats.m_alloc - arena->m_stats.m_free)
296 : // >> arena->m_hash_shift)
297 : // << "), frees: " << arena->m_stats.m_free << " [old_size: "
298 : // << old_size << ", new_size: " << new_size << ']');
299 :
300 228 : arena->m_hash_table = new_table;
301 228 : arena->m_hash_size = new_size;
302 228 : arena->m_hash_shift = highbit(arena->m_hash_size) - 1;
303 :
304 14820 : for (i = 0; i < old_size; i++)
305 : {
306 14592 : rtl_arena_segment_type * curr = old_table[i];
307 228745 : while (curr != 0)
308 : {
309 199561 : rtl_arena_segment_type * next = curr->m_fnext;
310 : rtl_arena_segment_type ** head;
311 :
312 199561 : head = &(arena->m_hash_table[RTL_ARENA_HASH_INDEX(arena, curr->m_addr)]);
313 199561 : curr->m_fnext = (*head);
314 199561 : (*head) = curr;
315 :
316 199561 : curr = next;
317 : }
318 14592 : old_table[i] = 0;
319 : }
320 :
321 228 : RTL_MEMORY_LOCK_RELEASE(&(arena->m_lock));
322 :
323 228 : if (old_table != arena->m_hash_table_0)
324 : {
325 0 : sal_Size old_bytes = old_size * sizeof(rtl_arena_segment_type*);
326 0 : rtl_arena_free (gp_arena_arena, old_table, old_bytes);
327 : }
328 : }
329 228 : }
330 :
331 : /** rtl_arena_hash_insert()
332 : * ...and update stats.
333 : */
334 : inline void
335 1690890 : rtl_arena_hash_insert (
336 : rtl_arena_type * arena,
337 : rtl_arena_segment_type * segment
338 : )
339 : {
340 : rtl_arena_segment_type ** ppSegment;
341 :
342 1690890 : ppSegment = &(arena->m_hash_table[RTL_ARENA_HASH_INDEX(arena, segment->m_addr)]);
343 :
344 1690890 : segment->m_fnext = (*ppSegment);
345 1690890 : (*ppSegment) = segment;
346 :
347 1690890 : arena->m_stats.m_alloc += 1;
348 1690890 : arena->m_stats.m_mem_alloc += segment->m_size;
349 1690890 : }
350 :
351 : /** rtl_arena_hash_remove()
352 : * ...and update stats.
353 : */
354 : rtl_arena_segment_type *
355 1593514 : rtl_arena_hash_remove (
356 : rtl_arena_type * arena,
357 : sal_uIntPtr addr,
358 : sal_Size size
359 : )
360 : {
361 : rtl_arena_segment_type *segment, **segpp;
362 1593514 : sal_Size lookups = 0;
363 :
364 1593514 : segpp = &(arena->m_hash_table[RTL_ARENA_HASH_INDEX(arena, addr)]);
365 3291797 : while ((segment = *segpp) != 0)
366 : {
367 1698283 : if (segment->m_addr == addr)
368 : {
369 1593514 : *segpp = segment->m_fnext, segment->m_fnext = segment->m_fprev = segment;
370 1593514 : break;
371 : }
372 :
373 : /* update lookup miss stats */
374 104769 : lookups += 1;
375 104769 : segpp = &(segment->m_fnext);
376 : }
377 :
378 : assert(segment != 0); // bad free
379 1593514 : if (segment != 0)
380 : {
381 : assert(segment->m_size == size);
382 : (void) size; // avoid warnings
383 :
384 1593514 : arena->m_stats.m_free += 1;
385 1593514 : arena->m_stats.m_mem_alloc -= segment->m_size;
386 :
387 1593514 : if (lookups > 1)
388 : {
389 20014 : sal_Size nseg = (sal_Size)(arena->m_stats.m_alloc - arena->m_stats.m_free);
390 20014 : if (nseg > 4 * arena->m_hash_size)
391 : {
392 228 : if (!(arena->m_flags & RTL_ARENA_FLAG_RESCALE))
393 : {
394 228 : sal_Size ave = nseg >> arena->m_hash_shift;
395 : assert(ave != 0);
396 228 : sal_Size new_size = arena->m_hash_size << (highbit(ave) - 1);
397 :
398 228 : arena->m_flags |= RTL_ARENA_FLAG_RESCALE;
399 228 : RTL_MEMORY_LOCK_RELEASE(&(arena->m_lock));
400 228 : rtl_arena_hash_rescale (arena, new_size);
401 228 : RTL_MEMORY_LOCK_ACQUIRE(&(arena->m_lock));
402 228 : arena->m_flags &= ~RTL_ARENA_FLAG_RESCALE;
403 : }
404 : }
405 : }
406 : }
407 :
408 1593514 : return (segment);
409 : }
410 :
411 : /* ================================================================= */
412 :
413 : /** rtl_arena_segment_alloc()
414 : * allocate (and remove) segment from freelist
415 : *
416 : * @precond arena->m_lock acquired
417 : * @precond (*ppSegment == 0)
418 : */
419 : bool
420 1690890 : rtl_arena_segment_alloc (
421 : rtl_arena_type * arena,
422 : sal_Size size,
423 : rtl_arena_segment_type ** ppSegment
424 : )
425 : {
426 1690890 : int index = 0;
427 :
428 : assert(*ppSegment == 0);
429 1690890 : if (!RTL_MEMORY_ISP2(size))
430 : {
431 1258618 : int msb = highbit(size);
432 1258618 : if (RTL_ARENA_FREELIST_SIZE == sal::static_int_cast< size_t >(msb))
433 : {
434 : /* highest possible freelist: fall back to first fit */
435 : rtl_arena_segment_type *head, *segment;
436 :
437 0 : head = &(arena->m_freelist_head[msb - 1]);
438 0 : for (segment = head->m_fnext; segment != head; segment = segment->m_fnext)
439 : {
440 0 : if (segment->m_size >= size)
441 : {
442 : /* allocate first fit segment */
443 0 : (*ppSegment) = segment;
444 0 : break;
445 : }
446 : }
447 0 : goto dequeue_and_leave;
448 : }
449 :
450 : /* roundup to next power of 2 */
451 1258618 : size = (((sal_Size)1) << msb);
452 : }
453 :
454 1690890 : index = lowbit(RTL_MEMORY_P2ALIGN(arena->m_freelist_bitmap, size));
455 1690890 : if (index > 0)
456 : {
457 : /* instant fit: allocate first free segment */
458 : rtl_arena_segment_type *head;
459 :
460 814010 : head = &(arena->m_freelist_head[index - 1]);
461 814010 : (*ppSegment) = head->m_fnext;
462 : assert((*ppSegment) != head);
463 : }
464 :
465 : dequeue_and_leave:
466 1690890 : if (*ppSegment != 0)
467 : {
468 : /* remove from freelist */
469 814010 : rtl_arena_freelist_remove (arena, (*ppSegment));
470 : }
471 1690890 : return (*ppSegment != 0);
472 : }
473 :
474 : /** rtl_arena_segment_create()
475 : * import new (span) segment from source arena
476 : *
477 : * @precond arena->m_lock acquired
478 : * @precond (*ppSegment == 0)
479 : */
480 : int
481 876880 : rtl_arena_segment_create (
482 : rtl_arena_type * arena,
483 : sal_Size size,
484 : rtl_arena_segment_type ** ppSegment
485 : )
486 : {
487 : assert((*ppSegment) == 0);
488 876880 : if (arena->m_source_alloc != 0)
489 : {
490 876880 : rtl_arena_segment_get (arena, ppSegment);
491 876880 : if (*ppSegment != 0)
492 : {
493 876880 : rtl_arena_segment_type * span = 0;
494 876880 : rtl_arena_segment_get (arena, &span);
495 876880 : if (span != 0)
496 : {
497 : /* import new span from source arena */
498 876880 : RTL_MEMORY_LOCK_RELEASE(&(arena->m_lock));
499 :
500 876880 : span->m_size = size;
501 : span->m_addr = (sal_uIntPtr)(arena->m_source_alloc)(
502 876880 : arena->m_source_arena, &(span->m_size));
503 :
504 876880 : RTL_MEMORY_LOCK_ACQUIRE(&(arena->m_lock));
505 876880 : if (span->m_addr != 0)
506 : {
507 : /* insert onto segment list, update stats */
508 876880 : span->m_type = RTL_ARENA_SEGMENT_TYPE_SPAN;
509 876880 : QUEUE_INSERT_HEAD_NAMED(&(arena->m_segment_head), span, s);
510 876880 : arena->m_stats.m_mem_total += span->m_size;
511 :
512 876880 : (*ppSegment)->m_addr = span->m_addr;
513 876880 : (*ppSegment)->m_size = span->m_size;
514 876880 : (*ppSegment)->m_type = RTL_ARENA_SEGMENT_TYPE_FREE;
515 876880 : QUEUE_INSERT_HEAD_NAMED(span, (*ppSegment), s);
516 :
517 : /* report success */
518 876880 : return (1);
519 : }
520 0 : rtl_arena_segment_put (arena, &span);
521 : }
522 0 : rtl_arena_segment_put (arena, ppSegment);
523 : }
524 : }
525 0 : return (0);
526 : }
527 :
528 : /** rtl_arena_segment_coalesce()
529 : * mark as free and join with adjacent free segment(s)
530 : *
531 : * @precond arena->m_lock acquired
532 : * @precond segment marked 'used'
533 : */
534 : void
535 1593560 : rtl_arena_segment_coalesce (
536 : rtl_arena_type * arena,
537 : rtl_arena_segment_type * segment
538 : )
539 : {
540 : rtl_arena_segment_type *next, *prev;
541 :
542 : /* mark segment free */
543 : assert(segment->m_type == RTL_ARENA_SEGMENT_TYPE_USED);
544 1593560 : segment->m_type = RTL_ARENA_SEGMENT_TYPE_FREE;
545 :
546 : /* try to merge w/ next segment */
547 1593560 : next = segment->m_snext;
548 1593560 : if (next->m_type == RTL_ARENA_SEGMENT_TYPE_FREE)
549 : {
550 : assert(segment->m_addr + segment->m_size == next->m_addr);
551 934991 : segment->m_size += next->m_size;
552 :
553 : /* remove from freelist */
554 934991 : rtl_arena_freelist_remove (arena, next);
555 :
556 : /* remove from segment list */
557 934991 : QUEUE_REMOVE_NAMED(next, s);
558 :
559 : /* release segment descriptor */
560 934991 : rtl_arena_segment_put (arena, &next);
561 : }
562 :
563 : /* try to merge w/ prev segment */
564 1593560 : prev = segment->m_sprev;
565 1593560 : if (prev->m_type == RTL_ARENA_SEGMENT_TYPE_FREE)
566 : {
567 : assert(prev->m_addr + prev->m_size == segment->m_addr);
568 353657 : segment->m_addr = prev->m_addr;
569 353657 : segment->m_size += prev->m_size;
570 :
571 : /* remove from freelist */
572 353657 : rtl_arena_freelist_remove (arena, prev);
573 :
574 : /* remove from segment list */
575 353657 : QUEUE_REMOVE_NAMED(prev, s);
576 :
577 : /* release segment descriptor */
578 353657 : rtl_arena_segment_put (arena, &prev);
579 : }
580 1593560 : }
581 :
582 : /* ================================================================= */
583 :
584 : /** rtl_arena_constructor()
585 : */
586 : void
587 17314 : rtl_arena_constructor (void * obj)
588 : {
589 17314 : rtl_arena_type * arena = (rtl_arena_type*)(obj);
590 : rtl_arena_segment_type * head;
591 : size_t i;
592 :
593 17314 : memset (arena, 0, sizeof(rtl_arena_type));
594 :
595 17314 : QUEUE_START_NAMED(arena, arena_);
596 :
597 17314 : (void) RTL_MEMORY_LOCK_INIT(&(arena->m_lock));
598 :
599 17314 : head = &(arena->m_segment_reserve_span_head);
600 17314 : rtl_arena_segment_constructor (head);
601 17314 : head->m_type = RTL_ARENA_SEGMENT_TYPE_HEAD;
602 :
603 17314 : head = &(arena->m_segment_reserve_head);
604 17314 : rtl_arena_segment_constructor (head);
605 17314 : head->m_type = RTL_ARENA_SEGMENT_TYPE_HEAD;
606 :
607 17314 : head = &(arena->m_segment_head);
608 17314 : rtl_arena_segment_constructor (head);
609 17314 : head->m_type = RTL_ARENA_SEGMENT_TYPE_HEAD;
610 :
611 1125410 : for (i = 0; i < RTL_ARENA_FREELIST_SIZE; i++)
612 : {
613 1108096 : head = &(arena->m_freelist_head[i]);
614 1108096 : rtl_arena_segment_constructor (head);
615 :
616 1108096 : head->m_size = (((sal_Size)1) << i);
617 1108096 : head->m_type = RTL_ARENA_SEGMENT_TYPE_HEAD;
618 : }
619 :
620 17314 : arena->m_hash_table = arena->m_hash_table_0;
621 17314 : arena->m_hash_size = RTL_ARENA_HASH_SIZE;
622 17314 : arena->m_hash_shift = highbit(arena->m_hash_size) - 1;
623 17314 : }
624 :
625 : /** rtl_arena_destructor()
626 : */
627 : void
628 5958 : rtl_arena_destructor (void * obj)
629 : {
630 5958 : rtl_arena_type * arena = (rtl_arena_type*)(obj);
631 : rtl_arena_segment_type * head;
632 : size_t i;
633 :
634 : assert(QUEUE_STARTED_NAMED(arena, arena_));
635 :
636 5958 : RTL_MEMORY_LOCK_DESTROY(&(arena->m_lock));
637 :
638 5958 : head = &(arena->m_segment_reserve_span_head);
639 : assert(head->m_type == RTL_ARENA_SEGMENT_TYPE_HEAD);
640 5958 : rtl_arena_segment_destructor (head);
641 :
642 5958 : head = &(arena->m_segment_reserve_head);
643 : assert(head->m_type == RTL_ARENA_SEGMENT_TYPE_HEAD);
644 5958 : rtl_arena_segment_destructor (head);
645 :
646 5958 : head = &(arena->m_segment_head);
647 : assert(head->m_type == RTL_ARENA_SEGMENT_TYPE_HEAD);
648 5958 : rtl_arena_segment_destructor (head);
649 :
650 387270 : for (i = 0; i < RTL_ARENA_FREELIST_SIZE; i++)
651 : {
652 381312 : head = &(arena->m_freelist_head[i]);
653 :
654 : assert(head->m_size == (((sal_Size)1) << i));
655 : assert(head->m_type == RTL_ARENA_SEGMENT_TYPE_HEAD);
656 :
657 381312 : rtl_arena_segment_destructor (head);
658 : }
659 :
660 : assert(arena->m_hash_table == arena->m_hash_table_0);
661 : assert(arena->m_hash_size == RTL_ARENA_HASH_SIZE);
662 : assert(
663 : arena->m_hash_shift ==
664 : sal::static_int_cast< unsigned >(highbit(arena->m_hash_size) - 1));
665 5958 : }
666 :
667 : /* ================================================================= */
668 :
669 : /** rtl_arena_activate()
670 : */
671 : rtl_arena_type *
672 14476 : rtl_arena_activate (
673 : rtl_arena_type * arena,
674 : const char * name,
675 : sal_Size quantum,
676 : sal_Size quantum_cache_max,
677 : rtl_arena_type * source_arena,
678 : void * (SAL_CALL * source_alloc)(rtl_arena_type *, sal_Size *),
679 : void (SAL_CALL * source_free) (rtl_arena_type *, void *, sal_Size)
680 : )
681 : {
682 : assert(arena != 0);
683 14476 : if (arena != 0)
684 : {
685 14476 : (void) snprintf (arena->m_name, sizeof(arena->m_name), "%s", name);
686 :
687 14476 : if (!RTL_MEMORY_ISP2(quantum))
688 : {
689 : /* roundup to next power of 2 */
690 0 : quantum = (((sal_Size)1) << highbit(quantum));
691 : }
692 14476 : quantum_cache_max = RTL_MEMORY_P2ROUNDUP(quantum_cache_max, quantum);
693 :
694 14476 : arena->m_quantum = quantum;
695 14476 : arena->m_quantum_shift = highbit(arena->m_quantum) - 1;
696 14476 : arena->m_qcache_max = quantum_cache_max;
697 :
698 14476 : arena->m_source_arena = source_arena;
699 14476 : arena->m_source_alloc = source_alloc;
700 14476 : arena->m_source_free = source_free;
701 :
702 14476 : if (arena->m_qcache_max > 0)
703 : {
704 : char namebuf[RTL_ARENA_NAME_LENGTH + 1];
705 0 : int i, n = (arena->m_qcache_max >> arena->m_quantum_shift);
706 :
707 0 : sal_Size size = n * sizeof(rtl_cache_type*);
708 0 : arena->m_qcache_ptr = (rtl_cache_type**)rtl_arena_alloc (gp_arena_arena, &size);
709 0 : if (!(arena->m_qcache_ptr))
710 : {
711 : /* out of memory */
712 0 : return (0);
713 : }
714 0 : for (i = 1; i <= n; i++)
715 : {
716 0 : size = i * arena->m_quantum;
717 0 : (void) snprintf (namebuf, sizeof(namebuf), "%s_%" SAL_PRIuUINTPTR, arena->m_name, size);
718 0 : arena->m_qcache_ptr[i - 1] = rtl_cache_create(namebuf, size, 0, NULL, NULL, NULL, NULL, arena, RTL_CACHE_FLAG_QUANTUMCACHE);
719 : }
720 : }
721 :
722 : /* insert into arena list */
723 14476 : RTL_MEMORY_LOCK_ACQUIRE(&(g_arena_list.m_lock));
724 14476 : QUEUE_INSERT_TAIL_NAMED(&(g_arena_list.m_arena_head), arena, arena_);
725 14476 : RTL_MEMORY_LOCK_RELEASE(&(g_arena_list.m_lock));
726 : }
727 14476 : return (arena);
728 : }
729 :
730 : /** rtl_arena_deactivate()
731 : */
732 : void
733 5958 : rtl_arena_deactivate (
734 : rtl_arena_type * arena
735 : )
736 : {
737 : rtl_arena_segment_type * head, * segment;
738 :
739 : /* remove from arena list */
740 5958 : RTL_MEMORY_LOCK_ACQUIRE(&(g_arena_list.m_lock));
741 5958 : QUEUE_REMOVE_NAMED(arena, arena_);
742 5958 : RTL_MEMORY_LOCK_RELEASE(&(g_arena_list.m_lock));
743 :
744 : /* cleanup quantum cache(s) */
745 5958 : if ((arena->m_qcache_max > 0) && (arena->m_qcache_ptr != 0))
746 : {
747 0 : int i, n = (arena->m_qcache_max >> arena->m_quantum_shift);
748 0 : for (i = 1; i <= n; i++)
749 : {
750 0 : if (arena->m_qcache_ptr[i - 1] != 0)
751 : {
752 0 : rtl_cache_destroy (arena->m_qcache_ptr[i - 1]);
753 0 : arena->m_qcache_ptr[i - 1] = 0;
754 : }
755 : }
756 : rtl_arena_free (
757 : gp_arena_arena,
758 : arena->m_qcache_ptr,
759 0 : n * sizeof(rtl_cache_type*));
760 :
761 0 : arena->m_qcache_ptr = 0;
762 : }
763 :
764 : /* check for leaked segments */
765 : // SAL_INFO(
766 : // "sal.rtl",
767 : // "rtl_arena_deactivate(" << arena->m_name << "): allocs: "
768 : // << arena->m_stats.m_alloc << ", frees: " << arena->m_stats.m_free
769 : // << "; total: " << arena->m_stats.m_mem_total << ", used: "
770 : // << arena->m_stats.m_mem_alloc);
771 5958 : if (arena->m_stats.m_alloc > arena->m_stats.m_free)
772 : {
773 : sal_Size i, n;
774 :
775 : // SAL_INFO(
776 : // "sal.rtl",
777 : // "rtl_arena_deactivate(" << arena->m_name << "): cleaning up "
778 : // << (arena->m_stats.m_alloc - arena->m_stats.m_free)
779 : // << " leaked segment(s) [" << arena->m_stats.m_mem_alloc
780 : // << " bytes]");
781 :
782 : /* cleanup still used segment(s) */
783 910 : for (i = 0, n = arena->m_hash_size; i < n; i++)
784 : {
785 1838 : while ((segment = arena->m_hash_table[i]) != 0)
786 : {
787 : /* pop from hash table */
788 46 : arena->m_hash_table[i] = segment->m_fnext, segment->m_fnext = segment->m_fprev = segment;
789 :
790 : /* coalesce w/ adjacent free segment(s) */
791 46 : rtl_arena_segment_coalesce (arena, segment);
792 :
793 : /* insert onto freelist */
794 46 : rtl_arena_freelist_insert (arena, segment);
795 : }
796 : }
797 : }
798 :
799 : /* cleanup hash table */
800 5958 : if (arena->m_hash_table != arena->m_hash_table_0)
801 : {
802 : rtl_arena_free (
803 : gp_arena_arena,
804 : arena->m_hash_table,
805 0 : arena->m_hash_size * sizeof(rtl_arena_segment_type*));
806 :
807 0 : arena->m_hash_table = arena->m_hash_table_0;
808 0 : arena->m_hash_size = RTL_ARENA_HASH_SIZE;
809 0 : arena->m_hash_shift = highbit(arena->m_hash_size) - 1;
810 : }
811 :
812 : /* cleanup segment list */
813 5958 : head = &(arena->m_segment_head);
814 6050 : for (segment = head->m_snext; segment != head; segment = head->m_snext)
815 : {
816 92 : if (segment->m_type == RTL_ARENA_SEGMENT_TYPE_FREE)
817 : {
818 : /* remove from freelist */
819 46 : rtl_arena_freelist_remove (arena, segment);
820 : }
821 : else
822 : {
823 : /* can have only free and span segments here */
824 : assert(segment->m_type == RTL_ARENA_SEGMENT_TYPE_SPAN);
825 : }
826 :
827 : /* remove from segment list */
828 92 : QUEUE_REMOVE_NAMED(segment, s);
829 :
830 : /* release segment descriptor */
831 92 : rtl_arena_segment_put (arena, &segment);
832 : }
833 :
834 : /* cleanup segment reserve list */
835 5958 : head = &(arena->m_segment_reserve_head);
836 3924446 : for (segment = head->m_snext; segment != head; segment = head->m_snext)
837 : {
838 : /* remove from segment list */
839 3918488 : QUEUE_REMOVE_NAMED(segment, s);
840 : }
841 :
842 : /* cleanup segment reserve span(s) */
843 5958 : head = &(arena->m_segment_reserve_span_head);
844 9310 : for (segment = head->m_snext; segment != head; segment = head->m_snext)
845 : {
846 : /* can have only span segments here */
847 : assert(segment->m_type == RTL_ARENA_SEGMENT_TYPE_SPAN);
848 :
849 : /* remove from segment list */
850 3352 : QUEUE_REMOVE_NAMED(segment, s);
851 :
852 : /* return span to g_machdep_arena */
853 3352 : rtl_machdep_free (gp_machdep_arena, (void*)(segment->m_addr), segment->m_size);
854 : }
855 5958 : }
856 :
857 : } //namespace
858 : /* ================================================================= *
859 : *
860 : * arena implementation.
861 : *
862 : * ================================================================= */
863 :
864 : /** rtl_arena_create()
865 : */
866 : rtl_arena_type *
867 5962 : SAL_CALL rtl_arena_create (
868 : const char * name,
869 : sal_Size quantum,
870 : sal_Size quantum_cache_max,
871 : rtl_arena_type * source_arena,
872 : void * (SAL_CALL * source_alloc)(rtl_arena_type *, sal_Size *),
873 : void (SAL_CALL * source_free) (rtl_arena_type *, void *, sal_Size),
874 : SAL_UNUSED_PARAMETER int
875 : ) SAL_THROW_EXTERN_C()
876 : {
877 5962 : rtl_arena_type * result = 0;
878 5962 : sal_Size size = sizeof(rtl_arena_type);
879 :
880 : try_alloc:
881 8800 : result = (rtl_arena_type*)rtl_arena_alloc (gp_arena_arena, &size);
882 8800 : if (result != 0)
883 : {
884 5962 : rtl_arena_type * arena = result;
885 5962 : rtl_arena_constructor (arena);
886 :
887 5962 : if (!source_arena)
888 : {
889 : assert(gp_default_arena != 0);
890 5962 : source_arena = gp_default_arena;
891 : }
892 :
893 : result = rtl_arena_activate (
894 : arena,
895 : name,
896 : quantum,
897 : quantum_cache_max,
898 : source_arena,
899 : source_alloc,
900 : source_free
901 5962 : );
902 :
903 5962 : if (result == 0)
904 : {
905 0 : rtl_arena_deactivate (arena);
906 0 : rtl_arena_destructor (arena);
907 0 : rtl_arena_free (gp_arena_arena, arena, size);
908 : }
909 : }
910 2838 : else if (gp_arena_arena == 0)
911 : {
912 2838 : ensureArenaSingleton();
913 2838 : if (gp_arena_arena)
914 : {
915 : /* try again */
916 2838 : goto try_alloc;
917 : }
918 : }
919 5962 : return (result);
920 : }
921 :
922 : /** rtl_arena_destroy()
923 : */
924 : void
925 5958 : SAL_CALL rtl_arena_destroy (
926 : rtl_arena_type * arena
927 : ) SAL_THROW_EXTERN_C()
928 : {
929 5958 : if (arena != 0)
930 : {
931 5958 : rtl_arena_deactivate (arena);
932 5958 : rtl_arena_destructor (arena);
933 5958 : rtl_arena_free (gp_arena_arena, arena, sizeof(rtl_arena_type));
934 : }
935 5958 : }
936 :
937 : /** rtl_arena_alloc()
938 : */
939 : void *
940 1698970 : SAL_CALL rtl_arena_alloc (
941 : rtl_arena_type * arena,
942 : sal_Size * pSize
943 : ) SAL_THROW_EXTERN_C()
944 : {
945 1698970 : void * addr = 0;
946 :
947 1698970 : if ((arena != 0) && (pSize != 0))
948 : {
949 : sal_Size size;
950 :
951 1693294 : if (alloc_mode == AMode_SYSTEM)
952 2404 : return rtl_allocateMemory(*pSize);
953 :
954 1690890 : size = RTL_MEMORY_ALIGN((*pSize), arena->m_quantum);
955 1690890 : if (size > arena->m_qcache_max)
956 : {
957 : /* allocate from segment list */
958 1690890 : rtl_arena_segment_type *segment = 0;
959 :
960 1690890 : RTL_MEMORY_LOCK_ACQUIRE(&(arena->m_lock));
961 2567770 : if (rtl_arena_segment_alloc (arena, size, &segment) ||
962 876880 : rtl_arena_segment_create(arena, size, &segment) )
963 : {
964 : /* shrink to fit */
965 : sal_Size oversize;
966 :
967 : /* mark segment used */
968 : assert(segment->m_type == RTL_ARENA_SEGMENT_TYPE_FREE);
969 1690890 : segment->m_type = RTL_ARENA_SEGMENT_TYPE_USED;
970 :
971 : /* resize */
972 : assert(segment->m_size >= size);
973 1690890 : oversize = segment->m_size - size;
974 1690890 : if ((oversize >= arena->m_quantum) && (oversize >= arena->m_qcache_max))
975 : {
976 1410373 : rtl_arena_segment_type * remainder = 0;
977 1410373 : rtl_arena_segment_get (arena, &remainder);
978 1410373 : if (remainder != 0)
979 : {
980 1410373 : segment->m_size = size;
981 :
982 1410373 : remainder->m_addr = segment->m_addr + segment->m_size;
983 1410373 : remainder->m_size = oversize;
984 1410373 : remainder->m_type = RTL_ARENA_SEGMENT_TYPE_FREE;
985 1410373 : QUEUE_INSERT_HEAD_NAMED(segment, remainder, s);
986 :
987 1410373 : rtl_arena_freelist_insert (arena, remainder);
988 : }
989 : }
990 :
991 1690890 : rtl_arena_hash_insert (arena, segment);
992 :
993 1690890 : (*pSize) = segment->m_size;
994 1690890 : addr = (void*)(segment->m_addr);
995 : }
996 1690890 : RTL_MEMORY_LOCK_RELEASE(&(arena->m_lock));
997 : }
998 0 : else if (size > 0)
999 : {
1000 : /* allocate from quantum cache(s) */
1001 0 : int index = (size >> arena->m_quantum_shift) - 1;
1002 : assert(arena->m_qcache_ptr[index] != 0);
1003 :
1004 0 : addr = rtl_cache_alloc (arena->m_qcache_ptr[index]);
1005 0 : if (addr != 0)
1006 0 : (*pSize) = size;
1007 : }
1008 : }
1009 1696566 : return (addr);
1010 : }
1011 :
1012 : /** rtl_arena_free()
1013 : */
1014 : void
1015 1595914 : SAL_CALL rtl_arena_free (
1016 : rtl_arena_type * arena,
1017 : void * addr,
1018 : sal_Size size
1019 : ) SAL_THROW_EXTERN_C()
1020 : {
1021 1595914 : if (arena != 0)
1022 : {
1023 1595914 : if (alloc_mode == AMode_SYSTEM)
1024 : {
1025 2400 : rtl_freeMemory(addr);
1026 2400 : return;
1027 : }
1028 :
1029 1593514 : size = RTL_MEMORY_ALIGN(size, arena->m_quantum);
1030 1593514 : if (size > arena->m_qcache_max)
1031 : {
1032 : /* free to segment list */
1033 : rtl_arena_segment_type * segment;
1034 :
1035 1593514 : RTL_MEMORY_LOCK_ACQUIRE(&(arena->m_lock));
1036 :
1037 1593514 : segment = rtl_arena_hash_remove (arena, (sal_uIntPtr)(addr), size);
1038 1593514 : if (segment != 0)
1039 : {
1040 : rtl_arena_segment_type *next, *prev;
1041 :
1042 : /* coalesce w/ adjacent free segment(s) */
1043 1593514 : rtl_arena_segment_coalesce (arena, segment);
1044 :
1045 : /* determine (new) next and prev segment */
1046 1593514 : next = segment->m_snext, prev = segment->m_sprev;
1047 :
1048 : /* entire span free when prev is a span, and next is either a span or a list head */
1049 2795916 : if (((prev->m_type == RTL_ARENA_SEGMENT_TYPE_SPAN)) &&
1050 1901656 : ((next->m_type == RTL_ARENA_SEGMENT_TYPE_SPAN) ||
1051 699254 : (next->m_type == RTL_ARENA_SEGMENT_TYPE_HEAD)) )
1052 : {
1053 : assert(
1054 : prev->m_addr == segment->m_addr
1055 : && prev->m_size == segment->m_size);
1056 :
1057 859697 : if (arena->m_source_free)
1058 : {
1059 859697 : addr = (void*)(prev->m_addr);
1060 859697 : size = prev->m_size;
1061 :
1062 : /* remove from segment list */
1063 859697 : QUEUE_REMOVE_NAMED(segment, s);
1064 :
1065 : /* release segment descriptor */
1066 859697 : rtl_arena_segment_put (arena, &segment);
1067 :
1068 : /* remove from segment list */
1069 859697 : QUEUE_REMOVE_NAMED(prev, s);
1070 :
1071 : /* release (span) segment descriptor */
1072 859697 : rtl_arena_segment_put (arena, &prev);
1073 :
1074 : /* update stats, return span to source arena */
1075 859697 : arena->m_stats.m_mem_total -= size;
1076 859697 : RTL_MEMORY_LOCK_RELEASE(&(arena->m_lock));
1077 :
1078 859697 : (arena->m_source_free)(arena->m_source_arena, addr, size);
1079 859697 : return;
1080 : }
1081 : }
1082 :
1083 : /* insert onto freelist */
1084 733817 : rtl_arena_freelist_insert (arena, segment);
1085 : }
1086 :
1087 733817 : RTL_MEMORY_LOCK_RELEASE(&(arena->m_lock));
1088 : }
1089 0 : else if (size > 0)
1090 : {
1091 : /* free to quantum cache(s) */
1092 0 : int index = (size >> arena->m_quantum_shift) - 1;
1093 : assert(arena->m_qcache_ptr[index] != 0);
1094 :
1095 0 : rtl_cache_free (arena->m_qcache_ptr[index], addr);
1096 : }
1097 : }
1098 : }
1099 :
1100 : /* ================================================================= *
1101 : *
1102 : * machdep internals.
1103 : *
1104 : * ================================================================= */
1105 :
1106 : #if defined(SAL_UNX)
1107 : #include <sys/mman.h>
1108 : #elif defined(SAL_W32)
1109 : #define MAP_FAILED 0
1110 : #endif /* SAL_UNX || SAL_W32 */
1111 :
1112 : namespace
1113 : {
1114 :
1115 : /** rtl_machdep_alloc()
1116 : */
1117 : void *
1118 252479 : SAL_CALL rtl_machdep_alloc (
1119 : rtl_arena_type * pArena,
1120 : sal_Size * pSize
1121 : )
1122 : {
1123 : void * addr;
1124 252479 : sal_Size size = (*pSize);
1125 :
1126 : assert(pArena == gp_machdep_arena);
1127 :
1128 : #if defined(SOLARIS) && defined(SPARC)
1129 : /* see @ mmap(2) man pages */
1130 : size += (pArena->m_quantum + pArena->m_quantum); /* "red-zone" pages */
1131 : if (size > (4 << 20))
1132 : size = RTL_MEMORY_P2ROUNDUP(size, (4 << 20));
1133 : else if (size > (512 << 10))
1134 : size = RTL_MEMORY_P2ROUNDUP(size, (512 << 10));
1135 : else
1136 : size = RTL_MEMORY_P2ROUNDUP(size, (64 << 10));
1137 : size -= (pArena->m_quantum + pArena->m_quantum); /* "red-zone" pages */
1138 : #else
1139 : /* default allocation granularity */
1140 252479 : if(pArena->m_quantum < (64 << 10))
1141 : {
1142 252479 : size = RTL_MEMORY_P2ROUNDUP(size, (64 << 10));
1143 : }
1144 : else
1145 : {
1146 0 : size = RTL_MEMORY_P2ROUNDUP(size, pArena->m_quantum);
1147 : }
1148 : #endif
1149 :
1150 : #if defined(SAL_UNX)
1151 252479 : addr = mmap (NULL, (size_t)(size), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
1152 : #elif defined(SAL_W32)
1153 : addr = VirtualAlloc (NULL, (SIZE_T)(size), MEM_COMMIT, PAGE_READWRITE);
1154 : #endif /* (SAL_UNX || SAL_W32) */
1155 :
1156 252479 : if (addr != MAP_FAILED)
1157 : {
1158 252479 : pArena->m_stats.m_alloc += 1;
1159 252479 : pArena->m_stats.m_mem_total += size;
1160 252479 : pArena->m_stats.m_mem_alloc += size;
1161 :
1162 252479 : (*pSize) = size;
1163 252479 : return (addr);
1164 : }
1165 0 : return (NULL);
1166 : }
1167 :
1168 : /** rtl_machdep_free()
1169 : */
1170 : void
1171 230494 : SAL_CALL rtl_machdep_free (
1172 : rtl_arena_type * pArena,
1173 : void * pAddr,
1174 : sal_Size nSize
1175 : )
1176 : {
1177 : assert(pArena == gp_machdep_arena);
1178 :
1179 230494 : pArena->m_stats.m_free += 1;
1180 230494 : pArena->m_stats.m_mem_total -= nSize;
1181 230494 : pArena->m_stats.m_mem_alloc -= nSize;
1182 :
1183 : #if defined(SAL_UNX)
1184 230494 : (void) munmap(pAddr, nSize);
1185 : #elif defined(SAL_W32)
1186 : (void) VirtualFree ((LPVOID)(pAddr), (SIZE_T)(0), MEM_RELEASE);
1187 : #endif /* (SAL_UNX || SAL_W32) */
1188 230494 : }
1189 :
1190 : sal_Size
1191 14108 : rtl_machdep_pagesize()
1192 : {
1193 : #if defined(SAL_UNX)
1194 : #if defined(FREEBSD) || defined(NETBSD) || defined(DRAGONFLY)
1195 : return ((sal_Size)getpagesize());
1196 : #else /* POSIX */
1197 14108 : return ((sal_Size)sysconf(_SC_PAGESIZE));
1198 : #endif /* xBSD || POSIX */
1199 : #elif defined(SAL_W32)
1200 : SYSTEM_INFO info;
1201 : GetSystemInfo (&info);
1202 : return ((sal_Size)(info.dwPageSize));
1203 : #endif /* (SAL_UNX || SAL_W32) */
1204 : }
1205 :
1206 : } //namespace
1207 :
1208 : /* ================================================================= *
1209 : *
1210 : * arena initialization.
1211 : *
1212 : * ================================================================= */
1213 :
1214 : void
1215 2838 : rtl_arena_init()
1216 : {
1217 : {
1218 : /* list of arenas */
1219 2838 : RTL_MEMORY_LOCK_INIT(&(g_arena_list.m_lock));
1220 2838 : rtl_arena_constructor (&(g_arena_list.m_arena_head));
1221 : }
1222 : {
1223 : /* machdep (pseudo) arena */
1224 : static rtl_arena_type g_machdep_arena;
1225 :
1226 : assert(gp_machdep_arena == 0);
1227 2838 : rtl_arena_constructor (&g_machdep_arena);
1228 :
1229 : gp_machdep_arena = rtl_arena_activate (
1230 : &g_machdep_arena,
1231 : "rtl_machdep_arena",
1232 : rtl_machdep_pagesize(),
1233 : 0, /* no quantum caching */
1234 : 0, 0, 0 /* no source */
1235 2838 : );
1236 : assert(gp_machdep_arena != 0);
1237 : }
1238 : {
1239 : /* default arena */
1240 : static rtl_arena_type g_default_arena;
1241 :
1242 : assert(gp_default_arena == 0);
1243 2838 : rtl_arena_constructor (&g_default_arena);
1244 :
1245 : gp_default_arena = rtl_arena_activate (
1246 : &g_default_arena,
1247 : "rtl_default_arena",
1248 : rtl_machdep_pagesize(),
1249 : 0, /* no quantum caching */
1250 : gp_machdep_arena, /* source */
1251 : rtl_machdep_alloc,
1252 : rtl_machdep_free
1253 2838 : );
1254 : assert(gp_default_arena != 0);
1255 : }
1256 : {
1257 : /* arena internal arena */
1258 : static rtl_arena_type g_arena_arena;
1259 :
1260 : assert(gp_arena_arena == 0);
1261 2838 : rtl_arena_constructor (&g_arena_arena);
1262 :
1263 : gp_arena_arena = rtl_arena_activate (
1264 : &g_arena_arena,
1265 : "rtl_arena_internal_arena",
1266 : 64, /* quantum */
1267 : 0, /* no quantum caching */
1268 : gp_default_arena, /* source */
1269 : rtl_arena_alloc,
1270 : rtl_arena_free
1271 2838 : );
1272 : assert(gp_arena_arena != 0);
1273 : }
1274 : // SAL_INFO("sal.rtl", "rtl_arena_init completed");
1275 2838 : }
1276 :
1277 : /* ================================================================= */
1278 :
1279 : void
1280 2838 : rtl_arena_fini()
1281 : {
1282 2838 : if (gp_arena_arena != 0)
1283 : {
1284 : rtl_arena_type * arena, * head;
1285 :
1286 2838 : RTL_MEMORY_LOCK_ACQUIRE(&(g_arena_list.m_lock));
1287 2838 : head = &(g_arena_list.m_arena_head);
1288 :
1289 2838 : for (arena = head->m_arena_next; arena != head; arena = arena->m_arena_next)
1290 : {
1291 : // SAL_INFO(
1292 : // "sal.rtl",
1293 : // "rtl_arena_fini(" << arena->m_name << "): allocs: "
1294 : // << arena->m_stats.m_alloc << ", frees: "
1295 : // << arena->m_stats.m_free << "; total: "
1296 : // << arena->m_stats.m_mem_total << ", used: "
1297 : // << arena->m_stats.m_mem_alloc);
1298 : }
1299 2838 : RTL_MEMORY_LOCK_RELEASE(&(g_arena_list.m_lock));
1300 : }
1301 : // SAL_INFO("sal.rtl", "rtl_arena_fini completed");
1302 2838 : }
1303 :
1304 : /* ================================================================= */
1305 :
1306 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|