Home | History | Annotate | Line # | Download | only in aml
      1  1.3     lukem /*	$NetBSD: aml_memman.c,v 1.3 2009/01/18 09:46:59 lukem Exp $	*/
      2  1.1  christos 
      3  1.1  christos /*-
      4  1.1  christos  * Copyright (c) 1999, 2000 Mitsuru IWASAKI <iwasaki (at) FreeBSD.org>
      5  1.1  christos  * All rights reserved.
      6  1.1  christos  *
      7  1.1  christos  * Redistribution and use in source and binary forms, with or without
      8  1.1  christos  * modification, are permitted provided that the following conditions
      9  1.1  christos  * are met:
     10  1.1  christos  * 1. Redistributions of source code must retain the above copyright
     11  1.1  christos  *    notice, this list of conditions and the following disclaimer.
     12  1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  christos  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  christos  *    documentation and/or other materials provided with the distribution.
     15  1.1  christos  *
     16  1.1  christos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  1.1  christos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  1.1  christos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  1.1  christos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  1.1  christos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  1.1  christos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  1.1  christos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  1.1  christos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  1.1  christos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  1.1  christos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  1.1  christos  * SUCH DAMAGE.
     27  1.1  christos  *
     28  1.1  christos  *	Id: aml_memman.c,v 1.10 2000/08/09 14:47:43 iwasaki Exp
     29  1.1  christos  *	$FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_memman.c,v 1.2 2000/11/09 06:24:45 iwasaki Exp $
     30  1.1  christos  */
     31  1.1  christos #include <sys/cdefs.h>
     32  1.3     lukem __RCSID("$NetBSD: aml_memman.c,v 1.3 2009/01/18 09:46:59 lukem Exp $");
     33  1.1  christos 
     34  1.1  christos /*
     35  1.1  christos  * Generic Memory Management
     36  1.1  christos  */
     37  1.1  christos 
     38  1.1  christos #include <sys/param.h>
     39  1.1  christos 
     40  1.1  christos #include <aml/aml_memman.h>
     41  1.1  christos 
     42  1.1  christos #ifndef _KERNEL
     43  1.1  christos #include <stdlib.h>
     44  1.1  christos #include <stdio.h>
     45  1.1  christos #include <string.h>
     46  1.1  christos #else /* _KERNEL */
     47  1.1  christos #include <sys/kernel.h>
     48  1.1  christos #include <sys/systm.h>
     49  1.1  christos #include <sys/malloc.h>
     50  1.1  christos MALLOC_DEFINE(M_MEMMAN, "memman", "Generic and Simple Memory Management");
     51  1.1  christos #endif /* !_KERNEL */
     52  1.1  christos 
     53  1.1  christos unsigned int	memid_unkown = 255;
     54  1.1  christos 
     55  1.1  christos static int		 manage_block(struct memman *memman, unsigned int id,
     56  1.1  christos 				      void *block, unsigned static_mem,
     57  1.1  christos 				      unsigned entries);
     58  1.1  christos static int		 blockman_init(struct memman *memman, unsigned int id);
     59  1.1  christos static void		 memman_flexsize_add_histogram(struct memman *memman,
     60  1.1  christos 						       size_t size,
     61  1.1  christos 						       int tolerance);
     62  1.1  christos static int		 memman_comp_histogram_size(const void *a,
     63  1.1  christos 						    const void *b);
     64  1.1  christos static void		 memman_sort_histogram_by_size(struct memman *memman);
     65  1.1  christos static unsigned int	 memman_guess_memid(struct memman *memman, void *chunk);
     66  1.1  christos static void		 memman_statistics_fixedsize(struct memman *memman);
     67  1.1  christos static void		 memman_statistics_flexsize(struct memman *memman);
     68  1.1  christos 
     69  1.1  christos static int
     70  1.1  christos manage_block(struct memman *memman, unsigned int id, void *block,
     71  1.1  christos     unsigned static_mem, unsigned entries)
     72  1.1  christos {
     73  1.1  christos 	unsigned int	i;
     74  1.1  christos 	size_t	alloc_size;
     75  1.1  christos 	void	*tmp, *realblock;
     76  1.1  christos 	struct	memman_blockman	*bmp;
     77  1.1  christos 	struct	memman_block *memblock;
     78  1.1  christos 	struct	memman_node *memnodes;
     79  1.1  christos 
     80  1.1  christos 	bmp = &memman->blockman[id];
     81  1.1  christos 	alloc_size = MEMMAN_BLOCKNODE_SIZE(entries);
     82  1.1  christos 
     83  1.1  christos 	if (static_mem) {
     84  1.1  christos 		tmp = (void *)block;
     85  1.1  christos 		realblock = (char *)block + alloc_size;
     86  1.1  christos 	} else {
     87  1.1  christos 		tmp = MEMMAN_SYSMALLOC(alloc_size);
     88  1.1  christos 		if (!tmp) {
     89  1.1  christos 			return (-1);
     90  1.1  christos 		}
     91  1.1  christos 		realblock = block;
     92  1.1  christos 
     93  1.1  christos 		memman->allocated_mem += alloc_size;
     94  1.1  christos 		memman->salloc_called++;
     95  1.1  christos 	}
     96  1.1  christos 
     97  1.1  christos 	memblock = (struct memman_block *)tmp;
     98  1.1  christos 	memnodes = (struct memman_node *)((char *)tmp + sizeof(struct memman_block));
     99  1.1  christos 
    100  1.1  christos 	memblock->block = realblock;
    101  1.1  christos 	memblock->static_mem = static_mem;
    102  1.1  christos 	memblock->allocated = entries;
    103  1.1  christos 	memblock->available = entries;
    104  1.1  christos 	if (!static_mem) {
    105  1.1  christos 		alloc_size += roundup(bmp->size * entries, ROUNDUP_UNIT);
    106  1.1  christos 	}
    107  1.1  christos 	memblock->allocated_mem = alloc_size;
    108  1.1  christos 	LIST_INSERT_HEAD(&bmp->block_list, memblock, links);
    109  1.1  christos 
    110  1.1  christos 	for (i = 0; i < entries; ++i) {
    111  1.1  christos 		memnodes[i].node = ((char *)realblock + (i * (bmp->size)));
    112  1.1  christos 		memnodes[i].memblock = memblock;
    113  1.1  christos 		LIST_INSERT_HEAD(&bmp->free_node_list, &memnodes[i], links);
    114  1.1  christos 	}
    115  1.1  christos 	bmp->available = entries;
    116  1.1  christos 
    117  1.1  christos 	return (0);
    118  1.1  christos }
    119  1.1  christos 
    120  1.1  christos static int
    121  1.1  christos blockman_init(struct memman *memman, unsigned int id)
    122  1.1  christos {
    123  1.1  christos 	int	status;
    124  1.1  christos 	struct	memman_blockman *bmp;
    125  1.1  christos 
    126  1.1  christos 	bmp = &memman->blockman[id];
    127  1.1  christos 	bmp->initialized = 1;
    128  1.1  christos 	LIST_INIT(&bmp->block_list);
    129  1.1  christos 	LIST_INIT(&bmp->free_node_list);
    130  1.1  christos 	LIST_INIT(&bmp->occupied_node_list);
    131  1.1  christos 	status = manage_block(memman, id, bmp->initial_block,
    132  1.1  christos 	    1, MEMMAN_INITIAL_SIZE);
    133  1.1  christos 	return (status);
    134  1.1  christos }
    135  1.1  christos 
    136  1.1  christos void *
    137  1.1  christos memman_alloc(struct memman *memman, unsigned int id)
    138  1.1  christos {
    139  1.1  christos 	size_t	alloc_size;
    140  1.1  christos 	void	*chunk, *block;
    141  1.1  christos 	struct	memman_blockman *bmp;
    142  1.1  christos 	struct	memman_node *memnode;
    143  1.1  christos 
    144  1.1  christos 	if (memman->max_memid <= id) {
    145  1.1  christos 		printf("memman_alloc: invalid memory type id\n");
    146  1.1  christos 		return (NULL);
    147  1.1  christos 	}
    148  1.1  christos 	bmp = &memman->blockman[id];
    149  1.1  christos 	if (!bmp->initialized) {
    150  1.1  christos 		if (blockman_init(memman, id)) {
    151  1.1  christos 			goto malloc_fail;
    152  1.1  christos 		}
    153  1.1  christos 	}
    154  1.1  christos 	memman->alloc_called++;
    155  1.1  christos 
    156  1.1  christos 	if (bmp->available == 0) {
    157  1.1  christos 		alloc_size = roundup(bmp->size * MEMMAN_INCR_SIZE,
    158  1.1  christos 		    ROUNDUP_UNIT);
    159  1.1  christos 		block = MEMMAN_SYSMALLOC(alloc_size);
    160  1.1  christos 		if (!block) {
    161  1.1  christos 			goto malloc_fail;
    162  1.1  christos 		}
    163  1.1  christos 		memman->required_mem += bmp->size * MEMMAN_INCR_SIZE;
    164  1.1  christos 		memman->allocated_mem += alloc_size;
    165  1.1  christos 		memman->salloc_called++;
    166  1.1  christos 
    167  1.1  christos 		if (manage_block(memman, id, block, 0, MEMMAN_INCR_SIZE)) {
    168  1.1  christos 			goto malloc_fail;
    169  1.1  christos 		}
    170  1.1  christos 	}
    171  1.1  christos 	memnode = LIST_FIRST(&bmp->free_node_list);
    172  1.1  christos 	LIST_REMOVE(memnode, links);
    173  1.1  christos 	chunk = memnode->node;
    174  1.1  christos 	LIST_INSERT_HEAD(&bmp->occupied_node_list, memnode, links);
    175  1.1  christos 	memnode->memblock->available--;
    176  1.1  christos 	bmp->available--;
    177  1.1  christos 
    178  1.1  christos 	return (chunk);
    179  1.1  christos 
    180  1.1  christos malloc_fail:
    181  1.1  christos 	printf("memman_alloc: could not allocate memory\n");
    182  1.1  christos 	return (NULL);
    183  1.1  christos }
    184  1.1  christos 
    185  1.1  christos static void
    186  1.1  christos memman_flexsize_add_histogram(struct memman *memman, size_t size,
    187  1.1  christos     int tolerance)
    188  1.1  christos {
    189  1.3     lukem 	unsigned int i;
    190  1.1  christos 	int	gap;
    191  1.1  christos 
    192  1.1  christos 	if (size == 0) {
    193  1.1  christos 		return;
    194  1.1  christos 	}
    195  1.1  christos 	for (i = 0; i < memman->flex_mem_histogram_ptr; i++) {
    196  1.1  christos 		gap = memman->flex_mem_histogram[i].mem_size - size;
    197  1.1  christos 		if (gap >= (tolerance * -1) && gap <= tolerance) {
    198  1.1  christos 			memman->flex_mem_histogram[i].count++;
    199  1.1  christos 			if (memman->flex_mem_histogram[i].mem_size < size) {
    200  1.1  christos 				memman->flex_mem_histogram[i].mem_size = size;
    201  1.1  christos 			}
    202  1.1  christos 			return;
    203  1.1  christos 		}
    204  1.1  christos 	}
    205  1.1  christos 
    206  1.1  christos 	if (memman->flex_mem_histogram_ptr == MEMMAN_HISTOGRAM_SIZE) {
    207  1.1  christos 		memman_flexsize_add_histogram(memman, size, tolerance + 1);
    208  1.1  christos 		return;
    209  1.1  christos 	}
    210  1.1  christos 	i = memman->flex_mem_histogram_ptr;
    211  1.1  christos 	memman->flex_mem_histogram[i].mem_size = size;
    212  1.1  christos 	memman->flex_mem_histogram[i].count = 1;
    213  1.1  christos 	memman->flex_mem_histogram_ptr++;
    214  1.1  christos }
    215  1.1  christos 
    216  1.1  christos static int
    217  1.1  christos memman_comp_histogram_size(const void *a, const void *b)
    218  1.1  christos {
    219  1.1  christos 	int	delta;
    220  1.1  christos 
    221  1.1  christos 	delta = ((const struct memman_histogram *)a)->mem_size -
    222  1.1  christos 	    ((const struct memman_histogram *)b)->mem_size;
    223  1.1  christos 	return (delta);
    224  1.1  christos }
    225  1.1  christos 
    226  1.1  christos static void
    227  1.1  christos memman_sort_histogram_by_size(struct memman *memman)
    228  1.1  christos {
    229  1.1  christos 	qsort(memman->flex_mem_histogram, memman->flex_mem_histogram_ptr,
    230  1.1  christos 	    sizeof(struct memman_histogram), memman_comp_histogram_size);
    231  1.1  christos }
    232  1.1  christos 
    233  1.1  christos void *
    234  1.1  christos memman_alloc_flexsize(struct memman *memman, size_t size)
    235  1.1  christos {
    236  1.1  christos 	void	*mem;
    237  1.1  christos 	struct	memman_flexmem_info *info;
    238  1.1  christos 
    239  1.1  christos 	if (size == 0) {
    240  1.1  christos 		return (NULL);
    241  1.1  christos 	}
    242  1.1  christos 	if ((mem = MEMMAN_SYSMALLOC(size)) != NULL) {	/* XXX */
    243  1.1  christos 
    244  1.1  christos 		info = MEMMAN_SYSMALLOC(sizeof(struct memman_flexmem_info));
    245  1.1  christos 		if (info) {
    246  1.1  christos 			if (!memman->flex_mem_initialized) {
    247  1.1  christos 				LIST_INIT(&memman->flexmem_info_list);
    248  1.1  christos 				bzero(memman->flex_mem_histogram,
    249  1.1  christos 				    sizeof(struct memman_histogram));
    250  1.1  christos 				memman->flex_mem_initialized = 1;
    251  1.1  christos 			}
    252  1.1  christos 			info->addr = mem;
    253  1.1  christos 			info->mem_size = size;
    254  1.1  christos 			LIST_INSERT_HEAD(&memman->flexmem_info_list, info, links);
    255  1.1  christos 		}
    256  1.1  christos 		memman->flex_alloc_called++;
    257  1.1  christos 		memman->flex_salloc_called++;
    258  1.1  christos 		memman->flex_required_mem += size;
    259  1.1  christos 		memman->flex_allocated_mem += size;
    260  1.1  christos 		if (memman->flex_mem_size_min == 0 ||
    261  1.1  christos 		    memman->flex_mem_size_min > size) {
    262  1.1  christos 			memman->flex_mem_size_min = size;
    263  1.1  christos 		}
    264  1.1  christos 		if (memman->flex_mem_size_max < size) {
    265  1.1  christos 			memman->flex_mem_size_max = size;
    266  1.1  christos 		}
    267  1.1  christos 		if (memman->flex_peak_mem_usage <
    268  1.1  christos 		    (memman->flex_allocated_mem - memman->flex_reclaimed_mem)) {
    269  1.1  christos 			memman->flex_peak_mem_usage =
    270  1.1  christos 			    (memman->flex_allocated_mem - memman->flex_reclaimed_mem);
    271  1.1  christos 		}
    272  1.1  christos 		memman_flexsize_add_histogram(memman, size,
    273  1.1  christos 		    memman->flex_mem_histogram_initial_tolerance);
    274  1.1  christos 	}
    275  1.1  christos 	return (mem);
    276  1.1  christos }
    277  1.1  christos 
    278  1.1  christos static unsigned int
    279  1.1  christos memman_guess_memid(struct memman *memman, void *chunk)
    280  1.1  christos {
    281  1.1  christos 	unsigned int	id;
    282  1.1  christos 	struct	memman_blockman *bmp;
    283  1.1  christos 	struct	memman_node *memnode;
    284  1.1  christos 
    285  1.1  christos 	for (id = 0; id < memman->max_memid; id++) {
    286  1.1  christos 		bmp = &memman->blockman[id];
    287  1.1  christos 		if (!bmp->initialized) {
    288  1.1  christos 			if (blockman_init(memman, id)) {
    289  1.1  christos 				printf("memman_free: could not initialized\n");
    290  1.1  christos 			}
    291  1.1  christos 		}
    292  1.1  christos 		LIST_FOREACH(memnode, &bmp->occupied_node_list, links) {
    293  1.1  christos 			if (memnode->node == chunk) {
    294  1.1  christos 				return (id);	/* got it! */
    295  1.1  christos 			}
    296  1.1  christos 		}
    297  1.1  christos 	}
    298  1.1  christos 	return (memid_unkown);	/* gave up */
    299  1.1  christos }
    300  1.1  christos 
    301  1.1  christos void
    302  1.1  christos memman_free(struct memman *memman, unsigned int memid, void *chunk)
    303  1.1  christos {
    304  1.1  christos 	unsigned int	id;
    305  1.1  christos 	unsigned	found;
    306  1.1  christos 	void	*block;
    307  1.1  christos 	struct	memman_blockman *bmp;
    308  1.1  christos 	struct	memman_block *memblock;
    309  1.1  christos 	struct	memman_node *memnode;
    310  1.1  christos 
    311  1.1  christos 	id = memid;
    312  1.1  christos 	if (memid == memid_unkown) {
    313  1.1  christos 		id = memman_guess_memid(memman, chunk);
    314  1.1  christos 	}
    315  1.1  christos 	if (memman->max_memid <= id) {
    316  1.1  christos 		printf("memman_free: invalid memory type id\n");
    317  1.1  christos 		MEMMAN_SYSABORT();
    318  1.1  christos 		return;
    319  1.1  christos 	}
    320  1.1  christos 	bmp = &memman->blockman[id];
    321  1.1  christos 	if (!bmp->initialized) {
    322  1.1  christos 		if (blockman_init(memman, id)) {
    323  1.1  christos 			printf("memman_free: could not initialized\n");
    324  1.1  christos 		}
    325  1.1  christos 	}
    326  1.1  christos 	found = 0;
    327  1.1  christos 	LIST_FOREACH(memnode, &bmp->occupied_node_list, links) {
    328  1.1  christos 		if (memnode->node == chunk) {
    329  1.1  christos 			found = 1;
    330  1.1  christos 			break;
    331  1.1  christos 		}
    332  1.1  christos 	}
    333  1.1  christos 	if (!found) {
    334  1.1  christos 		printf("memman_free: invalid address\n");
    335  1.1  christos 		return;
    336  1.1  christos 	}
    337  1.1  christos 	memman->free_called++;
    338  1.1  christos 
    339  1.1  christos 	LIST_REMOVE(memnode, links);
    340  1.1  christos 	memblock = memnode->memblock;
    341  1.1  christos 	memblock->available++;
    342  1.1  christos 	LIST_INSERT_HEAD(&bmp->free_node_list, memnode, links);
    343  1.1  christos 	bmp->available++;
    344  1.1  christos 
    345  1.1  christos 	if (!memblock->static_mem &&
    346  1.1  christos 	    memblock->available == memblock->allocated) {
    347  1.1  christos 		LIST_FOREACH(memnode, &bmp->free_node_list, links) {
    348  1.1  christos 			if (memnode->memblock != memblock) {
    349  1.1  christos 				continue;
    350  1.1  christos 			}
    351  1.1  christos 			LIST_REMOVE(memnode, links);
    352  1.1  christos 			bmp->available--;
    353  1.1  christos 		}
    354  1.1  christos 		block = memblock->block;
    355  1.1  christos 		MEMMAN_SYSFREE(block);
    356  1.1  christos 		memman->sfree_called++;
    357  1.1  christos 
    358  1.1  christos 		LIST_REMOVE(memblock, links);
    359  1.1  christos 		memman->sfree_called++;
    360  1.1  christos 		memman->reclaimed_mem += memblock->allocated_mem;
    361  1.1  christos 		MEMMAN_SYSFREE(memblock);
    362  1.1  christos 	}
    363  1.1  christos }
    364  1.1  christos 
    365  1.1  christos void
    366  1.1  christos memman_free_flexsize(struct memman *memman, void *chunk)
    367  1.1  christos {
    368  1.1  christos 	struct	memman_flexmem_info *info;
    369  1.1  christos 
    370  1.1  christos 	LIST_FOREACH(info, &memman->flexmem_info_list, links) {
    371  1.1  christos 		if (info->addr == chunk) {
    372  1.1  christos 			memman->flex_reclaimed_mem += info->mem_size;
    373  1.1  christos 			LIST_REMOVE(info, links);
    374  1.1  christos 			MEMMAN_SYSFREE(info);
    375  1.1  christos 			break;
    376  1.1  christos 		}
    377  1.1  christos 	}
    378  1.1  christos 	/* XXX */
    379  1.1  christos 	memman->flex_free_called++;
    380  1.1  christos 	memman->flex_sfree_called++;
    381  1.1  christos 	MEMMAN_SYSFREE(chunk);
    382  1.1  christos }
    383  1.1  christos 
    384  1.1  christos void
    385  1.1  christos memman_freeall(struct memman *memman)
    386  1.1  christos {
    387  1.3     lukem 	unsigned int id;
    388  1.1  christos 	void	*chunk;
    389  1.1  christos 	struct	memman_blockman *bmp;
    390  1.1  christos 	struct	memman_node *memnode;
    391  1.1  christos 	struct	memman_block *memblock;
    392  1.1  christos 	struct	memman_flexmem_info *info;
    393  1.1  christos 
    394  1.1  christos 	for (id = 0; id < memman->max_memid; id++) {
    395  1.1  christos 		bmp = &memman->blockman[id];
    396  1.1  christos 
    397  1.1  christos 		while ((memnode = LIST_FIRST(&bmp->occupied_node_list))) {
    398  1.1  christos 			chunk = memnode->node;
    399  1.3     lukem 			printf("memman_freeall: fixed size (id = %u)\n", id);
    400  1.1  christos 			memman_free(memman, id, chunk);
    401  1.1  christos 		}
    402  1.1  christos 		while ((memblock = LIST_FIRST(&bmp->block_list))) {
    403  1.1  christos 			LIST_REMOVE(memblock, links);
    404  1.1  christos 			if (!memblock->static_mem) {
    405  1.1  christos 				memman->sfree_called++;
    406  1.1  christos 				memman->reclaimed_mem += memblock->allocated_mem;
    407  1.1  christos 				MEMMAN_SYSFREE(memblock);
    408  1.1  christos 			}
    409  1.1  christos 		}
    410  1.1  christos 		bmp->initialized = 0;
    411  1.1  christos 	}
    412  1.1  christos 
    413  1.1  christos 	LIST_FOREACH(info, &memman->flexmem_info_list, links) {
    414  1.2    dogcow 		printf("memman_freeall: flex size (size = %zd, addr = %p)\n",
    415  1.1  christos 		    info->mem_size, info->addr);
    416  1.1  christos 		memman_free_flexsize(memman, info->addr);
    417  1.1  christos 	}
    418  1.1  christos }
    419  1.1  christos 
    420  1.1  christos static void
    421  1.1  christos memman_statistics_fixedsize(struct memman *memman)
    422  1.1  christos {
    423  1.1  christos 	printf("  fixed size memory blocks\n");
    424  1.1  christos 	printf("    alloc():		%d times\n", memman->alloc_called);
    425  1.1  christos 	printf("    system malloc():	%d times\n", memman->salloc_called);
    426  1.1  christos 	printf("    free():		%d times\n", memman->free_called);
    427  1.1  christos 	printf("    system free():	%d times\n", memman->sfree_called);
    428  1.2    dogcow 	printf("    required memory:	%zd bytes\n", memman->required_mem);
    429  1.2    dogcow 	printf("    allocated memory:	%zd bytes\n", memman->allocated_mem);
    430  1.2    dogcow 	printf("    reclaimed memory:	%zd bytes\n", memman->reclaimed_mem);
    431  1.1  christos }
    432  1.1  christos 
    433  1.1  christos static void
    434  1.1  christos memman_statistics_flexsize(struct memman *memman)
    435  1.1  christos {
    436  1.3     lukem 	unsigned int	i;
    437  1.1  christos 
    438  1.1  christos 	printf("  flexible size memory blocks\n");
    439  1.1  christos 	printf("    alloc():		%d times\n", memman->flex_alloc_called);
    440  1.1  christos 	printf("    system malloc():	%d times\n", memman->flex_salloc_called);
    441  1.1  christos 	printf("    free():		%d times\n", memman->flex_free_called);
    442  1.1  christos 	printf("    system free():	%d times\n", memman->flex_sfree_called);
    443  1.2    dogcow 	printf("    required memory:	%zd bytes\n", memman->flex_required_mem);
    444  1.2    dogcow 	printf("    allocated memory:	%zd bytes\n", memman->flex_allocated_mem);
    445  1.2    dogcow 	printf("    reclaimed memory:	%zd bytes\n", memman->flex_reclaimed_mem);
    446  1.2    dogcow 	printf("    peak memory usage:	%zd bytes\n", memman->flex_peak_mem_usage);
    447  1.2    dogcow 	printf("    min memory size:	%zd bytes\n", memman->flex_mem_size_min);
    448  1.2    dogcow 	printf("    max memory size:	%zd bytes\n", memman->flex_mem_size_max);
    449  1.2    dogcow 	printf("    avg memory size:	%zd bytes\n",
    450  1.1  christos 	    (memman->flex_alloc_called) ?
    451  1.1  christos 	    memman->flex_allocated_mem / memman->flex_alloc_called : 0);
    452  1.1  christos 
    453  1.1  christos 	printf("    memory size histogram (%d entries):\n",
    454  1.1  christos 	    memman->flex_mem_histogram_ptr);
    455  1.1  christos 	printf("	size	count\n");
    456  1.1  christos 	memman_sort_histogram_by_size(memman);
    457  1.1  christos 	for (i = 0; i < memman->flex_mem_histogram_ptr; i++) {
    458  1.3     lukem 		printf("	%zu	%d\n",
    459  1.1  christos 		    memman->flex_mem_histogram[i].mem_size,
    460  1.1  christos 		    memman->flex_mem_histogram[i].count);
    461  1.1  christos 	}
    462  1.1  christos }
    463  1.1  christos 
    464  1.1  christos void
    465  1.1  christos memman_statistics(struct memman *memman)
    466  1.1  christos {
    467  1.1  christos 	printf("memman: reporting statistics\n");
    468  1.1  christos 	memman_statistics_fixedsize(memman);
    469  1.1  christos 	memman_statistics_flexsize(memman);
    470  1.1  christos }
    471  1.1  christos 
    472  1.1  christos size_t
    473  1.1  christos memman_memid2size(struct memman *memman, unsigned int id)
    474  1.1  christos {
    475  1.1  christos 	if (memman->max_memid <= id) {
    476  1.1  christos 		printf("memman_alloc: invalid memory type id\n");
    477  1.1  christos 		return (0);
    478  1.1  christos 	}
    479  1.1  christos 	return (memman->blockman[id].size);
    480  1.1  christos }
    481