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