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