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