Home | History | Annotate | Line # | Download | only in kern
subr_pool.c revision 1.1
      1 /*	$NetBSD: subr_pool.c,v 1.1 1997/12/15 11:14:57 pk 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 /*
     49  * Pool resource management utility.
     50  */
     51 
     52 struct pool_item {
     53 	struct pool_item	*pi_next;
     54 };
     55 
     56 
     57 struct pool *
     58 pool_create(size, nitems, wchan, mtype)
     59 	size_t	size;
     60 	int	nitems;
     61 	char	*wchan;
     62 	int	mtype;
     63 {
     64 	struct pool *pp;
     65 
     66 	if (size < sizeof(struct pool_item)) {
     67 		printf("pool_create: size %lu too small\n", (u_long)size);
     68 		return (NULL);
     69 	}
     70 
     71 	pp = (struct pool *)malloc(sizeof(*pp), mtype, M_NOWAIT);
     72 	if (pp == NULL)
     73 		return (NULL);
     74 
     75 	pp->pr_freelist = NULL;
     76 	pp->pr_freecount = 0;
     77 	pp->pr_hiwat = 0;
     78 	pp->pr_flags = 0;
     79 	pp->pr_size = size;
     80 	pp->pr_wchan = wchan;
     81 	pp->pr_mtype = mtype;
     82 	simple_lock_init(&pp->pr_lock);
     83 
     84 	if (nitems != 0) {
     85 		if (pool_prime(pp, nitems) != 0)
     86 			pool_destroy(pp);
     87 		return (NULL);
     88 	}
     89 
     90 	return (pp);
     91 }
     92 
     93 /*
     94  * De-commision a pool resource.
     95  */
     96 void
     97 pool_destroy(pp)
     98 	struct pool *pp;
     99 {
    100 	struct pool_item *pi;
    101 
    102 	while ((pi = pp->pr_freelist) != NULL) {
    103 		pp->pr_freelist = pi->pi_next;
    104 		free(pi, pp->pr_mtype);
    105 	}
    106 	free(pp, pp->pr_mtype);
    107 }
    108 
    109 
    110 /*
    111  * Grab an item from the pool; must be called at splbio
    112  */
    113 void *
    114 pool_get(pp, flags)
    115 	struct pool *pp;
    116 	int flags;
    117 {
    118 	void *v;
    119 	struct pool_item *pi;
    120 
    121 again:
    122 	simple_lock(&pp->pr_lock);
    123 	if ((v = pp->pr_freelist) == NULL) {
    124 		if (flags & PR_MALLOCOK)
    125 			v = (void *)malloc(pp->pr_size, pp->pr_mtype, M_NOWAIT);
    126 
    127 		if (v == NULL) {
    128 			if ((flags & PR_WAITOK) == 0)
    129 				return (NULL);
    130 			pp->pr_flags |= PR_WANTED;
    131 			simple_unlock(&pp->pr_lock);
    132 			tsleep((caddr_t)pp, PSWP, pp->pr_wchan, 0);
    133 			goto again;
    134 		}
    135 	} else {
    136 		pi = v;
    137 		pp->pr_freelist = pi->pi_next;
    138 		pp->pr_freecount--;
    139 	}
    140 	simple_unlock(&pp->pr_lock);
    141 	return (v);
    142 }
    143 
    144 /*
    145  * Return resource to the pool; must be called at splbio
    146  */
    147 void
    148 pool_put(pp, v)
    149 	struct pool *pp;
    150 	void *v;
    151 {
    152 	struct pool_item *pi = v;
    153 
    154 	simple_lock(&pp->pr_lock);
    155 	if ((pp->pr_flags & PR_WANTED) || pp->pr_freecount < pp->pr_hiwat) {
    156 		/* Return to pool */
    157 		pi->pi_next = pp->pr_freelist;
    158 		pp->pr_freelist = pi;
    159 		pp->pr_freecount++;
    160 		if (pp->pr_flags & PR_WANTED) {
    161 			pp->pr_flags &= ~PR_WANTED;
    162 			wakeup((caddr_t)pp);
    163 		}
    164 	} else {
    165 		/* Return to system */
    166 		free(v, M_DEVBUF);
    167 
    168 		/*
    169 		 * Return any excess items allocated during periods of
    170 		 * contention.
    171 		 */
    172 		while (pp->pr_freecount > pp->pr_hiwat) {
    173 			pi = pp->pr_freelist;
    174 			pp->pr_freelist = pi->pi_next;
    175 			pp->pr_freecount--;
    176 			free(pi, M_DEVBUF);
    177 		}
    178 	}
    179 	simple_unlock(&pp->pr_lock);
    180 }
    181 
    182 /*
    183  * Add N items to the pool
    184  */
    185 int
    186 pool_prime(pp, n)
    187 	struct pool *pp;
    188 	int n;
    189 {
    190 	struct pool_item *pi;
    191 
    192 	simple_lock(&pp->pr_lock);
    193 	pp->pr_hiwat += n;
    194 	while (n--) {
    195 		pi = malloc(pp->pr_size, pp->pr_mtype, M_NOWAIT);
    196 		if (pi == NULL) {
    197 			simple_unlock(&pp->pr_lock);
    198 			return (ENOMEM);
    199 		}
    200 
    201 		pi->pi_next = pp->pr_freelist;
    202 		pp->pr_freelist = pi;
    203 		pp->pr_freecount++;
    204 	}
    205 	simple_unlock(&pp->pr_lock);
    206 	return (0);
    207 }
    208