1*e7dd2c75Slukem /* $NetBSD: aml_memman.c,v 1.3 2009/01/18 09:46:59 lukem Exp $ */
253e202c1Schristos
353e202c1Schristos /*-
453e202c1Schristos * Copyright (c) 1999, 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
553e202c1Schristos * All rights reserved.
653e202c1Schristos *
753e202c1Schristos * Redistribution and use in source and binary forms, with or without
853e202c1Schristos * modification, are permitted provided that the following conditions
953e202c1Schristos * are met:
1053e202c1Schristos * 1. Redistributions of source code must retain the above copyright
1153e202c1Schristos * notice, this list of conditions and the following disclaimer.
1253e202c1Schristos * 2. Redistributions in binary form must reproduce the above copyright
1353e202c1Schristos * notice, this list of conditions and the following disclaimer in the
1453e202c1Schristos * documentation and/or other materials provided with the distribution.
1553e202c1Schristos *
1653e202c1Schristos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1753e202c1Schristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1853e202c1Schristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1953e202c1Schristos * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2053e202c1Schristos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2153e202c1Schristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2253e202c1Schristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2353e202c1Schristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2453e202c1Schristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2553e202c1Schristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2653e202c1Schristos * SUCH DAMAGE.
2753e202c1Schristos *
2853e202c1Schristos * Id: aml_memman.c,v 1.10 2000/08/09 14:47:43 iwasaki Exp
2953e202c1Schristos * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_memman.c,v 1.2 2000/11/09 06:24:45 iwasaki Exp $
3053e202c1Schristos */
3153e202c1Schristos #include <sys/cdefs.h>
32*e7dd2c75Slukem __RCSID("$NetBSD: aml_memman.c,v 1.3 2009/01/18 09:46:59 lukem Exp $");
3353e202c1Schristos
3453e202c1Schristos /*
3553e202c1Schristos * Generic Memory Management
3653e202c1Schristos */
3753e202c1Schristos
3853e202c1Schristos #include <sys/param.h>
3953e202c1Schristos
4053e202c1Schristos #include <aml/aml_memman.h>
4153e202c1Schristos
4253e202c1Schristos #ifndef _KERNEL
4353e202c1Schristos #include <stdlib.h>
4453e202c1Schristos #include <stdio.h>
4553e202c1Schristos #include <string.h>
4653e202c1Schristos #else /* _KERNEL */
4753e202c1Schristos #include <sys/kernel.h>
4853e202c1Schristos #include <sys/systm.h>
4953e202c1Schristos #include <sys/malloc.h>
5053e202c1Schristos MALLOC_DEFINE(M_MEMMAN, "memman", "Generic and Simple Memory Management");
5153e202c1Schristos #endif /* !_KERNEL */
5253e202c1Schristos
5353e202c1Schristos unsigned int memid_unkown = 255;
5453e202c1Schristos
5553e202c1Schristos static int manage_block(struct memman *memman, unsigned int id,
5653e202c1Schristos void *block, unsigned static_mem,
5753e202c1Schristos unsigned entries);
5853e202c1Schristos static int blockman_init(struct memman *memman, unsigned int id);
5953e202c1Schristos static void memman_flexsize_add_histogram(struct memman *memman,
6053e202c1Schristos size_t size,
6153e202c1Schristos int tolerance);
6253e202c1Schristos static int memman_comp_histogram_size(const void *a,
6353e202c1Schristos const void *b);
6453e202c1Schristos static void memman_sort_histogram_by_size(struct memman *memman);
6553e202c1Schristos static unsigned int memman_guess_memid(struct memman *memman, void *chunk);
6653e202c1Schristos static void memman_statistics_fixedsize(struct memman *memman);
6753e202c1Schristos static void memman_statistics_flexsize(struct memman *memman);
6853e202c1Schristos
6953e202c1Schristos static int
manage_block(struct memman * memman,unsigned int id,void * block,unsigned static_mem,unsigned entries)7053e202c1Schristos manage_block(struct memman *memman, unsigned int id, void *block,
7153e202c1Schristos unsigned static_mem, unsigned entries)
7253e202c1Schristos {
7353e202c1Schristos unsigned int i;
7453e202c1Schristos size_t alloc_size;
7553e202c1Schristos void *tmp, *realblock;
7653e202c1Schristos struct memman_blockman *bmp;
7753e202c1Schristos struct memman_block *memblock;
7853e202c1Schristos struct memman_node *memnodes;
7953e202c1Schristos
8053e202c1Schristos bmp = &memman->blockman[id];
8153e202c1Schristos alloc_size = MEMMAN_BLOCKNODE_SIZE(entries);
8253e202c1Schristos
8353e202c1Schristos if (static_mem) {
8453e202c1Schristos tmp = (void *)block;
8553e202c1Schristos realblock = (char *)block + alloc_size;
8653e202c1Schristos } else {
8753e202c1Schristos tmp = MEMMAN_SYSMALLOC(alloc_size);
8853e202c1Schristos if (!tmp) {
8953e202c1Schristos return (-1);
9053e202c1Schristos }
9153e202c1Schristos realblock = block;
9253e202c1Schristos
9353e202c1Schristos memman->allocated_mem += alloc_size;
9453e202c1Schristos memman->salloc_called++;
9553e202c1Schristos }
9653e202c1Schristos
9753e202c1Schristos memblock = (struct memman_block *)tmp;
9853e202c1Schristos memnodes = (struct memman_node *)((char *)tmp + sizeof(struct memman_block));
9953e202c1Schristos
10053e202c1Schristos memblock->block = realblock;
10153e202c1Schristos memblock->static_mem = static_mem;
10253e202c1Schristos memblock->allocated = entries;
10353e202c1Schristos memblock->available = entries;
10453e202c1Schristos if (!static_mem) {
10553e202c1Schristos alloc_size += roundup(bmp->size * entries, ROUNDUP_UNIT);
10653e202c1Schristos }
10753e202c1Schristos memblock->allocated_mem = alloc_size;
10853e202c1Schristos LIST_INSERT_HEAD(&bmp->block_list, memblock, links);
10953e202c1Schristos
11053e202c1Schristos for (i = 0; i < entries; ++i) {
11153e202c1Schristos memnodes[i].node = ((char *)realblock + (i * (bmp->size)));
11253e202c1Schristos memnodes[i].memblock = memblock;
11353e202c1Schristos LIST_INSERT_HEAD(&bmp->free_node_list, &memnodes[i], links);
11453e202c1Schristos }
11553e202c1Schristos bmp->available = entries;
11653e202c1Schristos
11753e202c1Schristos return (0);
11853e202c1Schristos }
11953e202c1Schristos
12053e202c1Schristos static int
blockman_init(struct memman * memman,unsigned int id)12153e202c1Schristos blockman_init(struct memman *memman, unsigned int id)
12253e202c1Schristos {
12353e202c1Schristos int status;
12453e202c1Schristos struct memman_blockman *bmp;
12553e202c1Schristos
12653e202c1Schristos bmp = &memman->blockman[id];
12753e202c1Schristos bmp->initialized = 1;
12853e202c1Schristos LIST_INIT(&bmp->block_list);
12953e202c1Schristos LIST_INIT(&bmp->free_node_list);
13053e202c1Schristos LIST_INIT(&bmp->occupied_node_list);
13153e202c1Schristos status = manage_block(memman, id, bmp->initial_block,
13253e202c1Schristos 1, MEMMAN_INITIAL_SIZE);
13353e202c1Schristos return (status);
13453e202c1Schristos }
13553e202c1Schristos
13653e202c1Schristos void *
memman_alloc(struct memman * memman,unsigned int id)13753e202c1Schristos memman_alloc(struct memman *memman, unsigned int id)
13853e202c1Schristos {
13953e202c1Schristos size_t alloc_size;
14053e202c1Schristos void *chunk, *block;
14153e202c1Schristos struct memman_blockman *bmp;
14253e202c1Schristos struct memman_node *memnode;
14353e202c1Schristos
14453e202c1Schristos if (memman->max_memid <= id) {
14553e202c1Schristos printf("memman_alloc: invalid memory type id\n");
14653e202c1Schristos return (NULL);
14753e202c1Schristos }
14853e202c1Schristos bmp = &memman->blockman[id];
14953e202c1Schristos if (!bmp->initialized) {
15053e202c1Schristos if (blockman_init(memman, id)) {
15153e202c1Schristos goto malloc_fail;
15253e202c1Schristos }
15353e202c1Schristos }
15453e202c1Schristos memman->alloc_called++;
15553e202c1Schristos
15653e202c1Schristos if (bmp->available == 0) {
15753e202c1Schristos alloc_size = roundup(bmp->size * MEMMAN_INCR_SIZE,
15853e202c1Schristos ROUNDUP_UNIT);
15953e202c1Schristos block = MEMMAN_SYSMALLOC(alloc_size);
16053e202c1Schristos if (!block) {
16153e202c1Schristos goto malloc_fail;
16253e202c1Schristos }
16353e202c1Schristos memman->required_mem += bmp->size * MEMMAN_INCR_SIZE;
16453e202c1Schristos memman->allocated_mem += alloc_size;
16553e202c1Schristos memman->salloc_called++;
16653e202c1Schristos
16753e202c1Schristos if (manage_block(memman, id, block, 0, MEMMAN_INCR_SIZE)) {
16853e202c1Schristos goto malloc_fail;
16953e202c1Schristos }
17053e202c1Schristos }
17153e202c1Schristos memnode = LIST_FIRST(&bmp->free_node_list);
17253e202c1Schristos LIST_REMOVE(memnode, links);
17353e202c1Schristos chunk = memnode->node;
17453e202c1Schristos LIST_INSERT_HEAD(&bmp->occupied_node_list, memnode, links);
17553e202c1Schristos memnode->memblock->available--;
17653e202c1Schristos bmp->available--;
17753e202c1Schristos
17853e202c1Schristos return (chunk);
17953e202c1Schristos
18053e202c1Schristos malloc_fail:
18153e202c1Schristos printf("memman_alloc: could not allocate memory\n");
18253e202c1Schristos return (NULL);
18353e202c1Schristos }
18453e202c1Schristos
18553e202c1Schristos static void
memman_flexsize_add_histogram(struct memman * memman,size_t size,int tolerance)18653e202c1Schristos memman_flexsize_add_histogram(struct memman *memman, size_t size,
18753e202c1Schristos int tolerance)
18853e202c1Schristos {
189*e7dd2c75Slukem unsigned int i;
19053e202c1Schristos int gap;
19153e202c1Schristos
19253e202c1Schristos if (size == 0) {
19353e202c1Schristos return;
19453e202c1Schristos }
19553e202c1Schristos for (i = 0; i < memman->flex_mem_histogram_ptr; i++) {
19653e202c1Schristos gap = memman->flex_mem_histogram[i].mem_size - size;
19753e202c1Schristos if (gap >= (tolerance * -1) && gap <= tolerance) {
19853e202c1Schristos memman->flex_mem_histogram[i].count++;
19953e202c1Schristos if (memman->flex_mem_histogram[i].mem_size < size) {
20053e202c1Schristos memman->flex_mem_histogram[i].mem_size = size;
20153e202c1Schristos }
20253e202c1Schristos return;
20353e202c1Schristos }
20453e202c1Schristos }
20553e202c1Schristos
20653e202c1Schristos if (memman->flex_mem_histogram_ptr == MEMMAN_HISTOGRAM_SIZE) {
20753e202c1Schristos memman_flexsize_add_histogram(memman, size, tolerance + 1);
20853e202c1Schristos return;
20953e202c1Schristos }
21053e202c1Schristos i = memman->flex_mem_histogram_ptr;
21153e202c1Schristos memman->flex_mem_histogram[i].mem_size = size;
21253e202c1Schristos memman->flex_mem_histogram[i].count = 1;
21353e202c1Schristos memman->flex_mem_histogram_ptr++;
21453e202c1Schristos }
21553e202c1Schristos
21653e202c1Schristos static int
memman_comp_histogram_size(const void * a,const void * b)21753e202c1Schristos memman_comp_histogram_size(const void *a, const void *b)
21853e202c1Schristos {
21953e202c1Schristos int delta;
22053e202c1Schristos
22153e202c1Schristos delta = ((const struct memman_histogram *)a)->mem_size -
22253e202c1Schristos ((const struct memman_histogram *)b)->mem_size;
22353e202c1Schristos return (delta);
22453e202c1Schristos }
22553e202c1Schristos
22653e202c1Schristos static void
memman_sort_histogram_by_size(struct memman * memman)22753e202c1Schristos memman_sort_histogram_by_size(struct memman *memman)
22853e202c1Schristos {
22953e202c1Schristos qsort(memman->flex_mem_histogram, memman->flex_mem_histogram_ptr,
23053e202c1Schristos sizeof(struct memman_histogram), memman_comp_histogram_size);
23153e202c1Schristos }
23253e202c1Schristos
23353e202c1Schristos void *
memman_alloc_flexsize(struct memman * memman,size_t size)23453e202c1Schristos memman_alloc_flexsize(struct memman *memman, size_t size)
23553e202c1Schristos {
23653e202c1Schristos void *mem;
23753e202c1Schristos struct memman_flexmem_info *info;
23853e202c1Schristos
23953e202c1Schristos if (size == 0) {
24053e202c1Schristos return (NULL);
24153e202c1Schristos }
24253e202c1Schristos if ((mem = MEMMAN_SYSMALLOC(size)) != NULL) { /* XXX */
24353e202c1Schristos
24453e202c1Schristos info = MEMMAN_SYSMALLOC(sizeof(struct memman_flexmem_info));
24553e202c1Schristos if (info) {
24653e202c1Schristos if (!memman->flex_mem_initialized) {
24753e202c1Schristos LIST_INIT(&memman->flexmem_info_list);
24853e202c1Schristos bzero(memman->flex_mem_histogram,
24953e202c1Schristos sizeof(struct memman_histogram));
25053e202c1Schristos memman->flex_mem_initialized = 1;
25153e202c1Schristos }
25253e202c1Schristos info->addr = mem;
25353e202c1Schristos info->mem_size = size;
25453e202c1Schristos LIST_INSERT_HEAD(&memman->flexmem_info_list, info, links);
25553e202c1Schristos }
25653e202c1Schristos memman->flex_alloc_called++;
25753e202c1Schristos memman->flex_salloc_called++;
25853e202c1Schristos memman->flex_required_mem += size;
25953e202c1Schristos memman->flex_allocated_mem += size;
26053e202c1Schristos if (memman->flex_mem_size_min == 0 ||
26153e202c1Schristos memman->flex_mem_size_min > size) {
26253e202c1Schristos memman->flex_mem_size_min = size;
26353e202c1Schristos }
26453e202c1Schristos if (memman->flex_mem_size_max < size) {
26553e202c1Schristos memman->flex_mem_size_max = size;
26653e202c1Schristos }
26753e202c1Schristos if (memman->flex_peak_mem_usage <
26853e202c1Schristos (memman->flex_allocated_mem - memman->flex_reclaimed_mem)) {
26953e202c1Schristos memman->flex_peak_mem_usage =
27053e202c1Schristos (memman->flex_allocated_mem - memman->flex_reclaimed_mem);
27153e202c1Schristos }
27253e202c1Schristos memman_flexsize_add_histogram(memman, size,
27353e202c1Schristos memman->flex_mem_histogram_initial_tolerance);
27453e202c1Schristos }
27553e202c1Schristos return (mem);
27653e202c1Schristos }
27753e202c1Schristos
27853e202c1Schristos static unsigned int
memman_guess_memid(struct memman * memman,void * chunk)27953e202c1Schristos memman_guess_memid(struct memman *memman, void *chunk)
28053e202c1Schristos {
28153e202c1Schristos unsigned int id;
28253e202c1Schristos struct memman_blockman *bmp;
28353e202c1Schristos struct memman_node *memnode;
28453e202c1Schristos
28553e202c1Schristos for (id = 0; id < memman->max_memid; id++) {
28653e202c1Schristos bmp = &memman->blockman[id];
28753e202c1Schristos if (!bmp->initialized) {
28853e202c1Schristos if (blockman_init(memman, id)) {
28953e202c1Schristos printf("memman_free: could not initialized\n");
29053e202c1Schristos }
29153e202c1Schristos }
29253e202c1Schristos LIST_FOREACH(memnode, &bmp->occupied_node_list, links) {
29353e202c1Schristos if (memnode->node == chunk) {
29453e202c1Schristos return (id); /* got it! */
29553e202c1Schristos }
29653e202c1Schristos }
29753e202c1Schristos }
29853e202c1Schristos return (memid_unkown); /* gave up */
29953e202c1Schristos }
30053e202c1Schristos
30153e202c1Schristos void
memman_free(struct memman * memman,unsigned int memid,void * chunk)30253e202c1Schristos memman_free(struct memman *memman, unsigned int memid, void *chunk)
30353e202c1Schristos {
30453e202c1Schristos unsigned int id;
30553e202c1Schristos unsigned found;
30653e202c1Schristos void *block;
30753e202c1Schristos struct memman_blockman *bmp;
30853e202c1Schristos struct memman_block *memblock;
30953e202c1Schristos struct memman_node *memnode;
31053e202c1Schristos
31153e202c1Schristos id = memid;
31253e202c1Schristos if (memid == memid_unkown) {
31353e202c1Schristos id = memman_guess_memid(memman, chunk);
31453e202c1Schristos }
31553e202c1Schristos if (memman->max_memid <= id) {
31653e202c1Schristos printf("memman_free: invalid memory type id\n");
31753e202c1Schristos MEMMAN_SYSABORT();
31853e202c1Schristos return;
31953e202c1Schristos }
32053e202c1Schristos bmp = &memman->blockman[id];
32153e202c1Schristos if (!bmp->initialized) {
32253e202c1Schristos if (blockman_init(memman, id)) {
32353e202c1Schristos printf("memman_free: could not initialized\n");
32453e202c1Schristos }
32553e202c1Schristos }
32653e202c1Schristos found = 0;
32753e202c1Schristos LIST_FOREACH(memnode, &bmp->occupied_node_list, links) {
32853e202c1Schristos if (memnode->node == chunk) {
32953e202c1Schristos found = 1;
33053e202c1Schristos break;
33153e202c1Schristos }
33253e202c1Schristos }
33353e202c1Schristos if (!found) {
33453e202c1Schristos printf("memman_free: invalid address\n");
33553e202c1Schristos return;
33653e202c1Schristos }
33753e202c1Schristos memman->free_called++;
33853e202c1Schristos
33953e202c1Schristos LIST_REMOVE(memnode, links);
34053e202c1Schristos memblock = memnode->memblock;
34153e202c1Schristos memblock->available++;
34253e202c1Schristos LIST_INSERT_HEAD(&bmp->free_node_list, memnode, links);
34353e202c1Schristos bmp->available++;
34453e202c1Schristos
34553e202c1Schristos if (!memblock->static_mem &&
34653e202c1Schristos memblock->available == memblock->allocated) {
34753e202c1Schristos LIST_FOREACH(memnode, &bmp->free_node_list, links) {
34853e202c1Schristos if (memnode->memblock != memblock) {
34953e202c1Schristos continue;
35053e202c1Schristos }
35153e202c1Schristos LIST_REMOVE(memnode, links);
35253e202c1Schristos bmp->available--;
35353e202c1Schristos }
35453e202c1Schristos block = memblock->block;
35553e202c1Schristos MEMMAN_SYSFREE(block);
35653e202c1Schristos memman->sfree_called++;
35753e202c1Schristos
35853e202c1Schristos LIST_REMOVE(memblock, links);
35953e202c1Schristos memman->sfree_called++;
36053e202c1Schristos memman->reclaimed_mem += memblock->allocated_mem;
36153e202c1Schristos MEMMAN_SYSFREE(memblock);
36253e202c1Schristos }
36353e202c1Schristos }
36453e202c1Schristos
36553e202c1Schristos void
memman_free_flexsize(struct memman * memman,void * chunk)36653e202c1Schristos memman_free_flexsize(struct memman *memman, void *chunk)
36753e202c1Schristos {
36853e202c1Schristos struct memman_flexmem_info *info;
36953e202c1Schristos
37053e202c1Schristos LIST_FOREACH(info, &memman->flexmem_info_list, links) {
37153e202c1Schristos if (info->addr == chunk) {
37253e202c1Schristos memman->flex_reclaimed_mem += info->mem_size;
37353e202c1Schristos LIST_REMOVE(info, links);
37453e202c1Schristos MEMMAN_SYSFREE(info);
37553e202c1Schristos break;
37653e202c1Schristos }
37753e202c1Schristos }
37853e202c1Schristos /* XXX */
37953e202c1Schristos memman->flex_free_called++;
38053e202c1Schristos memman->flex_sfree_called++;
38153e202c1Schristos MEMMAN_SYSFREE(chunk);
38253e202c1Schristos }
38353e202c1Schristos
38453e202c1Schristos void
memman_freeall(struct memman * memman)38553e202c1Schristos memman_freeall(struct memman *memman)
38653e202c1Schristos {
387*e7dd2c75Slukem unsigned int id;
38853e202c1Schristos void *chunk;
38953e202c1Schristos struct memman_blockman *bmp;
39053e202c1Schristos struct memman_node *memnode;
39153e202c1Schristos struct memman_block *memblock;
39253e202c1Schristos struct memman_flexmem_info *info;
39353e202c1Schristos
39453e202c1Schristos for (id = 0; id < memman->max_memid; id++) {
39553e202c1Schristos bmp = &memman->blockman[id];
39653e202c1Schristos
39753e202c1Schristos while ((memnode = LIST_FIRST(&bmp->occupied_node_list))) {
39853e202c1Schristos chunk = memnode->node;
399*e7dd2c75Slukem printf("memman_freeall: fixed size (id = %u)\n", id);
40053e202c1Schristos memman_free(memman, id, chunk);
40153e202c1Schristos }
40253e202c1Schristos while ((memblock = LIST_FIRST(&bmp->block_list))) {
40353e202c1Schristos LIST_REMOVE(memblock, links);
40453e202c1Schristos if (!memblock->static_mem) {
40553e202c1Schristos memman->sfree_called++;
40653e202c1Schristos memman->reclaimed_mem += memblock->allocated_mem;
40753e202c1Schristos MEMMAN_SYSFREE(memblock);
40853e202c1Schristos }
40953e202c1Schristos }
41053e202c1Schristos bmp->initialized = 0;
41153e202c1Schristos }
41253e202c1Schristos
41353e202c1Schristos LIST_FOREACH(info, &memman->flexmem_info_list, links) {
4147ac7d15dSdogcow printf("memman_freeall: flex size (size = %zd, addr = %p)\n",
41553e202c1Schristos info->mem_size, info->addr);
41653e202c1Schristos memman_free_flexsize(memman, info->addr);
41753e202c1Schristos }
41853e202c1Schristos }
41953e202c1Schristos
42053e202c1Schristos static void
memman_statistics_fixedsize(struct memman * memman)42153e202c1Schristos memman_statistics_fixedsize(struct memman *memman)
42253e202c1Schristos {
42353e202c1Schristos printf(" fixed size memory blocks\n");
42453e202c1Schristos printf(" alloc(): %d times\n", memman->alloc_called);
42553e202c1Schristos printf(" system malloc(): %d times\n", memman->salloc_called);
42653e202c1Schristos printf(" free(): %d times\n", memman->free_called);
42753e202c1Schristos printf(" system free(): %d times\n", memman->sfree_called);
4287ac7d15dSdogcow printf(" required memory: %zd bytes\n", memman->required_mem);
4297ac7d15dSdogcow printf(" allocated memory: %zd bytes\n", memman->allocated_mem);
4307ac7d15dSdogcow printf(" reclaimed memory: %zd bytes\n", memman->reclaimed_mem);
43153e202c1Schristos }
43253e202c1Schristos
43353e202c1Schristos static void
memman_statistics_flexsize(struct memman * memman)43453e202c1Schristos memman_statistics_flexsize(struct memman *memman)
43553e202c1Schristos {
436*e7dd2c75Slukem unsigned int i;
43753e202c1Schristos
43853e202c1Schristos printf(" flexible size memory blocks\n");
43953e202c1Schristos printf(" alloc(): %d times\n", memman->flex_alloc_called);
44053e202c1Schristos printf(" system malloc(): %d times\n", memman->flex_salloc_called);
44153e202c1Schristos printf(" free(): %d times\n", memman->flex_free_called);
44253e202c1Schristos printf(" system free(): %d times\n", memman->flex_sfree_called);
4437ac7d15dSdogcow printf(" required memory: %zd bytes\n", memman->flex_required_mem);
4447ac7d15dSdogcow printf(" allocated memory: %zd bytes\n", memman->flex_allocated_mem);
4457ac7d15dSdogcow printf(" reclaimed memory: %zd bytes\n", memman->flex_reclaimed_mem);
4467ac7d15dSdogcow printf(" peak memory usage: %zd bytes\n", memman->flex_peak_mem_usage);
4477ac7d15dSdogcow printf(" min memory size: %zd bytes\n", memman->flex_mem_size_min);
4487ac7d15dSdogcow printf(" max memory size: %zd bytes\n", memman->flex_mem_size_max);
4497ac7d15dSdogcow printf(" avg memory size: %zd bytes\n",
45053e202c1Schristos (memman->flex_alloc_called) ?
45153e202c1Schristos memman->flex_allocated_mem / memman->flex_alloc_called : 0);
45253e202c1Schristos
45353e202c1Schristos printf(" memory size histogram (%d entries):\n",
45453e202c1Schristos memman->flex_mem_histogram_ptr);
45553e202c1Schristos printf(" size count\n");
45653e202c1Schristos memman_sort_histogram_by_size(memman);
45753e202c1Schristos for (i = 0; i < memman->flex_mem_histogram_ptr; i++) {
458*e7dd2c75Slukem printf(" %zu %d\n",
45953e202c1Schristos memman->flex_mem_histogram[i].mem_size,
46053e202c1Schristos memman->flex_mem_histogram[i].count);
46153e202c1Schristos }
46253e202c1Schristos }
46353e202c1Schristos
46453e202c1Schristos void
memman_statistics(struct memman * memman)46553e202c1Schristos memman_statistics(struct memman *memman)
46653e202c1Schristos {
46753e202c1Schristos printf("memman: reporting statistics\n");
46853e202c1Schristos memman_statistics_fixedsize(memman);
46953e202c1Schristos memman_statistics_flexsize(memman);
47053e202c1Schristos }
47153e202c1Schristos
47253e202c1Schristos size_t
memman_memid2size(struct memman * memman,unsigned int id)47353e202c1Schristos memman_memid2size(struct memman *memman, unsigned int id)
47453e202c1Schristos {
47553e202c1Schristos if (memman->max_memid <= id) {
47653e202c1Schristos printf("memman_alloc: invalid memory type id\n");
47753e202c1Schristos return (0);
47853e202c1Schristos }
47953e202c1Schristos return (memman->blockman[id].size);
48053e202c1Schristos }
481