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