xref: /netbsd-src/usr.sbin/acpitools/aml/aml_memman.c (revision e7dd2c7514af4e72722e9e1d552190a40fd852d2)
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