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 : /* ================================================================= *
32 : *
33 : * arena internals.
34 : *
35 : * ================================================================= */
36 :
37 : /** g_arena_list
38 : * @internal
39 : */
40 : struct rtl_arena_list_st
41 : {
42 : rtl_memory_lock_type m_lock;
43 : rtl_arena_type m_arena_head;
44 : };
45 :
46 : static rtl_arena_list_st g_arena_list;
47 :
48 : /** gp_arena_arena
49 : * provided for arena_type allocations, and hash_table resizing.
50 : *
51 : * @internal
52 : */
53 : static rtl_arena_type * gp_arena_arena = 0;
54 :
55 : /** gp_machdep_arena
56 : *
57 : * Low level virtual memory (pseudo) arena
58 : * (platform dependent implementation)
59 : *
60 : * @internal
61 : */
62 : static rtl_arena_type * gp_machdep_arena = 0;
63 :
64 : /** gp_default_arena
65 : */
66 : rtl_arena_type * gp_default_arena = 0;
67 :
68 : namespace
69 : {
70 :
71 : void *
72 : SAL_CALL rtl_machdep_alloc (
73 : rtl_arena_type * pArena,
74 : sal_Size * pSize
75 : );
76 :
77 : void
78 : SAL_CALL rtl_machdep_free (
79 : rtl_arena_type * pArena,
80 : void * pAddr,
81 : sal_Size nSize
82 : );
83 :
84 : sal_Size
85 : rtl_machdep_pagesize();
86 :
87 : /* ================================================================= */
88 :
89 : /** rtl_arena_segment_constructor()
90 : */
91 : int
92 784972 : rtl_arena_segment_constructor (void * obj)
93 : {
94 784972 : rtl_arena_segment_type * segment = static_cast<rtl_arena_segment_type*>(obj);
95 :
96 784972 : QUEUE_START_NAMED(segment, s);
97 784972 : QUEUE_START_NAMED(segment, f);
98 :
99 784972 : return 1;
100 : }
101 :
102 : /** rtl_arena_segment_destructor()
103 : */
104 : void
105 272958 : rtl_arena_segment_destructor (void * obj)
106 : {
107 : rtl_arena_segment_type * segment = static_cast< rtl_arena_segment_type * >(
108 272958 : obj);
109 : assert(QUEUE_STARTED_NAMED(segment, s));
110 : assert(QUEUE_STARTED_NAMED(segment, f));
111 : (void) segment; // avoid warnings
112 272958 : }
113 :
114 : /* ================================================================= */
115 :
116 : /** rtl_arena_segment_populate()
117 : *
118 : * @precond arena->m_lock acquired.
119 : */
120 : bool
121 6810 : rtl_arena_segment_populate (
122 : rtl_arena_type * arena
123 : )
124 : {
125 : rtl_arena_segment_type *span;
126 6810 : sal_Size size = rtl_machdep_pagesize();
127 :
128 : span = static_cast< rtl_arena_segment_type * >(
129 6810 : rtl_machdep_alloc(gp_machdep_arena, &size));
130 6810 : if (span != 0)
131 : {
132 : rtl_arena_segment_type *first, *last, *head;
133 6810 : sal_Size count = size / sizeof(rtl_arena_segment_type);
134 :
135 : /* insert onto reserve span list */
136 6810 : QUEUE_INSERT_TAIL_NAMED(&(arena->m_segment_reserve_span_head), span, s);
137 6810 : QUEUE_START_NAMED(span, f);
138 6810 : span->m_addr = reinterpret_cast<sal_uIntPtr>(span);
139 6810 : span->m_size = size;
140 6810 : span->m_type = RTL_ARENA_SEGMENT_TYPE_SPAN;
141 :
142 : /* insert onto reserve list */
143 6810 : head = &(arena->m_segment_reserve_head);
144 7967700 : for (first = span + 1, last = span + count; first < last; ++first)
145 : {
146 7960890 : QUEUE_INSERT_TAIL_NAMED(head, first, s);
147 7960890 : QUEUE_START_NAMED(first, f);
148 7960890 : first->m_addr = 0;
149 7960890 : first->m_size = 0;
150 7960890 : first->m_type = 0;
151 : }
152 : }
153 6810 : return (span != 0);
154 : }
155 :
156 : /** rtl_arena_segment_get()
157 : *
158 : * @precond arena->m_lock acquired.
159 : * @precond (*ppSegment == 0)
160 : */
161 : inline void
162 2529680 : rtl_arena_segment_get (
163 : rtl_arena_type * arena,
164 : rtl_arena_segment_type ** ppSegment
165 : )
166 : {
167 : rtl_arena_segment_type * head;
168 :
169 : assert(*ppSegment == 0);
170 :
171 2529680 : head = &(arena->m_segment_reserve_head);
172 2529680 : if ((head->m_snext != head) || rtl_arena_segment_populate (arena))
173 : {
174 2529681 : (*ppSegment) = head->m_snext;
175 2529681 : QUEUE_REMOVE_NAMED((*ppSegment), s);
176 : }
177 2529680 : }
178 :
179 : /** rtl_arena_segment_put()
180 : *
181 : * @precond arena->m_lock acquired.
182 : * @postcond (*ppSegment == 0)
183 : */
184 : inline void
185 2417697 : rtl_arena_segment_put (
186 : rtl_arena_type * arena,
187 : rtl_arena_segment_type ** ppSegment
188 : )
189 : {
190 : rtl_arena_segment_type * head;
191 :
192 : assert(QUEUE_STARTED_NAMED((*ppSegment), s));
193 : assert(QUEUE_STARTED_NAMED((*ppSegment), f));
194 :
195 2417697 : (*ppSegment)->m_addr = 0;
196 2417697 : (*ppSegment)->m_size = 0;
197 :
198 : assert((*ppSegment)->m_type != RTL_ARENA_SEGMENT_TYPE_HEAD);
199 2417697 : (*ppSegment)->m_type = 0;
200 :
201 : /* keep as reserve */
202 2417697 : head = &(arena->m_segment_reserve_head);
203 2417697 : QUEUE_INSERT_HEAD_NAMED(head, (*ppSegment), s);
204 :
205 : /* clear */
206 2417697 : (*ppSegment) = 0;
207 2417697 : }
208 :
209 : /** rtl_arena_freelist_insert()
210 : *
211 : * @precond arena->m_lock acquired.
212 : */
213 : inline void
214 1646916 : rtl_arena_freelist_insert (
215 : rtl_arena_type * arena,
216 : rtl_arena_segment_type * segment
217 : )
218 : {
219 : rtl_arena_segment_type * head;
220 :
221 1646916 : head = &(arena->m_freelist_head[highbit(segment->m_size) - 1]);
222 1646916 : QUEUE_INSERT_TAIL_NAMED(head, segment, f);
223 :
224 1646916 : arena->m_freelist_bitmap |= head->m_size;
225 1646916 : }
226 :
227 : /** rtl_arena_freelist_remove()
228 : *
229 : * @precond arena->m_lock acquired.
230 : */
231 : inline void
232 1618226 : rtl_arena_freelist_remove (
233 : rtl_arena_type * arena,
234 : rtl_arena_segment_type * segment
235 : )
236 : {
237 2679700 : if ((segment->m_fnext->m_type == RTL_ARENA_SEGMENT_TYPE_HEAD) &&
238 1061474 : (segment->m_fprev->m_type == RTL_ARENA_SEGMENT_TYPE_HEAD) )
239 : {
240 : rtl_arena_segment_type * head;
241 :
242 696628 : head = segment->m_fprev;
243 : assert(arena->m_freelist_bitmap & head->m_size);
244 696628 : arena->m_freelist_bitmap ^= head->m_size;
245 : }
246 1618226 : QUEUE_REMOVE_NAMED(segment, f);
247 1618226 : }
248 :
249 : /* ================================================================= */
250 :
251 : /** RTL_ARENA_HASH_INDEX()
252 : */
253 : #define RTL_ARENA_HASH_INDEX_IMPL(a, s, q, m) \
254 : ((((a) + ((a) >> (s)) + ((a) >> ((s) << 1))) >> (q)) & (m))
255 :
256 : #define RTL_ARENA_HASH_INDEX(arena, addr) \
257 : RTL_ARENA_HASH_INDEX_IMPL((addr), (arena)->m_hash_shift, (arena)->m_quantum_shift, ((arena)->m_hash_size - 1))
258 :
259 : /** rtl_arena_hash_rescale()
260 : *
261 : * @precond arena->m_lock released.
262 : */
263 : void
264 144 : rtl_arena_hash_rescale (
265 : rtl_arena_type * arena,
266 : sal_Size new_size
267 : )
268 : {
269 : assert(new_size != 0);
270 :
271 : rtl_arena_segment_type ** new_table;
272 : sal_Size new_bytes;
273 :
274 144 : new_bytes = new_size * sizeof(rtl_arena_segment_type*);
275 144 : new_table = static_cast<rtl_arena_segment_type **>(rtl_arena_alloc (gp_arena_arena, &new_bytes));
276 :
277 144 : if (new_table != 0)
278 : {
279 : rtl_arena_segment_type ** old_table;
280 : sal_Size old_size, i;
281 :
282 144 : memset (new_table, 0, new_bytes);
283 :
284 144 : RTL_MEMORY_LOCK_ACQUIRE(&(arena->m_lock));
285 :
286 144 : old_table = arena->m_hash_table;
287 144 : old_size = arena->m_hash_size;
288 :
289 : // SAL_INFO(
290 : // "sal.rtl",
291 : // "rtl_arena_hash_rescale(" << arena->m_name << "): nseg: "
292 : // << (arena->m_stats.m_alloc - arena->m_stats.m_free) << " (ave: "
293 : // << ((arena->m_stats.m_alloc - arena->m_stats.m_free)
294 : // >> arena->m_hash_shift)
295 : // << "), frees: " << arena->m_stats.m_free << " [old_size: "
296 : // << old_size << ", new_size: " << new_size << ']');
297 :
298 144 : arena->m_hash_table = new_table;
299 144 : arena->m_hash_size = new_size;
300 144 : arena->m_hash_shift = highbit(arena->m_hash_size) - 1;
301 :
302 9808 : for (i = 0; i < old_size; i++)
303 : {
304 9664 : rtl_arena_segment_type * curr = old_table[i];
305 150816 : while (curr != 0)
306 : {
307 131488 : rtl_arena_segment_type * next = curr->m_fnext;
308 : rtl_arena_segment_type ** head;
309 :
310 : // coverity[negative_shift]
311 131488 : head = &(arena->m_hash_table[RTL_ARENA_HASH_INDEX(arena, curr->m_addr)]);
312 131488 : curr->m_fnext = (*head);
313 131488 : (*head) = curr;
314 :
315 131488 : curr = next;
316 : }
317 9664 : old_table[i] = 0;
318 : }
319 :
320 144 : RTL_MEMORY_LOCK_RELEASE(&(arena->m_lock));
321 :
322 144 : if (old_table != arena->m_hash_table_0)
323 : {
324 1 : sal_Size old_bytes = old_size * sizeof(rtl_arena_segment_type*);
325 1 : rtl_arena_free (gp_arena_arena, old_table, old_bytes);
326 : }
327 : }
328 144 : }
329 :
330 : /** rtl_arena_hash_insert()
331 : * ...and update stats.
332 : */
333 : inline void
334 1332071 : rtl_arena_hash_insert (
335 : rtl_arena_type * arena,
336 : rtl_arena_segment_type * segment
337 : )
338 : {
339 : rtl_arena_segment_type ** ppSegment;
340 :
341 1332071 : ppSegment = &(arena->m_hash_table[RTL_ARENA_HASH_INDEX(arena, segment->m_addr)]);
342 :
343 1332071 : segment->m_fnext = (*ppSegment);
344 1332071 : (*ppSegment) = segment;
345 :
346 1332071 : arena->m_stats.m_alloc += 1;
347 1332071 : arena->m_stats.m_mem_alloc += segment->m_size;
348 1332071 : }
349 :
350 : /** rtl_arena_hash_remove()
351 : * ...and update stats.
352 : */
353 : rtl_arena_segment_type *
354 1260472 : rtl_arena_hash_remove (
355 : rtl_arena_type * arena,
356 : sal_uIntPtr addr,
357 : sal_Size size
358 : )
359 : {
360 : rtl_arena_segment_type *segment, **segpp;
361 1260472 : sal_Size lookups = 0;
362 :
363 1260472 : segpp = &(arena->m_hash_table[RTL_ARENA_HASH_INDEX(arena, addr)]);
364 2596388 : while ((segment = *segpp) != 0)
365 : {
366 1335916 : if (segment->m_addr == addr)
367 : {
368 1260472 : *segpp = segment->m_fnext, segment->m_fnext = segment->m_fprev = segment;
369 1260472 : break;
370 : }
371 :
372 : /* update lookup miss stats */
373 75444 : lookups += 1;
374 75444 : segpp = &(segment->m_fnext);
375 : }
376 :
377 : assert(segment != 0); // bad free
378 1260472 : if (segment != 0)
379 : {
380 : assert(segment->m_size == size);
381 : (void) size; // avoid warnings
382 :
383 1260472 : arena->m_stats.m_free += 1;
384 1260472 : arena->m_stats.m_mem_alloc -= segment->m_size;
385 :
386 1260472 : if (lookups > 1)
387 : {
388 16329 : sal_Size nseg = (sal_Size)(arena->m_stats.m_alloc - arena->m_stats.m_free);
389 16329 : if (nseg > 4 * arena->m_hash_size)
390 : {
391 144 : if (!(arena->m_flags & RTL_ARENA_FLAG_RESCALE))
392 : {
393 144 : sal_Size ave = nseg >> arena->m_hash_shift;
394 : assert(ave != 0);
395 144 : sal_Size new_size = arena->m_hash_size << (highbit(ave) - 1);
396 :
397 144 : arena->m_flags |= RTL_ARENA_FLAG_RESCALE;
398 144 : RTL_MEMORY_LOCK_RELEASE(&(arena->m_lock));
399 144 : rtl_arena_hash_rescale (arena, new_size);
400 144 : RTL_MEMORY_LOCK_ACQUIRE(&(arena->m_lock));
401 144 : arena->m_flags &= ~RTL_ARENA_FLAG_RESCALE;
402 : }
403 : }
404 : }
405 : }
406 :
407 1260472 : return segment;
408 : }
409 :
410 : /* ================================================================= */
411 :
412 : /** rtl_arena_segment_alloc()
413 : * allocate (and remove) segment from freelist
414 : *
415 : * @precond arena->m_lock acquired
416 : * @precond (*ppSegment == 0)
417 : */
418 : bool
419 1332071 : rtl_arena_segment_alloc (
420 : rtl_arena_type * arena,
421 : sal_Size size,
422 : rtl_arena_segment_type ** ppSegment
423 : )
424 : {
425 1332071 : int index = 0;
426 :
427 : assert(*ppSegment == 0);
428 1332071 : if (!RTL_MEMORY_ISP2(size))
429 : {
430 1043546 : int msb = highbit(size);
431 1043546 : if (RTL_ARENA_FREELIST_SIZE == sal::static_int_cast< size_t >(msb))
432 : {
433 : /* highest possible freelist: fall back to first fit */
434 : rtl_arena_segment_type *head, *segment;
435 :
436 0 : head = &(arena->m_freelist_head[msb - 1]);
437 0 : for (segment = head->m_fnext; segment != head; segment = segment->m_fnext)
438 : {
439 0 : if (segment->m_size >= size)
440 : {
441 : /* allocate first fit segment */
442 0 : (*ppSegment) = segment;
443 0 : break;
444 : }
445 : }
446 0 : goto dequeue_and_leave;
447 : }
448 :
449 : /* roundup to next power of 2 */
450 1043546 : size = (((sal_Size)1) << msb);
451 : }
452 :
453 1332071 : index = lowbit(RTL_MEMORY_P2ALIGN(arena->m_freelist_bitmap, size));
454 1332072 : if (index > 0)
455 : {
456 : /* instant fit: allocate first free segment */
457 : rtl_arena_segment_type *head;
458 :
459 613704 : head = &(arena->m_freelist_head[index - 1]);
460 613704 : (*ppSegment) = head->m_fnext;
461 : assert((*ppSegment) != head);
462 : }
463 :
464 : dequeue_and_leave:
465 1332072 : if (*ppSegment != 0)
466 : {
467 : /* remove from freelist */
468 613704 : rtl_arena_freelist_remove (arena, (*ppSegment));
469 : }
470 1332071 : return (*ppSegment != 0);
471 : }
472 :
473 : /** rtl_arena_segment_create()
474 : * import new (span) segment from source arena
475 : *
476 : * @precond arena->m_lock acquired
477 : * @precond (*ppSegment == 0)
478 : */
479 : int
480 718368 : rtl_arena_segment_create (
481 : rtl_arena_type * arena,
482 : sal_Size size,
483 : rtl_arena_segment_type ** ppSegment
484 : )
485 : {
486 : assert((*ppSegment) == 0);
487 718368 : if (arena->m_source_alloc != 0)
488 : {
489 718368 : rtl_arena_segment_get (arena, ppSegment);
490 718368 : if (*ppSegment != 0)
491 : {
492 718368 : rtl_arena_segment_type * span = 0;
493 718368 : rtl_arena_segment_get (arena, &span);
494 718368 : if (span != 0)
495 : {
496 : /* import new span from source arena */
497 718368 : RTL_MEMORY_LOCK_RELEASE(&(arena->m_lock));
498 :
499 718368 : span->m_size = size;
500 : span->m_addr = reinterpret_cast<sal_uIntPtr>(
501 : (arena->m_source_alloc)(
502 718368 : arena->m_source_arena, &(span->m_size)));
503 :
504 718368 : RTL_MEMORY_LOCK_ACQUIRE(&(arena->m_lock));
505 718368 : if (span->m_addr != 0)
506 : {
507 : /* insert onto segment list, update stats */
508 718368 : span->m_type = RTL_ARENA_SEGMENT_TYPE_SPAN;
509 718368 : QUEUE_INSERT_HEAD_NAMED(&(arena->m_segment_head), span, s);
510 718368 : arena->m_stats.m_mem_total += span->m_size;
511 :
512 718368 : (*ppSegment)->m_addr = span->m_addr;
513 718368 : (*ppSegment)->m_size = span->m_size;
514 718368 : (*ppSegment)->m_type = RTL_ARENA_SEGMENT_TYPE_FREE;
515 718368 : QUEUE_INSERT_HEAD_NAMED(span, (*ppSegment), s);
516 :
517 : /* report success */
518 718368 : 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 1260530 : 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 1260530 : segment->m_type = RTL_ARENA_SEGMENT_TYPE_FREE;
545 :
546 : /* try to merge w/ next segment */
547 1260530 : next = segment->m_snext;
548 1260530 : if (next->m_type == RTL_ARENA_SEGMENT_TYPE_FREE)
549 : {
550 : assert(segment->m_addr + segment->m_size == next->m_addr);
551 716039 : segment->m_size += next->m_size;
552 :
553 : /* remove from freelist */
554 716039 : rtl_arena_freelist_remove (arena, next);
555 :
556 : /* remove from segment list */
557 716039 : QUEUE_REMOVE_NAMED(next, s);
558 :
559 : /* release segment descriptor */
560 716039 : rtl_arena_segment_put (arena, &next);
561 : }
562 :
563 : /* try to merge w/ prev segment */
564 1260529 : prev = segment->m_sprev;
565 1260529 : if (prev->m_type == RTL_ARENA_SEGMENT_TYPE_FREE)
566 : {
567 : assert(prev->m_addr + prev->m_size == segment->m_addr);
568 288426 : segment->m_addr = prev->m_addr;
569 288426 : segment->m_size += prev->m_size;
570 :
571 : /* remove from freelist */
572 288426 : rtl_arena_freelist_remove (arena, prev);
573 :
574 : /* remove from segment list */
575 288426 : QUEUE_REMOVE_NAMED(prev, s);
576 :
577 : /* release segment descriptor */
578 288426 : rtl_arena_segment_put (arena, &prev);
579 : }
580 1260529 : }
581 :
582 : /* ================================================================= */
583 :
584 : /** rtl_arena_constructor()
585 : */
586 : void
587 11716 : rtl_arena_constructor (void * obj)
588 : {
589 11716 : rtl_arena_type * arena = static_cast<rtl_arena_type*>(obj);
590 : rtl_arena_segment_type * head;
591 : size_t i;
592 :
593 11716 : memset (arena, 0, sizeof(rtl_arena_type));
594 :
595 11716 : QUEUE_START_NAMED(arena, arena_);
596 :
597 11716 : (void) RTL_MEMORY_LOCK_INIT(&(arena->m_lock));
598 :
599 11716 : head = &(arena->m_segment_reserve_span_head);
600 11716 : rtl_arena_segment_constructor (head);
601 11716 : head->m_type = RTL_ARENA_SEGMENT_TYPE_HEAD;
602 :
603 11716 : head = &(arena->m_segment_reserve_head);
604 11716 : rtl_arena_segment_constructor (head);
605 11716 : head->m_type = RTL_ARENA_SEGMENT_TYPE_HEAD;
606 :
607 11716 : head = &(arena->m_segment_head);
608 11716 : rtl_arena_segment_constructor (head);
609 11716 : head->m_type = RTL_ARENA_SEGMENT_TYPE_HEAD;
610 :
611 761540 : for (i = 0; i < RTL_ARENA_FREELIST_SIZE; i++)
612 : {
613 749824 : head = &(arena->m_freelist_head[i]);
614 749824 : rtl_arena_segment_constructor (head);
615 :
616 749824 : head->m_size = (((sal_Size)1) << i);
617 749824 : head->m_type = RTL_ARENA_SEGMENT_TYPE_HEAD;
618 : }
619 :
620 11716 : arena->m_hash_table = arena->m_hash_table_0;
621 11716 : arena->m_hash_size = RTL_ARENA_HASH_SIZE;
622 11716 : arena->m_hash_shift = highbit(arena->m_hash_size) - 1;
623 11716 : }
624 :
625 : /** rtl_arena_destructor()
626 : */
627 : void
628 4074 : rtl_arena_destructor (void * obj)
629 : {
630 4074 : rtl_arena_type * arena = static_cast<rtl_arena_type*>(obj);
631 : rtl_arena_segment_type * head;
632 : size_t i;
633 :
634 : assert(QUEUE_STARTED_NAMED(arena, arena_));
635 :
636 4074 : RTL_MEMORY_LOCK_DESTROY(&(arena->m_lock));
637 :
638 4074 : head = &(arena->m_segment_reserve_span_head);
639 : assert(head->m_type == RTL_ARENA_SEGMENT_TYPE_HEAD);
640 4074 : rtl_arena_segment_destructor (head);
641 :
642 4074 : head = &(arena->m_segment_reserve_head);
643 : assert(head->m_type == RTL_ARENA_SEGMENT_TYPE_HEAD);
644 4074 : rtl_arena_segment_destructor (head);
645 :
646 4074 : head = &(arena->m_segment_head);
647 : assert(head->m_type == RTL_ARENA_SEGMENT_TYPE_HEAD);
648 4074 : rtl_arena_segment_destructor (head);
649 :
650 264810 : for (i = 0; i < RTL_ARENA_FREELIST_SIZE; i++)
651 : {
652 260736 : 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 260736 : 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 4074 : }
666 :
667 : /* ================================================================= */
668 :
669 : /** rtl_arena_activate()
670 : */
671 : rtl_arena_type *
672 9806 : 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 9806 : if (arena != 0)
684 : {
685 9806 : (void) snprintf (arena->m_name, sizeof(arena->m_name), "%s", name);
686 :
687 9806 : if (!RTL_MEMORY_ISP2(quantum))
688 : {
689 : /* roundup to next power of 2 */
690 0 : quantum = (((sal_Size)1) << highbit(quantum));
691 : }
692 9806 : quantum_cache_max = RTL_MEMORY_P2ROUNDUP(quantum_cache_max, quantum);
693 :
694 9806 : arena->m_quantum = quantum;
695 9806 : arena->m_quantum_shift = highbit(arena->m_quantum) - 1;
696 9806 : arena->m_qcache_max = quantum_cache_max;
697 :
698 9806 : arena->m_source_arena = source_arena;
699 9806 : arena->m_source_alloc = source_alloc;
700 9806 : arena->m_source_free = source_free;
701 :
702 9806 : 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 = static_cast<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 9806 : RTL_MEMORY_LOCK_ACQUIRE(&(g_arena_list.m_lock));
724 9806 : QUEUE_INSERT_TAIL_NAMED(&(g_arena_list.m_arena_head), arena, arena_);
725 9806 : RTL_MEMORY_LOCK_RELEASE(&(g_arena_list.m_lock));
726 : }
727 9806 : return arena;
728 : }
729 :
730 : /** rtl_arena_deactivate()
731 : */
732 : void
733 4074 : rtl_arena_deactivate (
734 : rtl_arena_type * arena
735 : )
736 : {
737 : rtl_arena_segment_type * head, * segment;
738 :
739 : /* remove from arena list */
740 4074 : RTL_MEMORY_LOCK_ACQUIRE(&(g_arena_list.m_lock));
741 4074 : QUEUE_REMOVE_NAMED(arena, arena_);
742 4074 : RTL_MEMORY_LOCK_RELEASE(&(g_arena_list.m_lock));
743 :
744 : /* cleanup quantum cache(s) */
745 4074 : 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 4074 : 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 1040 : for (i = 0, n = arena->m_hash_size; i < n; i++)
784 : {
785 2106 : while ((segment = arena->m_hash_table[i]) != 0)
786 : {
787 : /* pop from hash table */
788 58 : arena->m_hash_table[i] = segment->m_fnext, segment->m_fnext = segment->m_fprev = segment;
789 :
790 : /* coalesce w/ adjacent free segment(s) */
791 58 : rtl_arena_segment_coalesce (arena, segment);
792 :
793 : /* insert onto freelist */
794 58 : rtl_arena_freelist_insert (arena, segment);
795 : }
796 : }
797 : }
798 :
799 : /* cleanup hash table */
800 4074 : 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 4074 : head = &(arena->m_segment_head);
814 4188 : for (segment = head->m_snext; segment != head; segment = head->m_snext)
815 : {
816 114 : if (segment->m_type == RTL_ARENA_SEGMENT_TYPE_FREE)
817 : {
818 : /* remove from freelist */
819 57 : 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 114 : QUEUE_REMOVE_NAMED(segment, s);
829 :
830 : /* release segment descriptor */
831 114 : rtl_arena_segment_put (arena, &segment);
832 : }
833 :
834 : /* cleanup segment reserve list */
835 4074 : head = &(arena->m_segment_reserve_head);
836 3404695 : for (segment = head->m_snext; segment != head; segment = head->m_snext)
837 : {
838 : /* remove from segment list */
839 3400621 : QUEUE_REMOVE_NAMED(segment, s);
840 : }
841 :
842 : /* cleanup segment reserve span(s) */
843 4074 : head = &(arena->m_segment_reserve_span_head);
844 6983 : 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 2909 : QUEUE_REMOVE_NAMED(segment, s);
851 :
852 : /* return span to g_machdep_arena */
853 2909 : rtl_machdep_free (gp_machdep_arena, reinterpret_cast<void*>(segment->m_addr), segment->m_size);
854 : }
855 4074 : }
856 :
857 : } //namespace
858 : /* ================================================================= *
859 : *
860 : * arena implementation.
861 : *
862 : * ================================================================= */
863 :
864 : /** rtl_arena_create()
865 : */
866 : rtl_arena_type *
867 4076 : 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 4076 : rtl_arena_type * result = 0;
878 4076 : sal_Size size = sizeof(rtl_arena_type);
879 :
880 : try_alloc:
881 5986 : result = static_cast<rtl_arena_type*>(rtl_arena_alloc (gp_arena_arena, &size));
882 5986 : if (result != 0)
883 : {
884 4076 : rtl_arena_type * arena = result;
885 4076 : rtl_arena_constructor (arena);
886 :
887 4076 : if (!source_arena)
888 : {
889 : assert(gp_default_arena != 0);
890 4076 : 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 4076 : );
902 :
903 4076 : 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 1910 : else if (gp_arena_arena == 0)
911 : {
912 1910 : ensureArenaSingleton();
913 1910 : if (gp_arena_arena)
914 : {
915 : /* try again */
916 1910 : goto try_alloc;
917 : }
918 : }
919 4076 : return result;
920 : }
921 :
922 : /** rtl_arena_destroy()
923 : */
924 : void
925 4074 : SAL_CALL rtl_arena_destroy (
926 : rtl_arena_type * arena
927 : ) SAL_THROW_EXTERN_C()
928 : {
929 4074 : if (arena != 0)
930 : {
931 4074 : rtl_arena_deactivate (arena);
932 4074 : rtl_arena_destructor (arena);
933 4074 : rtl_arena_free (gp_arena_arena, arena, sizeof(rtl_arena_type));
934 : }
935 4074 : }
936 :
937 : /** rtl_arena_alloc()
938 : */
939 : void *
940 1335892 : SAL_CALL rtl_arena_alloc (
941 : rtl_arena_type * arena,
942 : sal_Size * pSize
943 : ) SAL_THROW_EXTERN_C()
944 : {
945 1335892 : void * addr = 0;
946 :
947 1335892 : if ((arena != 0) && (pSize != 0))
948 : {
949 : sal_Size size;
950 :
951 1332072 : size = RTL_MEMORY_ALIGN((*pSize), arena->m_quantum);
952 1332072 : if (size > arena->m_qcache_max)
953 : {
954 : /* allocate from segment list */
955 1332072 : rtl_arena_segment_type *segment = 0;
956 :
957 1332072 : RTL_MEMORY_LOCK_ACQUIRE(&(arena->m_lock));
958 2050439 : if (rtl_arena_segment_alloc (arena, size, &segment) ||
959 718368 : rtl_arena_segment_create(arena, size, &segment) )
960 : {
961 : /* shrink to fit */
962 : sal_Size oversize;
963 :
964 : /* mark segment used */
965 : assert(segment->m_type == RTL_ARENA_SEGMENT_TYPE_FREE);
966 1332072 : segment->m_type = RTL_ARENA_SEGMENT_TYPE_USED;
967 :
968 : /* resize */
969 : assert(segment->m_size >= size);
970 1332072 : oversize = segment->m_size - size;
971 1332072 : if ((oversize >= arena->m_quantum) && (oversize >= arena->m_qcache_max))
972 : {
973 1092946 : rtl_arena_segment_type * remainder = 0;
974 1092946 : rtl_arena_segment_get (arena, &remainder);
975 1092946 : if (remainder != 0)
976 : {
977 1092946 : segment->m_size = size;
978 :
979 1092946 : remainder->m_addr = segment->m_addr + segment->m_size;
980 1092946 : remainder->m_size = oversize;
981 1092946 : remainder->m_type = RTL_ARENA_SEGMENT_TYPE_FREE;
982 1092946 : QUEUE_INSERT_HEAD_NAMED(segment, remainder, s);
983 :
984 1092946 : rtl_arena_freelist_insert (arena, remainder);
985 : }
986 : }
987 :
988 1332071 : rtl_arena_hash_insert (arena, segment);
989 :
990 1332071 : (*pSize) = segment->m_size;
991 1332071 : addr = reinterpret_cast<void*>(segment->m_addr);
992 : }
993 1332071 : RTL_MEMORY_LOCK_RELEASE(&(arena->m_lock));
994 : }
995 0 : else if (size > 0)
996 : {
997 : /* allocate from quantum cache(s) */
998 0 : int index = (size >> arena->m_quantum_shift) - 1;
999 : assert(arena->m_qcache_ptr[index] != 0);
1000 :
1001 0 : addr = rtl_cache_alloc (arena->m_qcache_ptr[index]);
1002 0 : if (addr != 0)
1003 0 : (*pSize) = size;
1004 : }
1005 : }
1006 1335892 : return addr;
1007 : }
1008 :
1009 : /** rtl_arena_free()
1010 : */
1011 : void
1012 1260472 : SAL_CALL rtl_arena_free (
1013 : rtl_arena_type * arena,
1014 : void * addr,
1015 : sal_Size size
1016 : ) SAL_THROW_EXTERN_C()
1017 : {
1018 1260472 : if (arena != 0)
1019 : {
1020 1260472 : size = RTL_MEMORY_ALIGN(size, arena->m_quantum);
1021 1260472 : if (size > arena->m_qcache_max)
1022 : {
1023 : /* free to segment list */
1024 : rtl_arena_segment_type * segment;
1025 :
1026 1260472 : RTL_MEMORY_LOCK_ACQUIRE(&(arena->m_lock));
1027 :
1028 1260472 : segment = rtl_arena_hash_remove (arena, reinterpret_cast<sal_uIntPtr>(addr), size);
1029 1260472 : if (segment != 0)
1030 : {
1031 : rtl_arena_segment_type *next, *prev;
1032 :
1033 : /* coalesce w/ adjacent free segment(s) */
1034 1260472 : rtl_arena_segment_coalesce (arena, segment);
1035 :
1036 : /* determine (new) next and prev segment */
1037 1260471 : next = segment->m_snext, prev = segment->m_sprev;
1038 :
1039 : /* entire span free when prev is a span, and next is either a span or a list head */
1040 2226597 : if (((prev->m_type == RTL_ARENA_SEGMENT_TYPE_SPAN)) &&
1041 1562037 : ((next->m_type == RTL_ARENA_SEGMENT_TYPE_SPAN) ||
1042 595911 : (next->m_type == RTL_ARENA_SEGMENT_TYPE_HEAD)) )
1043 : {
1044 : assert(
1045 : prev->m_addr == segment->m_addr
1046 : && prev->m_size == segment->m_size);
1047 :
1048 706559 : if (arena->m_source_free)
1049 : {
1050 706559 : addr = reinterpret_cast<void*>(prev->m_addr);
1051 706559 : size = prev->m_size;
1052 :
1053 : /* remove from segment list */
1054 706559 : QUEUE_REMOVE_NAMED(segment, s);
1055 :
1056 : /* release segment descriptor */
1057 706559 : rtl_arena_segment_put (arena, &segment);
1058 :
1059 : /* remove from segment list */
1060 706559 : QUEUE_REMOVE_NAMED(prev, s);
1061 :
1062 : /* release (span) segment descriptor */
1063 706559 : rtl_arena_segment_put (arena, &prev);
1064 :
1065 : /* update stats, return span to source arena */
1066 706559 : arena->m_stats.m_mem_total -= size;
1067 706559 : RTL_MEMORY_LOCK_RELEASE(&(arena->m_lock));
1068 :
1069 706559 : (arena->m_source_free)(arena->m_source_arena, addr, size);
1070 1967031 : return;
1071 : }
1072 : }
1073 :
1074 : /* insert onto freelist */
1075 553912 : rtl_arena_freelist_insert (arena, segment);
1076 : }
1077 :
1078 553913 : RTL_MEMORY_LOCK_RELEASE(&(arena->m_lock));
1079 : }
1080 0 : else if (size > 0)
1081 : {
1082 : /* free to quantum cache(s) */
1083 0 : int index = (size >> arena->m_quantum_shift) - 1;
1084 : assert(arena->m_qcache_ptr[index] != 0);
1085 :
1086 0 : rtl_cache_free (arena->m_qcache_ptr[index], addr);
1087 : }
1088 : }
1089 : }
1090 :
1091 : /* ================================================================= *
1092 : *
1093 : * machdep internals.
1094 : *
1095 : * ================================================================= */
1096 :
1097 : #if defined(SAL_UNX)
1098 : #include <sys/mman.h>
1099 : #elif defined(SAL_W32)
1100 : #define MAP_FAILED 0
1101 : #endif /* SAL_UNX || SAL_W32 */
1102 :
1103 : namespace
1104 : {
1105 :
1106 : /** rtl_machdep_alloc()
1107 : */
1108 : void *
1109 204678 : SAL_CALL rtl_machdep_alloc (
1110 : rtl_arena_type * pArena,
1111 : sal_Size * pSize
1112 : )
1113 : {
1114 : void * addr;
1115 204678 : sal_Size size = (*pSize);
1116 :
1117 : assert(pArena == gp_machdep_arena);
1118 :
1119 : #if defined(SOLARIS) && defined(SPARC)
1120 : /* see @ mmap(2) man pages */
1121 : size += (pArena->m_quantum + pArena->m_quantum); /* "red-zone" pages */
1122 : if (size > (4 << 20))
1123 : size = RTL_MEMORY_P2ROUNDUP(size, (4 << 20));
1124 : else if (size > (512 << 10))
1125 : size = RTL_MEMORY_P2ROUNDUP(size, (512 << 10));
1126 : else
1127 : size = RTL_MEMORY_P2ROUNDUP(size, (64 << 10));
1128 : size -= (pArena->m_quantum + pArena->m_quantum); /* "red-zone" pages */
1129 : #else
1130 : /* default allocation granularity */
1131 204678 : if(pArena->m_quantum < (64 << 10))
1132 : {
1133 204678 : size = RTL_MEMORY_P2ROUNDUP(size, (64 << 10));
1134 : }
1135 : else
1136 : {
1137 0 : size = RTL_MEMORY_P2ROUNDUP(size, pArena->m_quantum);
1138 : }
1139 : #endif
1140 :
1141 : #if defined(SAL_UNX)
1142 204678 : addr = mmap (NULL, (size_t)(size), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
1143 : #elif defined(SAL_W32)
1144 : addr = VirtualAlloc (NULL, (SIZE_T)(size), MEM_COMMIT, PAGE_READWRITE);
1145 : #endif /* (SAL_UNX || SAL_W32) */
1146 :
1147 204678 : if (addr != MAP_FAILED)
1148 : {
1149 204678 : pArena->m_stats.m_alloc += 1;
1150 204678 : pArena->m_stats.m_mem_total += size;
1151 204678 : pArena->m_stats.m_mem_alloc += size;
1152 :
1153 204678 : (*pSize) = size;
1154 204678 : return addr;
1155 : }
1156 0 : return NULL;
1157 : }
1158 :
1159 : /** rtl_machdep_free()
1160 : */
1161 : void
1162 189211 : SAL_CALL rtl_machdep_free (
1163 : rtl_arena_type * pArena,
1164 : void * pAddr,
1165 : sal_Size nSize
1166 : )
1167 : {
1168 : assert(pArena == gp_machdep_arena);
1169 :
1170 189211 : pArena->m_stats.m_free += 1;
1171 189211 : pArena->m_stats.m_mem_total -= nSize;
1172 189211 : pArena->m_stats.m_mem_alloc -= nSize;
1173 :
1174 : #if defined(SAL_UNX)
1175 189211 : (void) munmap(pAddr, nSize);
1176 : #elif defined(SAL_W32)
1177 : (void) VirtualFree ((LPVOID)(pAddr), (SIZE_T)(0), MEM_RELEASE);
1178 : #endif /* (SAL_UNX || SAL_W32) */
1179 189211 : }
1180 :
1181 : sal_Size
1182 10630 : rtl_machdep_pagesize()
1183 : {
1184 : #if defined(SAL_UNX)
1185 : #if defined(FREEBSD) || defined(NETBSD) || defined(DRAGONFLY)
1186 : return (sal_Size)getpagesize();
1187 : #else /* POSIX */
1188 10630 : return (sal_Size)sysconf(_SC_PAGESIZE);
1189 : #endif /* xBSD || POSIX */
1190 : #elif defined(SAL_W32)
1191 : SYSTEM_INFO info;
1192 : GetSystemInfo (&info);
1193 : return (sal_Size)info.dwPageSize;
1194 : #endif /* (SAL_UNX || SAL_W32) */
1195 : }
1196 :
1197 : } //namespace
1198 :
1199 : /* ================================================================= *
1200 : *
1201 : * arena initialization.
1202 : *
1203 : * ================================================================= */
1204 :
1205 : void
1206 1910 : rtl_arena_init()
1207 : {
1208 : {
1209 : /* list of arenas */
1210 1910 : RTL_MEMORY_LOCK_INIT(&(g_arena_list.m_lock));
1211 1910 : rtl_arena_constructor (&(g_arena_list.m_arena_head));
1212 : }
1213 : {
1214 : /* machdep (pseudo) arena */
1215 : static rtl_arena_type g_machdep_arena;
1216 :
1217 : assert(gp_machdep_arena == 0);
1218 1910 : rtl_arena_constructor (&g_machdep_arena);
1219 :
1220 : gp_machdep_arena = rtl_arena_activate (
1221 : &g_machdep_arena,
1222 : "rtl_machdep_arena",
1223 : rtl_machdep_pagesize(),
1224 : 0, /* no quantum caching */
1225 : 0, 0, 0 /* no source */
1226 1910 : );
1227 : assert(gp_machdep_arena != 0);
1228 : }
1229 : {
1230 : /* default arena */
1231 : static rtl_arena_type g_default_arena;
1232 :
1233 : assert(gp_default_arena == 0);
1234 1910 : rtl_arena_constructor (&g_default_arena);
1235 :
1236 : gp_default_arena = rtl_arena_activate (
1237 : &g_default_arena,
1238 : "rtl_default_arena",
1239 : rtl_machdep_pagesize(),
1240 : 0, /* no quantum caching */
1241 : gp_machdep_arena, /* source */
1242 : rtl_machdep_alloc,
1243 : rtl_machdep_free
1244 1910 : );
1245 : assert(gp_default_arena != 0);
1246 : }
1247 : {
1248 : /* arena internal arena */
1249 : static rtl_arena_type g_arena_arena;
1250 :
1251 : assert(gp_arena_arena == 0);
1252 1910 : rtl_arena_constructor (&g_arena_arena);
1253 :
1254 : gp_arena_arena = rtl_arena_activate (
1255 : &g_arena_arena,
1256 : "rtl_arena_internal_arena",
1257 : 64, /* quantum */
1258 : 0, /* no quantum caching */
1259 : gp_default_arena, /* source */
1260 : rtl_arena_alloc,
1261 : rtl_arena_free
1262 1910 : );
1263 : assert(gp_arena_arena != 0);
1264 : }
1265 : // SAL_INFO("sal.rtl", "rtl_arena_init completed");
1266 1910 : }
1267 :
1268 : /* ================================================================= */
1269 :
1270 : void
1271 1910 : rtl_arena_fini()
1272 : {
1273 1910 : if (gp_arena_arena != 0)
1274 : {
1275 : rtl_arena_type * arena, * head;
1276 :
1277 1910 : RTL_MEMORY_LOCK_ACQUIRE(&(g_arena_list.m_lock));
1278 1910 : head = &(g_arena_list.m_arena_head);
1279 :
1280 1910 : for (arena = head->m_arena_next; arena != head; arena = arena->m_arena_next)
1281 : {
1282 : // SAL_INFO(
1283 : // "sal.rtl",
1284 : // "rtl_arena_fini(" << arena->m_name << "): allocs: "
1285 : // << arena->m_stats.m_alloc << ", frees: "
1286 : // << arena->m_stats.m_free << "; total: "
1287 : // << arena->m_stats.m_mem_total << ", used: "
1288 : // << arena->m_stats.m_mem_alloc);
1289 : }
1290 1910 : RTL_MEMORY_LOCK_RELEASE(&(g_arena_list.m_lock));
1291 : }
1292 : // SAL_INFO("sal.rtl", "rtl_arena_fini completed");
1293 1910 : }
1294 :
1295 : /* ================================================================= */
1296 :
1297 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|