Home | History | Annotate | Line # | Download | only in kern
subr_pool.c revision 1.4.2.2
      1  1.4.2.2      eeh /*	$NetBSD: subr_pool.c,v 1.4.2.2 1998/08/08 03:06:56 eeh Exp $	*/
      2      1.1       pk 
      3      1.1       pk /*-
      4      1.1       pk  * Copyright (c) 1997 The NetBSD Foundation, Inc.
      5      1.1       pk  * All rights reserved.
      6      1.1       pk  *
      7      1.1       pk  * This code is derived from software contributed to The NetBSD Foundation
      8      1.1       pk  * by Paul Kranenburg.
      9      1.1       pk  *
     10      1.1       pk  * Redistribution and use in source and binary forms, with or without
     11      1.1       pk  * modification, are permitted provided that the following conditions
     12      1.1       pk  * are met:
     13      1.1       pk  * 1. Redistributions of source code must retain the above copyright
     14      1.1       pk  *    notice, this list of conditions and the following disclaimer.
     15      1.1       pk  * 2. Redistributions in binary form must reproduce the above copyright
     16      1.1       pk  *    notice, this list of conditions and the following disclaimer in the
     17      1.1       pk  *    documentation and/or other materials provided with the distribution.
     18      1.1       pk  * 3. All advertising materials mentioning features or use of this software
     19      1.1       pk  *    must display the following acknowledgement:
     20      1.1       pk  *        This product includes software developed by the NetBSD
     21      1.1       pk  *        Foundation, Inc. and its contributors.
     22      1.1       pk  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23      1.1       pk  *    contributors may be used to endorse or promote products derived
     24      1.1       pk  *    from this software without specific prior written permission.
     25      1.1       pk  *
     26      1.1       pk  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27      1.1       pk  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28      1.1       pk  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29      1.1       pk  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30      1.1       pk  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31      1.1       pk  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32      1.1       pk  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33      1.1       pk  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34      1.1       pk  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35      1.1       pk  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36      1.1       pk  * POSSIBILITY OF SUCH DAMAGE.
     37      1.1       pk  */
     38      1.1       pk 
     39      1.1       pk #include <sys/param.h>
     40      1.1       pk #include <sys/systm.h>
     41      1.1       pk #include <sys/proc.h>
     42      1.1       pk #include <sys/errno.h>
     43      1.1       pk #include <sys/kernel.h>
     44      1.1       pk #include <sys/malloc.h>
     45      1.1       pk #include <sys/lock.h>
     46      1.1       pk #include <sys/pool.h>
     47      1.1       pk 
     48      1.3       pk #include <vm/vm.h>
     49      1.3       pk #include <vm/vm_kern.h>
     50      1.3       pk 
     51      1.3       pk #if defined(UVM)
     52      1.3       pk #include <uvm/uvm.h>
     53      1.3       pk #endif
     54      1.3       pk 
     55      1.1       pk /*
     56      1.1       pk  * Pool resource management utility.
     57      1.3       pk  *
     58      1.3       pk  * Memory is allocated in pages which are split into pieces according
     59      1.3       pk  * to the pool item size. Each page is kept on a list headed by `pr_pagelist'
     60      1.3       pk  * in the pool structure and the individual pool items are on a linked list
     61      1.3       pk  * headed by `ph_itemlist' in each page header. The memory for building
     62      1.3       pk  * the page list is either taken from the allocated pages themselves (for
     63      1.3       pk  * small pool items) or taken from an internal pool of page headers (`phpool').
     64      1.3       pk  *
     65      1.1       pk  */
     66      1.1       pk 
     67      1.3       pk /* List of all pools */
     68  1.4.2.2      eeh TAILQ_HEAD(,pool) pool_head = TAILQ_HEAD_INITIALIZER(pool_head);
     69      1.3       pk 
     70      1.3       pk /* Private pool for page header structures */
     71      1.3       pk static struct pool phpool;
     72      1.3       pk 
     73      1.3       pk /* # of seconds to retain page after last use */
     74      1.3       pk int pool_inactive_time = 10;
     75      1.3       pk 
     76      1.3       pk /* Next candidate for drainage (see pool_drain()) */
     77      1.3       pk static struct pool	*drainpp = NULL;
     78      1.3       pk 
     79      1.3       pk struct pool_item_header {
     80      1.3       pk 	/* Page headers */
     81      1.3       pk 	TAILQ_ENTRY(pool_item_header)
     82      1.3       pk 				ph_pagelist;	/* pool page list */
     83      1.3       pk 	TAILQ_HEAD(,pool_item)	ph_itemlist;	/* chunk list for this page */
     84      1.3       pk 	LIST_ENTRY(pool_item_header)
     85      1.3       pk 				ph_hashlist;	/* Off-page page headers */
     86      1.3       pk 	int			ph_nmissing;	/* # of chunks in use */
     87      1.3       pk 	caddr_t			ph_page;	/* this page's address */
     88      1.3       pk 	struct timeval		ph_time;	/* last referenced */
     89      1.3       pk };
     90      1.3       pk 
     91      1.1       pk struct pool_item {
     92      1.3       pk #ifdef DIAGNOSTIC
     93      1.3       pk 	int pi_magic;
     94      1.3       pk #define PI_MAGIC 0xdeadbeef
     95      1.3       pk #endif
     96      1.3       pk 	/* Other entries use only this list entry */
     97      1.3       pk 	TAILQ_ENTRY(pool_item)	pi_list;
     98      1.3       pk };
     99      1.3       pk 
    100      1.3       pk 
    101      1.3       pk #define PR_HASH_INDEX(pp,addr) \
    102      1.3       pk 	(((u_long)(addr) >> (pp)->pr_pageshift) & (PR_HASHTABSIZE - 1))
    103      1.3       pk 
    104      1.3       pk 
    105      1.3       pk 
    106      1.3       pk static struct pool_item_header
    107      1.3       pk 		*pr_find_pagehead __P((struct pool *, caddr_t));
    108      1.3       pk static void	pr_rmpage __P((struct pool *, struct pool_item_header *));
    109      1.3       pk static int	pool_prime_page __P((struct pool *, caddr_t));
    110      1.3       pk static void	*pool_page_alloc __P((unsigned long, int, int));
    111      1.3       pk static void	pool_page_free __P((void *, unsigned long, int));
    112      1.3       pk int pool_chk __P((struct pool *, char *));
    113      1.3       pk 
    114      1.3       pk 
    115      1.3       pk #ifdef POOL_DIAGNOSTIC
    116      1.3       pk /*
    117      1.3       pk  * Pool log entry. An array of these is allocated in pool_create().
    118      1.3       pk  */
    119      1.3       pk struct pool_log {
    120      1.3       pk 	const char	*pl_file;
    121      1.3       pk 	long		pl_line;
    122      1.3       pk 	int		pl_action;
    123      1.3       pk #define PRLOG_GET	1
    124      1.3       pk #define PRLOG_PUT	2
    125      1.3       pk 	void		*pl_addr;
    126      1.1       pk };
    127      1.1       pk 
    128      1.3       pk /* Number of entries in pool log buffers */
    129      1.3       pk int pool_logsize = 10;
    130      1.1       pk 
    131      1.3       pk static void	pr_log __P((struct pool *, void *, int, const char *, long));
    132      1.3       pk static void	pr_printlog __P((struct pool *));
    133      1.3       pk 
    134      1.3       pk static __inline__ void
    135      1.3       pk pr_log(pp, v, action, file, line)
    136      1.3       pk 	struct pool	*pp;
    137      1.3       pk 	void		*v;
    138      1.3       pk 	int		action;
    139      1.3       pk 	const char	*file;
    140      1.3       pk 	long		line;
    141      1.3       pk {
    142      1.3       pk 	int n = pp->pr_curlogentry;
    143      1.3       pk 	struct pool_log *pl;
    144      1.3       pk 
    145      1.3       pk 	if ((pp->pr_flags & PR_LOGGING) == 0)
    146      1.3       pk 		return;
    147      1.3       pk 
    148      1.3       pk 	/*
    149      1.3       pk 	 * Fill in the current entry. Wrap around and overwrite
    150      1.3       pk 	 * the oldest entry if necessary.
    151      1.3       pk 	 */
    152      1.3       pk 	pl = &pp->pr_log[n];
    153      1.3       pk 	pl->pl_file = file;
    154      1.3       pk 	pl->pl_line = line;
    155      1.3       pk 	pl->pl_action = action;
    156      1.3       pk 	pl->pl_addr = v;
    157      1.3       pk 	if (++n >= pp->pr_logsize)
    158      1.3       pk 		n = 0;
    159      1.3       pk 	pp->pr_curlogentry = n;
    160      1.3       pk }
    161      1.3       pk 
    162      1.3       pk static void
    163      1.3       pk pr_printlog(pp)
    164      1.3       pk 	struct pool *pp;
    165      1.3       pk {
    166      1.3       pk 	int i = pp->pr_logsize;
    167      1.3       pk 	int n = pp->pr_curlogentry;
    168      1.3       pk 
    169      1.3       pk 	if ((pp->pr_flags & PR_LOGGING) == 0)
    170      1.3       pk 		return;
    171      1.3       pk 
    172      1.3       pk 	pool_print(pp, "printlog");
    173      1.3       pk 
    174      1.3       pk 	/*
    175      1.3       pk 	 * Print all entries in this pool's log.
    176      1.3       pk 	 */
    177      1.3       pk 	while (i-- > 0) {
    178      1.3       pk 		struct pool_log *pl = &pp->pr_log[n];
    179      1.3       pk 		if (pl->pl_action != 0) {
    180      1.3       pk 			printf("log entry %d:\n", i);
    181      1.3       pk 			printf("\taction = %s, addr = %p\n",
    182      1.3       pk 				pl->pl_action == PRLOG_GET ? "get" : "put",
    183      1.3       pk 				pl->pl_addr);
    184      1.3       pk 			printf("\tfile: %s at line %lu\n",
    185      1.3       pk 				pl->pl_file, pl->pl_line);
    186      1.3       pk 		}
    187      1.3       pk 		if (++n >= pp->pr_logsize)
    188      1.3       pk 			n = 0;
    189      1.3       pk 	}
    190      1.3       pk }
    191      1.3       pk #else
    192      1.3       pk #define pr_log(pp, v, action, file, line)
    193      1.3       pk #define pr_printlog(pp)
    194      1.3       pk #endif
    195      1.3       pk 
    196      1.3       pk 
    197      1.3       pk /*
    198      1.3       pk  * Return the pool page header based on page address.
    199      1.3       pk  */
    200      1.3       pk static __inline__ struct pool_item_header *
    201      1.3       pk pr_find_pagehead(pp, page)
    202      1.3       pk 	struct pool *pp;
    203      1.3       pk 	caddr_t page;
    204      1.3       pk {
    205      1.3       pk 	struct pool_item_header *ph;
    206      1.3       pk 
    207      1.3       pk 	if ((pp->pr_flags & PR_PHINPAGE) != 0)
    208      1.3       pk 		return ((struct pool_item_header *)(page + pp->pr_phoffset));
    209      1.3       pk 
    210      1.3       pk 	for (ph = LIST_FIRST(&pp->pr_hashtab[PR_HASH_INDEX(pp, page)]);
    211      1.3       pk 	     ph != NULL;
    212      1.3       pk 	     ph = LIST_NEXT(ph, ph_hashlist)) {
    213      1.3       pk 		if (ph->ph_page == page)
    214      1.3       pk 			return (ph);
    215      1.3       pk 	}
    216      1.3       pk 	return (NULL);
    217      1.3       pk }
    218      1.3       pk 
    219      1.3       pk /*
    220      1.3       pk  * Remove a page from the pool.
    221      1.3       pk  */
    222      1.3       pk static __inline__ void
    223      1.3       pk pr_rmpage(pp, ph)
    224      1.3       pk 	struct pool *pp;
    225      1.3       pk 	struct pool_item_header *ph;
    226      1.3       pk {
    227      1.3       pk 
    228      1.3       pk 	/*
    229      1.3       pk 	 * Unlink a page from the pool and release it.
    230      1.3       pk 	 */
    231      1.3       pk 	TAILQ_REMOVE(&pp->pr_pagelist, ph, ph_pagelist);
    232      1.3       pk 	(*pp->pr_free)(ph->ph_page, pp->pr_pagesz, pp->pr_mtype);
    233      1.3       pk 	pp->pr_npages--;
    234      1.3       pk 	pp->pr_npagefree++;
    235      1.3       pk 
    236      1.3       pk 	if ((pp->pr_flags & PR_PHINPAGE) == 0) {
    237      1.3       pk 		LIST_REMOVE(ph, ph_hashlist);
    238      1.3       pk 		pool_put(&phpool, ph);
    239      1.3       pk 	}
    240      1.3       pk 
    241      1.3       pk 	if (pp->pr_curpage == ph) {
    242      1.3       pk 		/*
    243      1.3       pk 		 * Find a new non-empty page header, if any.
    244      1.3       pk 		 * Start search from the page head, to increase the
    245      1.3       pk 		 * chance for "high water" pages to be freed.
    246      1.3       pk 		 */
    247      1.3       pk 		for (ph = TAILQ_FIRST(&pp->pr_pagelist); ph != NULL;
    248      1.3       pk 		     ph = TAILQ_NEXT(ph, ph_pagelist))
    249      1.3       pk 			if (TAILQ_FIRST(&ph->ph_itemlist) != NULL)
    250      1.3       pk 				break;
    251      1.3       pk 
    252      1.3       pk 		pp->pr_curpage = ph;
    253      1.3       pk 	}
    254      1.3       pk }
    255      1.3       pk 
    256      1.3       pk /*
    257      1.3       pk  * Allocate and initialize a pool.
    258      1.3       pk  */
    259      1.1       pk struct pool *
    260      1.3       pk pool_create(size, align, ioff, nitems, wchan, pagesz, alloc, release, mtype)
    261      1.1       pk 	size_t	size;
    262      1.3       pk 	u_int	align;
    263      1.3       pk 	u_int	ioff;
    264      1.1       pk 	int	nitems;
    265      1.1       pk 	char	*wchan;
    266      1.3       pk 	size_t	pagesz;
    267      1.3       pk 	void	*(*alloc) __P((unsigned long, int, int));
    268      1.3       pk 	void	(*release) __P((void *, unsigned long, int));
    269      1.1       pk 	int	mtype;
    270      1.1       pk {
    271      1.1       pk 	struct pool *pp;
    272      1.3       pk 	int flags;
    273      1.1       pk 
    274      1.3       pk 	pp = (struct pool *)malloc(sizeof(*pp), M_POOL, M_NOWAIT);
    275      1.3       pk 	if (pp == NULL)
    276      1.1       pk 		return (NULL);
    277      1.3       pk 
    278      1.3       pk 	flags = PR_FREEHEADER;
    279      1.3       pk #ifdef POOL_DIAGNOSTIC
    280      1.3       pk 	if (pool_logsize != 0)
    281      1.3       pk 		flags |= PR_LOGGING;
    282      1.3       pk #endif
    283      1.3       pk 
    284      1.3       pk 	pool_init(pp, size, align, ioff, flags, wchan, pagesz,
    285      1.3       pk 		  alloc, release, mtype);
    286      1.3       pk 
    287      1.3       pk 	if (nitems != 0) {
    288      1.3       pk 		if (pool_prime(pp, nitems, NULL) != 0) {
    289      1.3       pk 			pool_destroy(pp);
    290      1.3       pk 			return (NULL);
    291      1.3       pk 		}
    292      1.1       pk 	}
    293      1.1       pk 
    294      1.3       pk 	return (pp);
    295      1.3       pk }
    296      1.3       pk 
    297      1.3       pk /*
    298      1.3       pk  * Initialize the given pool resource structure.
    299      1.3       pk  *
    300      1.3       pk  * We export this routine to allow other kernel parts to declare
    301      1.3       pk  * static pools that must be initialized before malloc() is available.
    302      1.3       pk  */
    303      1.3       pk void
    304      1.3       pk pool_init(pp, size, align, ioff, flags, wchan, pagesz, alloc, release, mtype)
    305      1.3       pk 	struct pool	*pp;
    306      1.3       pk 	size_t		size;
    307      1.3       pk 	u_int		align;
    308      1.3       pk 	u_int		ioff;
    309      1.3       pk 	int		flags;
    310      1.3       pk 	char		*wchan;
    311      1.3       pk 	size_t		pagesz;
    312      1.3       pk 	void		*(*alloc) __P((unsigned long, int, int));
    313      1.3       pk 	void		(*release) __P((void *, unsigned long, int));
    314      1.3       pk 	int		mtype;
    315      1.3       pk {
    316      1.3       pk 	int off, slack;
    317      1.3       pk 
    318      1.3       pk 	/*
    319      1.3       pk 	 * Check arguments and construct default values.
    320      1.3       pk 	 */
    321      1.3       pk 	if (!powerof2(pagesz) || pagesz > PAGE_SIZE)
    322      1.3       pk 		panic("pool_init: page size invalid (%lx)\n", (u_long)pagesz);
    323      1.3       pk 
    324      1.4  thorpej 	if (alloc == NULL && release == NULL) {
    325      1.3       pk 		alloc = pool_page_alloc;
    326      1.3       pk 		release = pool_page_free;
    327      1.4  thorpej 		pagesz = PAGE_SIZE;	/* Rounds to PAGE_SIZE anyhow. */
    328      1.4  thorpej 	} else if ((alloc != NULL && release != NULL) == 0) {
    329      1.4  thorpej 		/* If you specifiy one, must specify both. */
    330      1.4  thorpej 		panic("pool_init: must specify alloc and release together");
    331      1.4  thorpej 	}
    332      1.4  thorpej 
    333      1.3       pk 	if (pagesz == 0)
    334      1.3       pk 		pagesz = PAGE_SIZE;
    335      1.3       pk 
    336      1.3       pk 	if (align == 0)
    337      1.3       pk 		align = ALIGN(1);
    338      1.3       pk 
    339      1.3       pk 	/*
    340      1.3       pk 	 * Initialize the pool structure.
    341      1.3       pk 	 */
    342      1.3       pk 	TAILQ_INSERT_TAIL(&pool_head, pp, pr_poollist);
    343      1.3       pk 	TAILQ_INIT(&pp->pr_pagelist);
    344      1.3       pk 	pp->pr_curpage = NULL;
    345      1.3       pk 	pp->pr_npages = 0;
    346      1.3       pk 	pp->pr_minitems = 0;
    347      1.3       pk 	pp->pr_minpages = 0;
    348      1.3       pk 	pp->pr_maxpages = UINT_MAX;
    349      1.3       pk 	pp->pr_flags = flags;
    350      1.3       pk 	pp->pr_size = ALIGN(size);
    351      1.3       pk 	pp->pr_align = align;
    352      1.3       pk 	pp->pr_wchan = wchan;
    353      1.3       pk 	pp->pr_mtype = mtype;
    354      1.3       pk 	pp->pr_alloc = alloc;
    355      1.3       pk 	pp->pr_free = release;
    356      1.3       pk 	pp->pr_pagesz = pagesz;
    357      1.3       pk 	pp->pr_pagemask = ~(pagesz - 1);
    358      1.3       pk 	pp->pr_pageshift = ffs(pagesz) - 1;
    359      1.3       pk 
    360      1.3       pk 	/*
    361      1.3       pk 	 * Decide whether to put the page header off page to avoid
    362      1.3       pk 	 * wasting too large a part of the page. Off-page page headers
    363      1.3       pk 	 * go on a hash table, so we can match a returned item
    364      1.3       pk 	 * with its header based on the page address.
    365      1.3       pk 	 * We use 1/16 of the page size as the threshold (XXX: tune)
    366      1.3       pk 	 */
    367      1.3       pk 	if (pp->pr_size < pagesz/16) {
    368      1.3       pk 		/* Use the end of the page for the page header */
    369      1.3       pk 		pp->pr_flags |= PR_PHINPAGE;
    370      1.3       pk 		pp->pr_phoffset = off =
    371      1.3       pk 			pagesz - ALIGN(sizeof(struct pool_item_header));
    372      1.2       pk 	} else {
    373      1.3       pk 		/* The page header will be taken from our page header pool */
    374      1.3       pk 		pp->pr_phoffset = 0;
    375      1.3       pk 		off = pagesz;
    376      1.3       pk 		bzero(pp->pr_hashtab, sizeof(pp->pr_hashtab));
    377      1.2       pk 	}
    378      1.1       pk 
    379      1.3       pk 	/*
    380      1.3       pk 	 * Alignment is to take place at `ioff' within the item. This means
    381      1.3       pk 	 * we must reserve up to `align - 1' bytes on the page to allow
    382      1.3       pk 	 * appropriate positioning of each item.
    383      1.3       pk 	 *
    384      1.3       pk 	 * Silently enforce `0 <= ioff < align'.
    385      1.3       pk 	 */
    386      1.3       pk 	pp->pr_itemoffset = ioff = ioff % align;
    387      1.3       pk 	pp->pr_itemsperpage = (off - ((align - ioff) % align)) / pp->pr_size;
    388      1.3       pk 
    389      1.3       pk 	/*
    390      1.3       pk 	 * Use the slack between the chunks and the page header
    391      1.3       pk 	 * for "cache coloring".
    392      1.3       pk 	 */
    393      1.3       pk 	slack = off - pp->pr_itemsperpage * pp->pr_size;
    394      1.3       pk 	pp->pr_maxcolor = (slack / align) * align;
    395      1.3       pk 	pp->pr_curcolor = 0;
    396      1.3       pk 
    397      1.3       pk 	pp->pr_nget = 0;
    398      1.3       pk 	pp->pr_nfail = 0;
    399      1.3       pk 	pp->pr_nput = 0;
    400      1.3       pk 	pp->pr_npagealloc = 0;
    401      1.3       pk 	pp->pr_npagefree = 0;
    402      1.1       pk 	pp->pr_hiwat = 0;
    403      1.3       pk 
    404      1.3       pk #ifdef POOL_DIAGNOSTIC
    405      1.3       pk 	if ((flags & PR_LOGGING) != 0) {
    406      1.3       pk 		pp->pr_log = malloc(pool_logsize * sizeof(struct pool_log),
    407      1.3       pk 				    M_TEMP, M_NOWAIT);
    408      1.3       pk 		if (pp->pr_log == NULL)
    409      1.3       pk 			pp->pr_flags &= ~PR_LOGGING;
    410      1.3       pk 		pp->pr_curlogentry = 0;
    411      1.3       pk 		pp->pr_logsize = pool_logsize;
    412      1.3       pk 	}
    413      1.3       pk #endif
    414      1.3       pk 
    415      1.1       pk 	simple_lock_init(&pp->pr_lock);
    416      1.1       pk 
    417      1.3       pk 	/*
    418      1.3       pk 	 * Initialize private page header pool if we haven't done so yet.
    419      1.3       pk 	 */
    420      1.3       pk 	if (phpool.pr_size == 0) {
    421      1.3       pk 		pool_init(&phpool, sizeof(struct pool_item_header), 0, 0,
    422      1.3       pk 			  0, "phpool", 0, 0, 0, 0);
    423      1.1       pk 	}
    424      1.1       pk 
    425      1.3       pk 	return;
    426      1.1       pk }
    427      1.1       pk 
    428      1.1       pk /*
    429      1.1       pk  * De-commision a pool resource.
    430      1.1       pk  */
    431      1.1       pk void
    432      1.1       pk pool_destroy(pp)
    433      1.1       pk 	struct pool *pp;
    434      1.1       pk {
    435      1.3       pk 	struct pool_item_header *ph;
    436      1.3       pk 
    437      1.3       pk #ifdef DIAGNOSTIC
    438      1.3       pk 	if (pp->pr_nget - pp->pr_nput != 0) {
    439      1.3       pk 		pr_printlog(pp);
    440      1.3       pk 		panic("pool_destroy: pool busy: still out: %lu\n",
    441      1.3       pk 		      pp->pr_nget - pp->pr_nput);
    442      1.3       pk 	}
    443      1.3       pk #endif
    444      1.1       pk 
    445      1.3       pk 	/* Remove all pages */
    446      1.3       pk 	if ((pp->pr_flags & PR_STATIC) == 0)
    447      1.3       pk 		while ((ph = pp->pr_pagelist.tqh_first) != NULL)
    448      1.3       pk 			pr_rmpage(pp, ph);
    449      1.3       pk 
    450      1.3       pk 	/* Remove from global pool list */
    451      1.3       pk 	TAILQ_REMOVE(&pool_head, pp, pr_poollist);
    452      1.3       pk 	drainpp = NULL;
    453      1.3       pk 
    454      1.3       pk #ifdef POOL_DIAGNOSTIC
    455      1.3       pk 	if ((pp->pr_flags & PR_LOGGING) != 0)
    456      1.3       pk 		free(pp->pr_log, M_TEMP);
    457      1.3       pk #endif
    458      1.2       pk 
    459      1.3       pk 	if (pp->pr_flags & PR_FREEHEADER)
    460      1.3       pk 		free(pp, M_POOL);
    461      1.1       pk }
    462      1.1       pk 
    463      1.1       pk 
    464      1.1       pk /*
    465      1.3       pk  * Grab an item from the pool; must be called at appropriate spl level
    466      1.1       pk  */
    467      1.3       pk #ifdef POOL_DIAGNOSTIC
    468      1.3       pk void *
    469      1.3       pk _pool_get(pp, flags, file, line)
    470      1.3       pk 	struct pool *pp;
    471      1.3       pk 	int flags;
    472      1.3       pk 	const char *file;
    473      1.3       pk 	long line;
    474      1.3       pk #else
    475      1.1       pk void *
    476      1.1       pk pool_get(pp, flags)
    477      1.1       pk 	struct pool *pp;
    478      1.1       pk 	int flags;
    479      1.3       pk #endif
    480      1.1       pk {
    481      1.1       pk 	void *v;
    482      1.1       pk 	struct pool_item *pi;
    483      1.3       pk 	struct pool_item_header *ph;
    484      1.1       pk 
    485      1.2       pk #ifdef DIAGNOSTIC
    486      1.3       pk 	if ((pp->pr_flags & PR_STATIC) && (flags & PR_MALLOCOK)) {
    487      1.3       pk 		pr_printlog(pp);
    488      1.2       pk 		panic("pool_get: static");
    489      1.3       pk 	}
    490      1.2       pk #endif
    491      1.2       pk 
    492      1.1       pk 	simple_lock(&pp->pr_lock);
    493      1.3       pk 	if (curproc == NULL && (flags & PR_WAITOK) != 0)
    494      1.3       pk 		panic("pool_get: must have NOWAIT");
    495      1.1       pk 
    496      1.3       pk 	/*
    497      1.3       pk 	 * The convention we use is that if `curpage' is not NULL, then
    498      1.3       pk 	 * it points at a non-empty bucket. In particular, `curpage'
    499      1.3       pk 	 * never points at a page header which has PR_PHINPAGE set and
    500      1.3       pk 	 * has no items in its bucket.
    501      1.3       pk 	 */
    502      1.3       pk again:
    503      1.3       pk 	if ((ph = pp->pr_curpage) == NULL) {
    504      1.3       pk 		void *v = (*pp->pr_alloc)(pp->pr_pagesz, flags, pp->pr_mtype);
    505      1.1       pk 		if (v == NULL) {
    506      1.3       pk 			if (flags & PR_URGENT)
    507      1.3       pk 				panic("pool_get: urgent");
    508      1.3       pk 			if ((flags & PR_WAITOK) == 0) {
    509      1.3       pk 				pp->pr_nfail++;
    510      1.3       pk 				simple_unlock(&pp->pr_lock);
    511      1.1       pk 				return (NULL);
    512      1.3       pk 			}
    513      1.3       pk 
    514      1.1       pk 			pp->pr_flags |= PR_WANTED;
    515      1.1       pk 			simple_unlock(&pp->pr_lock);
    516      1.1       pk 			tsleep((caddr_t)pp, PSWP, pp->pr_wchan, 0);
    517      1.3       pk 			simple_lock(&pp->pr_lock);
    518      1.3       pk 		} else {
    519      1.3       pk 			pp->pr_npagealloc++;
    520      1.3       pk 			pool_prime_page(pp, v);
    521      1.1       pk 		}
    522      1.3       pk 
    523      1.3       pk 		goto again;
    524      1.3       pk 	}
    525      1.3       pk 
    526      1.3       pk 	if ((v = pi = TAILQ_FIRST(&ph->ph_itemlist)) == NULL)
    527      1.3       pk 		panic("pool_get: %s: page empty", pp->pr_wchan);
    528      1.3       pk 
    529      1.3       pk 	pr_log(pp, v, PRLOG_GET, file, line);
    530      1.3       pk 
    531      1.3       pk #ifdef DIAGNOSTIC
    532      1.3       pk 	if (pi->pi_magic != PI_MAGIC) {
    533      1.3       pk 		pr_printlog(pp);
    534      1.3       pk 		panic("pool_get(%s): free list modified: magic=%x; page %p;"
    535      1.3       pk 		       " item addr %p\n",
    536      1.3       pk 			pp->pr_wchan, pi->pi_magic, ph->ph_page, pi);
    537      1.3       pk 	}
    538      1.3       pk #endif
    539      1.3       pk 
    540      1.3       pk 	/*
    541      1.3       pk 	 * Remove from item list.
    542      1.3       pk 	 */
    543      1.3       pk 	TAILQ_REMOVE(&ph->ph_itemlist, pi, pi_list);
    544      1.3       pk 	ph->ph_nmissing++;
    545      1.3       pk 	if (TAILQ_FIRST(&ph->ph_itemlist) == NULL) {
    546      1.3       pk 		/*
    547      1.3       pk 		 * Find a new non-empty page header, if any.
    548      1.3       pk 		 * Start search from the page head, to increase
    549      1.3       pk 		 * the chance for "high water" pages to be freed.
    550      1.3       pk 		 *
    551      1.3       pk 		 * First, move the now empty page to the head of
    552      1.3       pk 		 * the page list.
    553      1.3       pk 		 */
    554      1.3       pk 		TAILQ_REMOVE(&pp->pr_pagelist, ph, ph_pagelist);
    555      1.3       pk 		TAILQ_INSERT_HEAD(&pp->pr_pagelist, ph, ph_pagelist);
    556      1.3       pk 		while ((ph = TAILQ_NEXT(ph, ph_pagelist)) != NULL)
    557      1.3       pk 			if (TAILQ_FIRST(&ph->ph_itemlist) != NULL)
    558      1.3       pk 				break;
    559      1.3       pk 
    560      1.3       pk 		pp->pr_curpage = ph;
    561      1.1       pk 	}
    562      1.3       pk 
    563      1.3       pk 	pp->pr_nget++;
    564      1.1       pk 	simple_unlock(&pp->pr_lock);
    565      1.1       pk 	return (v);
    566      1.1       pk }
    567      1.1       pk 
    568      1.1       pk /*
    569      1.3       pk  * Return resource to the pool; must be called at appropriate spl level
    570      1.1       pk  */
    571      1.3       pk #ifdef POOL_DIAGNOSTIC
    572      1.3       pk void
    573      1.3       pk _pool_put(pp, v, file, line)
    574      1.3       pk 	struct pool *pp;
    575      1.3       pk 	void *v;
    576      1.3       pk 	const char *file;
    577      1.3       pk 	long line;
    578      1.3       pk #else
    579      1.1       pk void
    580      1.1       pk pool_put(pp, v)
    581      1.1       pk 	struct pool *pp;
    582      1.1       pk 	void *v;
    583      1.3       pk #endif
    584      1.1       pk {
    585      1.1       pk 	struct pool_item *pi = v;
    586      1.3       pk 	struct pool_item_header *ph;
    587      1.3       pk 	caddr_t page;
    588      1.3       pk 
    589      1.3       pk 	page = (caddr_t)((u_long)v & pp->pr_pagemask);
    590      1.1       pk 
    591      1.1       pk 	simple_lock(&pp->pr_lock);
    592      1.3       pk 
    593      1.3       pk 	pr_log(pp, v, PRLOG_PUT, file, line);
    594      1.3       pk 
    595      1.3       pk 	if ((ph = pr_find_pagehead(pp, page)) == NULL) {
    596      1.3       pk 		pr_printlog(pp);
    597      1.3       pk 		panic("pool_put: %s: page header missing", pp->pr_wchan);
    598      1.3       pk 	}
    599      1.3       pk 
    600      1.3       pk 	/*
    601      1.3       pk 	 * Return to item list.
    602      1.3       pk 	 */
    603      1.2       pk #ifdef DIAGNOSTIC
    604      1.3       pk 	pi->pi_magic = PI_MAGIC;
    605      1.3       pk #endif
    606      1.3       pk 	TAILQ_INSERT_HEAD(&ph->ph_itemlist, pi, pi_list);
    607      1.3       pk 	ph->ph_nmissing--;
    608      1.3       pk 	pp->pr_nput++;
    609      1.3       pk 
    610      1.3       pk 	/* Cancel "pool empty" condition if it exists */
    611      1.3       pk 	if (pp->pr_curpage == NULL)
    612      1.3       pk 		pp->pr_curpage = ph;
    613      1.3       pk 
    614      1.3       pk 	if (pp->pr_flags & PR_WANTED) {
    615      1.3       pk 		pp->pr_flags &= ~PR_WANTED;
    616      1.3       pk 		wakeup((caddr_t)pp);
    617      1.3       pk 		simple_unlock(&pp->pr_lock);
    618      1.3       pk 		return;
    619      1.3       pk 	}
    620      1.3       pk 
    621      1.3       pk 	/*
    622      1.3       pk 	 * If this page is now complete, move it to the end of the pagelist.
    623      1.3       pk 	 * If this page has just become un-empty, move it the head.
    624      1.3       pk 	 */
    625      1.3       pk 	if (ph->ph_nmissing == 0) {
    626      1.3       pk 		if (pp->pr_npages > pp->pr_maxpages) {
    627      1.3       pk #if 0
    628      1.3       pk 			timeout(pool_drain, 0, pool_inactive_time*hz);
    629      1.3       pk #else
    630      1.3       pk 			pr_rmpage(pp, ph);
    631      1.2       pk #endif
    632      1.3       pk 		} else {
    633      1.3       pk 			TAILQ_REMOVE(&pp->pr_pagelist, ph, ph_pagelist);
    634      1.3       pk 			TAILQ_INSERT_TAIL(&pp->pr_pagelist, ph, ph_pagelist);
    635      1.3       pk 			ph->ph_time = time;
    636      1.3       pk 
    637      1.3       pk 			/* XXX - update curpage */
    638      1.3       pk 			for (ph = TAILQ_FIRST(&pp->pr_pagelist); ph != NULL;
    639      1.3       pk 			     ph = TAILQ_NEXT(ph, ph_pagelist))
    640      1.3       pk 				if (TAILQ_FIRST(&ph->ph_itemlist) != NULL)
    641      1.3       pk 					break;
    642      1.1       pk 
    643      1.3       pk 			pp->pr_curpage = ph;
    644      1.1       pk 		}
    645      1.1       pk 	}
    646      1.3       pk 
    647      1.1       pk 	simple_unlock(&pp->pr_lock);
    648      1.1       pk }
    649      1.1       pk 
    650      1.1       pk /*
    651      1.3       pk  * Add N items to the pool.
    652      1.1       pk  */
    653      1.1       pk int
    654      1.2       pk pool_prime(pp, n, storage)
    655      1.1       pk 	struct pool *pp;
    656      1.1       pk 	int n;
    657      1.2       pk 	caddr_t storage;
    658      1.1       pk {
    659      1.3       pk 	caddr_t cp;
    660      1.3       pk 	int newnitems, newpages;
    661      1.2       pk 
    662      1.2       pk #ifdef DIAGNOSTIC
    663      1.2       pk 	if (storage && !(pp->pr_flags & PR_STATIC))
    664      1.2       pk 		panic("pool_prime: static");
    665      1.2       pk 	/* !storage && static caught below */
    666      1.2       pk #endif
    667      1.1       pk 
    668      1.3       pk 	newnitems = pp->pr_minitems + n;
    669      1.3       pk 	newpages =
    670      1.3       pk 		roundup(pp->pr_itemsperpage,newnitems) / pp->pr_itemsperpage
    671      1.3       pk 		- pp->pr_minpages;
    672      1.3       pk 
    673      1.1       pk 	simple_lock(&pp->pr_lock);
    674      1.3       pk 	while (newpages-- > 0) {
    675      1.3       pk 
    676      1.2       pk 		if (pp->pr_flags & PR_STATIC) {
    677      1.3       pk 			cp = storage;
    678      1.3       pk 			storage += pp->pr_pagesz;
    679      1.3       pk 		} else {
    680      1.3       pk 			cp = (*pp->pr_alloc)(pp->pr_pagesz, 0, pp->pr_mtype);
    681      1.3       pk 		}
    682      1.2       pk 
    683      1.3       pk 		if (cp == NULL) {
    684      1.1       pk 			simple_unlock(&pp->pr_lock);
    685      1.1       pk 			return (ENOMEM);
    686      1.1       pk 		}
    687      1.1       pk 
    688      1.3       pk 		pool_prime_page(pp, cp);
    689      1.3       pk 		pp->pr_minpages++;
    690      1.1       pk 	}
    691      1.3       pk 
    692      1.3       pk 	pp->pr_minitems = newnitems;
    693      1.3       pk 
    694      1.3       pk 	if (pp->pr_minpages >= pp->pr_maxpages)
    695      1.3       pk 		pp->pr_maxpages = pp->pr_minpages + 1;	/* XXX */
    696      1.3       pk 
    697      1.1       pk 	simple_unlock(&pp->pr_lock);
    698      1.1       pk 	return (0);
    699      1.1       pk }
    700      1.3       pk 
    701      1.3       pk /*
    702      1.3       pk  * Add a page worth of items to the pool.
    703      1.3       pk  */
    704      1.3       pk int
    705      1.3       pk pool_prime_page(pp, storage)
    706      1.3       pk 	struct pool *pp;
    707      1.3       pk 	caddr_t storage;
    708      1.3       pk {
    709      1.3       pk 	struct pool_item *pi;
    710      1.3       pk 	struct pool_item_header *ph;
    711      1.3       pk 	caddr_t cp = storage;
    712      1.3       pk 	unsigned int align = pp->pr_align;
    713      1.3       pk 	unsigned int ioff = pp->pr_itemoffset;
    714      1.3       pk 	int n;
    715      1.3       pk 
    716      1.3       pk 	if ((pp->pr_flags & PR_PHINPAGE) != 0) {
    717      1.3       pk 		ph = (struct pool_item_header *)(cp + pp->pr_phoffset);
    718      1.3       pk 	} else {
    719      1.3       pk 		ph = pool_get(&phpool, PR_URGENT);
    720      1.3       pk 		LIST_INSERT_HEAD(&pp->pr_hashtab[PR_HASH_INDEX(pp, cp)],
    721      1.3       pk 				 ph, ph_hashlist);
    722      1.3       pk 	}
    723      1.3       pk 
    724      1.3       pk 	/*
    725      1.3       pk 	 * Insert page header.
    726      1.3       pk 	 */
    727      1.3       pk 	TAILQ_INSERT_HEAD(&pp->pr_pagelist, ph, ph_pagelist);
    728      1.3       pk 	TAILQ_INIT(&ph->ph_itemlist);
    729      1.3       pk 	ph->ph_page = storage;
    730      1.3       pk 	ph->ph_nmissing = 0;
    731      1.3       pk 	ph->ph_time.tv_sec = ph->ph_time.tv_usec = 0;
    732      1.3       pk 
    733      1.3       pk 	/*
    734      1.3       pk 	 * Color this page.
    735      1.3       pk 	 */
    736      1.3       pk 	cp = (caddr_t)(cp + pp->pr_curcolor);
    737      1.3       pk 	if ((pp->pr_curcolor += align) > pp->pr_maxcolor)
    738      1.3       pk 		pp->pr_curcolor = 0;
    739      1.3       pk 
    740      1.3       pk 	/*
    741      1.3       pk 	 * Adjust storage to apply aligment to `pr_itemoffset' in each item.
    742      1.3       pk 	 */
    743      1.3       pk 	if (ioff != 0)
    744      1.3       pk 		cp = (caddr_t)(cp + (align - ioff));
    745      1.3       pk 
    746      1.3       pk 	/*
    747      1.3       pk 	 * Insert remaining chunks on the bucket list.
    748      1.3       pk 	 */
    749      1.3       pk 	n = pp->pr_itemsperpage;
    750      1.3       pk 
    751      1.3       pk 	while (n--) {
    752      1.3       pk 		pi = (struct pool_item *)cp;
    753      1.3       pk 
    754      1.3       pk 		/* Insert on page list */
    755      1.3       pk 		TAILQ_INSERT_TAIL(&ph->ph_itemlist, pi, pi_list);
    756      1.3       pk #ifdef DIAGNOSTIC
    757      1.3       pk 		pi->pi_magic = PI_MAGIC;
    758      1.3       pk #endif
    759      1.3       pk 		cp = (caddr_t)(cp + pp->pr_size);
    760      1.3       pk 	}
    761      1.3       pk 
    762      1.3       pk 	/*
    763      1.3       pk 	 * If the pool was depleted, point at the new page.
    764      1.3       pk 	 */
    765      1.3       pk 	if (pp->pr_curpage == NULL)
    766      1.3       pk 		pp->pr_curpage = ph;
    767      1.3       pk 
    768      1.3       pk 	if (++pp->pr_npages > pp->pr_hiwat)
    769      1.3       pk 		pp->pr_hiwat = pp->pr_npages;
    770      1.3       pk 
    771      1.3       pk 	return (0);
    772      1.3       pk }
    773      1.3       pk 
    774      1.3       pk void
    775      1.3       pk pool_setlowat(pp, n)
    776      1.3       pk 	pool_handle_t	pp;
    777      1.3       pk 	int n;
    778      1.3       pk {
    779      1.3       pk 	pp->pr_minitems = n;
    780      1.3       pk 	if (n == 0) {
    781      1.3       pk 		pp->pr_minpages = 0;
    782      1.3       pk 		return;
    783      1.3       pk 	}
    784      1.3       pk 	pp->pr_minpages =
    785      1.3       pk 		roundup(pp->pr_itemsperpage,n) / pp->pr_itemsperpage;
    786      1.3       pk }
    787      1.3       pk 
    788      1.3       pk void
    789      1.3       pk pool_sethiwat(pp, n)
    790      1.3       pk 	pool_handle_t	pp;
    791      1.3       pk 	int n;
    792      1.3       pk {
    793      1.3       pk 	if (n == 0) {
    794      1.3       pk 		pp->pr_maxpages = 0;
    795      1.3       pk 		return;
    796      1.3       pk 	}
    797      1.3       pk 	pp->pr_maxpages =
    798      1.3       pk 		roundup(pp->pr_itemsperpage,n) / pp->pr_itemsperpage;
    799      1.3       pk }
    800      1.3       pk 
    801      1.3       pk 
    802      1.3       pk /*
    803      1.3       pk  * Default page allocator.
    804      1.3       pk  */
    805      1.3       pk static void *
    806      1.3       pk pool_page_alloc(sz, flags, mtype)
    807      1.3       pk 	unsigned long sz;
    808      1.3       pk 	int flags;
    809      1.3       pk 	int mtype;
    810      1.3       pk {
    811      1.3       pk 
    812      1.3       pk #if defined(UVM)
    813      1.4  thorpej 	return ((void *)uvm_km_alloc_poolpage());
    814      1.4  thorpej #else
    815      1.4  thorpej 	return ((void *)kmem_alloc_poolpage());
    816      1.4  thorpej #endif
    817      1.3       pk }
    818      1.3       pk 
    819      1.3       pk static void
    820      1.3       pk pool_page_free(v, sz, mtype)
    821      1.3       pk 	void *v;
    822      1.3       pk 	unsigned long sz;
    823      1.3       pk 	int mtype;
    824      1.3       pk {
    825      1.3       pk 
    826      1.3       pk #if defined(UVM)
    827  1.4.2.1      eeh 	uvm_km_free_poolpage((vaddr_t)v);
    828      1.3       pk #else
    829  1.4.2.1      eeh 	kmem_free_poolpage((vaddr_t)v);
    830      1.3       pk #endif
    831      1.3       pk }
    832      1.3       pk 
    833      1.3       pk /*
    834      1.3       pk  * Release all complete pages that have not been used recently.
    835      1.3       pk  */
    836      1.3       pk void
    837      1.3       pk pool_reclaim (pp)
    838      1.3       pk 	pool_handle_t pp;
    839      1.3       pk {
    840      1.3       pk 	struct pool_item_header *ph, *phnext;
    841      1.3       pk 	struct timeval curtime = time;
    842      1.3       pk 
    843      1.3       pk 	if (pp->pr_flags & PR_STATIC)
    844      1.3       pk 		return;
    845      1.3       pk 
    846      1.3       pk 	if (simple_lock_try(&pp->pr_lock) == 0)
    847      1.3       pk 		return;
    848      1.3       pk 
    849      1.3       pk 	for (ph = TAILQ_FIRST(&pp->pr_pagelist); ph != NULL; ph = phnext) {
    850      1.3       pk 		phnext = TAILQ_NEXT(ph, ph_pagelist);
    851      1.3       pk 
    852      1.3       pk 		/* Check our minimum page claim */
    853      1.3       pk 		if (pp->pr_npages <= pp->pr_minpages)
    854      1.3       pk 			break;
    855      1.3       pk 
    856      1.3       pk 		if (ph->ph_nmissing == 0) {
    857      1.3       pk 			struct timeval diff;
    858      1.3       pk 			timersub(&curtime, &ph->ph_time, &diff);
    859      1.3       pk 			if (diff.tv_sec < pool_inactive_time)
    860      1.3       pk 				continue;
    861      1.3       pk 			pr_rmpage(pp, ph);
    862      1.3       pk 		}
    863      1.3       pk 	}
    864      1.3       pk 
    865      1.3       pk 	simple_unlock(&pp->pr_lock);
    866      1.3       pk }
    867      1.3       pk 
    868      1.3       pk 
    869      1.3       pk /*
    870      1.3       pk  * Drain pools, one at a time.
    871      1.3       pk  */
    872      1.3       pk void
    873      1.3       pk pool_drain(arg)
    874      1.3       pk 	void *arg;
    875      1.3       pk {
    876      1.3       pk 	struct pool *pp;
    877      1.3       pk 	int s = splimp();
    878      1.3       pk 
    879      1.3       pk 	/* XXX:lock pool head */
    880      1.3       pk 	if (drainpp == NULL && (drainpp = TAILQ_FIRST(&pool_head)) == NULL) {
    881      1.3       pk 		splx(s);
    882      1.3       pk 		return;
    883      1.3       pk 	}
    884      1.3       pk 
    885      1.3       pk 	pp = drainpp;
    886      1.3       pk 	drainpp = TAILQ_NEXT(pp, pr_poollist);
    887      1.3       pk 	/* XXX:unlock pool head */
    888      1.3       pk 
    889      1.3       pk 	pool_reclaim(pp);
    890      1.3       pk 	splx(s);
    891      1.3       pk }
    892      1.3       pk 
    893      1.3       pk 
    894      1.3       pk #ifdef DEBUG
    895      1.3       pk /*
    896      1.3       pk  * Diagnostic helpers.
    897      1.3       pk  */
    898      1.3       pk void
    899      1.3       pk pool_print(pp, label)
    900      1.3       pk 	struct pool *pp;
    901      1.3       pk 	char *label;
    902      1.3       pk {
    903      1.3       pk 
    904      1.3       pk 	if (label != NULL)
    905      1.3       pk 		printf("%s: ", label);
    906      1.3       pk 
    907      1.3       pk 	printf("pool %s: nalloc %lu nfree %lu npagealloc %lu npagefree %lu\n"
    908      1.3       pk 	       "         npages %u minitems %u itemsperpage %u itemoffset %u\n",
    909      1.3       pk 		pp->pr_wchan,
    910      1.3       pk 		pp->pr_nget,
    911      1.3       pk 		pp->pr_nput,
    912      1.3       pk 		pp->pr_npagealloc,
    913      1.3       pk 		pp->pr_npagefree,
    914      1.3       pk 		pp->pr_npages,
    915      1.3       pk 		pp->pr_minitems,
    916      1.3       pk 		pp->pr_itemsperpage,
    917      1.3       pk 		pp->pr_itemoffset);
    918      1.3       pk }
    919      1.3       pk 
    920      1.3       pk int
    921      1.3       pk pool_chk(pp, label)
    922      1.3       pk 	struct pool *pp;
    923      1.3       pk 	char *label;
    924      1.3       pk {
    925      1.3       pk 	struct pool_item_header *ph;
    926      1.3       pk 	int r = 0;
    927      1.3       pk 
    928      1.3       pk 	simple_lock(&pp->pr_lock);
    929      1.3       pk 
    930      1.3       pk 	for (ph = TAILQ_FIRST(&pp->pr_pagelist); ph != NULL;
    931      1.3       pk 	     ph = TAILQ_NEXT(ph, ph_pagelist)) {
    932      1.3       pk 
    933      1.3       pk 		struct pool_item *pi;
    934      1.3       pk 		int n;
    935      1.3       pk 		caddr_t page;
    936      1.3       pk 
    937      1.3       pk 		page = (caddr_t)((u_long)ph & pp->pr_pagemask);
    938      1.3       pk 		if (page != ph->ph_page) {
    939      1.3       pk 			if (label != NULL)
    940      1.3       pk 				printf("%s: ", label);
    941      1.3       pk 			printf("pool(%s): page inconsistency: page %p;"
    942      1.3       pk 			       " at page head addr %p (p %p)\n",
    943      1.3       pk 				pp->pr_wchan, ph->ph_page,
    944      1.3       pk 				ph, page);
    945      1.3       pk 			r++;
    946      1.3       pk 			goto out;
    947      1.3       pk 		}
    948      1.3       pk 
    949      1.3       pk 		for (pi = TAILQ_FIRST(&ph->ph_itemlist), n = 0;
    950      1.3       pk 		     pi != NULL;
    951      1.3       pk 		     pi = TAILQ_NEXT(pi,pi_list), n++) {
    952      1.3       pk 
    953      1.3       pk #ifdef DIAGNOSTIC
    954      1.3       pk 			if (pi->pi_magic != PI_MAGIC) {
    955      1.3       pk 				if (label != NULL)
    956      1.3       pk 					printf("%s: ", label);
    957      1.3       pk 				printf("pool(%s): free list modified: magic=%x;"
    958      1.3       pk 				       " page %p; item ordinal %d;"
    959      1.3       pk 				       " addr %p (p %p)\n",
    960      1.3       pk 					pp->pr_wchan, pi->pi_magic, ph->ph_page,
    961      1.3       pk 					n, pi, page);
    962      1.3       pk 				panic("pool");
    963      1.3       pk 			}
    964      1.3       pk #endif
    965      1.3       pk 			page = (caddr_t)((u_long)pi & pp->pr_pagemask);
    966      1.3       pk 			if (page == ph->ph_page)
    967      1.3       pk 				continue;
    968      1.3       pk 
    969      1.3       pk 			if (label != NULL)
    970      1.3       pk 				printf("%s: ", label);
    971      1.3       pk 			printf("pool(%s): page inconsistency: page %p;"
    972      1.3       pk 			       " item ordinal %d; addr %p (p %p)\n",
    973      1.3       pk 				pp->pr_wchan, ph->ph_page,
    974      1.3       pk 				n, pi, page);
    975      1.3       pk 			r++;
    976      1.3       pk 			goto out;
    977      1.3       pk 		}
    978      1.3       pk 	}
    979      1.3       pk out:
    980      1.3       pk 	simple_unlock(&pp->pr_lock);
    981      1.3       pk 	return (r);
    982      1.3       pk }
    983      1.3       pk #endif
    984