dmr's nami
[unix-history] / usr / src / sys / kern / uipc_mbuf.c
CommitLineData
82bff71e 1/* uipc_mbuf.c 1.29 82/02/08 */
d80cae33
BJ
2
3#include "../h/param.h"
4#include "../h/dir.h"
5#include "../h/user.h"
6#include "../h/proc.h"
7#include "../h/pte.h"
8#include "../h/cmap.h"
9#include "../h/map.h"
e6dd2097 10#include "../h/mbuf.h"
0ef33f87 11#include "../net/in_systm.h" /* XXX */
d80cae33
BJ
12#include "../h/vm.h"
13
7c733634
BJ
14mbinit()
15{
7c733634
BJ
16
17COUNT(MBINIT);
18 if (m_reserve(32) == 0)
19 goto bad;
20 if (m_clalloc(4, MPG_MBUFS) == 0)
21 goto bad;
22 if (m_clalloc(32, MPG_CLUSTERS) == 0)
23 goto bad;
24 return;
25bad:
26 panic("mbinit");
27}
28
29caddr_t
30m_clalloc(ncl, how)
31 register int ncl;
32 int how;
33{
34 int npg, mbx;
35 register struct mbuf *m;
36 register int i;
37 int s;
38
39COUNT(M_CLALLOC);
40 npg = ncl * CLSIZE;
f3156a73 41 s = splimp(); /* careful: rmalloc isn't reentrant */
7c733634 42 mbx = rmalloc(mbmap, npg);
f3156a73 43 splx(s);
7c733634
BJ
44 if (mbx == 0)
45 return (0);
46 m = cltom(mbx / CLSIZE);
47 if (memall(&Mbmap[mbx], ncl * CLSIZE, proc, CSYS) == 0)
48 return (0);
49 vmaccess(&Mbmap[mbx], (caddr_t)m, npg);
7c733634
BJ
50 switch (how) {
51
52 case MPG_CLUSTERS:
53 s = splimp();
54 for (i = 0; i < ncl; i++) {
55 m->m_off = 0;
56 m->m_next = mclfree;
57 mclfree = m;
58 m += CLBYTES / sizeof (*m);
59 nmclfree++;
60 }
61 mbstat.m_clusters += ncl;
62 splx(s);
63 break;
64
65 case MPG_MBUFS:
66 for (i = ncl * CLBYTES / sizeof (*m); i > 0; i--) {
67 m->m_off = 0;
1d395c5a 68 m->m_free = 0;
7c733634
BJ
69 (void) m_free(m);
70 m++;
71 }
72 mbstat.m_clusters += ncl;
d2109fac 73 break;
7c733634
BJ
74 }
75 return ((caddr_t)m);
76}
77
78m_pgfree(addr, n)
79 caddr_t addr;
80 int n;
81{
82
83COUNT(M_PGFREE);
7c733634
BJ
84}
85
86m_expand()
87{
88
89COUNT(M_EXPAND);
90 if (mbstat.m_bufs >= mbstat.m_hiwat)
91 return (0);
92 if (m_clalloc(1, MPG_MBUFS) == 0)
93 goto steal;
94 return (1);
95steal:
96 /* should ask protocols to free code */
97 return (0);
98}
99
100/* NEED SOME WAY TO RELEASE SPACE */
101
102/*
103 * Space reservation routines
104 */
196d84fd
BJ
105m_reserve(mbufs)
106 int mbufs;
e1506033
BJ
107{
108
5b3fa994 109 if (mbstat.m_lowat + (mbufs>>1) > (NMBCLUSTERS-32) * CLBYTES)
e1506033 110 return (0);
eb1bc170
BJ
111 mbstat.m_hiwat += mbufs;
112 mbstat.m_lowat = mbstat.m_hiwat >> 1;
ae921915 113 return (1);
e1506033
BJ
114}
115
196d84fd
BJ
116m_release(mbufs)
117 int mbufs;
e1506033
BJ
118{
119
eb1bc170
BJ
120 mbstat.m_hiwat -= mbufs;
121 mbstat.m_lowat = mbstat.m_hiwat >> 1;
e1506033
BJ
122}
123
7c733634
BJ
124/*
125 * Space allocation routines.
126 * These are also available as macros
127 * for critical paths.
128 */
d80cae33
BJ
129struct mbuf *
130m_get(canwait)
131 int canwait;
132{
133 register struct mbuf *m;
134
135COUNT(M_GET);
136 MGET(m, canwait);
137 return (m);
138}
139
cc15ab5d
BJ
140struct mbuf *
141m_getclr(canwait)
142 int canwait;
143{
144 register struct mbuf *m;
145
146COUNT(M_GETCLR);
ae921915 147 m = m_get(canwait);
cc15ab5d
BJ
148 if (m == 0)
149 return (0);
150 m->m_off = MMINOFF;
151 bzero(mtod(m, caddr_t), MLEN);
152 return (m);
153}
154
d80cae33
BJ
155struct mbuf *
156m_free(m)
157 struct mbuf *m;
158{
159 register struct mbuf *n;
160
161COUNT(M_FREE);
162 MFREE(m, n);
163 return (n);
164}
165
ae921915 166/*ARGSUSED*/
d80cae33
BJ
167struct mbuf *
168m_more(type)
169 int type;
170{
d80cae33
BJ
171 register struct mbuf *m;
172
173COUNT(M_MORE);
174 if (!m_expand()) {
6d19f7ef 175 mbstat.m_drops++;
d80cae33
BJ
176 return (NULL);
177 }
ae921915
BJ
178#define m_more(x) (panic("m_more"), (struct mbuf *)0)
179 MGET(m, type);
3995e6f7 180#undef m_more
d80cae33
BJ
181 return (m);
182}
183
8f3e7457 184m_freem(m)
d80cae33
BJ
185 register struct mbuf *m;
186{
187 register struct mbuf *n;
2b4b57cd 188 register int s;
d80cae33
BJ
189
190COUNT(M_FREEM);
191 if (m == NULL)
ae921915 192 return;
dad64fdf 193 s = splimp();
d80cae33 194 do {
8f3e7457 195 MFREE(m, n);
d80cae33
BJ
196 } while (m = n);
197 splx(s);
2b4b57cd
BJ
198}
199
7c733634
BJ
200/*
201 * Mbuffer utility routines.
202 */
2b4b57cd
BJ
203struct mbuf *
204m_copy(m, off, len)
205 register struct mbuf *m;
206 int off;
207 register int len;
208{
209 register struct mbuf *n, **np;
210 struct mbuf *top, *p;
211COUNT(M_COPY);
212
213 if (len == 0)
214 return (0);
215 if (off < 0 || len < 0)
216 panic("m_copy");
217 while (off > 0) {
218 if (m == 0)
219 panic("m_copy");
220 if (off < m->m_len)
221 break;
222 off -= m->m_len;
223 m = m->m_next;
224 }
225 np = &top;
226 top = 0;
227 while (len > 0) {
842ff042
BJ
228 if (m == 0) {
229 if (len != M_COPYALL)
230 panic("m_copy");
231 break;
232 }
2b4b57cd
BJ
233 MGET(n, 1);
234 *np = n;
235 if (n == 0)
236 goto nospace;
2b4b57cd
BJ
237 n->m_len = MIN(len, m->m_len - off);
238 if (m->m_off > MMAXOFF) {
239 p = mtod(m, struct mbuf *);
240 n->m_off = ((int)p - (int)n) + off;
0ef33f87 241 mclrefcnt[mtocl(p)]++;
2b4b57cd
BJ
242 } else {
243 n->m_off = MMINOFF;
244 bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
245 (unsigned)n->m_len);
246 }
842ff042
BJ
247 if (len != M_COPYALL)
248 len -= n->m_len;
2b4b57cd
BJ
249 off = 0;
250 m = m->m_next;
251 np = &n->m_next;
252 }
253 return (top);
254nospace:
2b4b57cd
BJ
255 m_freem(top);
256 return (0);
d80cae33
BJ
257}
258
8f3e7457
BJ
259m_cat(m, n)
260 register struct mbuf *m, *n;
261{
262
263 while (m->m_next)
264 m = m->m_next;
265 while (n)
8f4851aa
BJ
266 if (m->m_off < MMAXOFF &&
267 m->m_off + m->m_len + n->m_len <= MMAXOFF) {
ae921915
BJ
268 bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
269 (u_int)n->m_len);
8f3e7457
BJ
270 m->m_len += n->m_len;
271 n = m_free(n);
272 } else {
273 m->m_next = n;
274 m = n;
275 n = m->m_next;
276 }
277}
278
d80cae33
BJ
279m_adj(mp, len)
280 struct mbuf *mp;
ae921915 281 register int len;
d80cae33
BJ
282{
283 register struct mbuf *m, *n;
284
285COUNT(M_ADJ);
286 if ((m = mp) == NULL)
287 return;
6d19f7ef 288 if (len >= 0) {
d80cae33 289 while (m != NULL && len > 0) {
6d19f7ef 290 if (m->m_len <= len) {
d80cae33
BJ
291 len -= m->m_len;
292 m->m_len = 0;
293 m = m->m_next;
6d19f7ef 294 } else {
d80cae33
BJ
295 m->m_len -= len;
296 m->m_off += len;
297 break;
298 }
299 }
6d19f7ef
BJ
300 } else {
301 /* a 2 pass algorithm might be better */
d80cae33
BJ
302 len = -len;
303 while (len > 0 && m->m_len != 0) {
d80cae33
BJ
304 while (m != NULL && m->m_len != 0) {
305 n = m;
306 m = m->m_next;
307 }
6d19f7ef 308 if (n->m_len <= len) {
d80cae33
BJ
309 len -= n->m_len;
310 n->m_len = 0;
311 m = mp;
6d19f7ef 312 } else {
d80cae33
BJ
313 n->m_len -= len;
314 break;
315 }
316 }
317 }
318}
7c733634 319
10103653
BJ
320struct mbuf *
321m_pullup(m0, len)
322 struct mbuf *m0;
7c733634
BJ
323 int len;
324{
10103653
BJ
325 register struct mbuf *m, *n;
326 int cnt;
7c733634 327
82bff71e 328 n = m0;
10103653
BJ
329 if (len > MLEN)
330 goto bad;
331 MGET(m, 0);
332 if (m == 0)
333 goto bad;
334 m->m_off = MMINOFF;
335 m->m_len = 0;
10103653
BJ
336 do {
337 cnt = MIN(MLEN - m->m_len, len);
338 if (cnt > n->m_len)
339 cnt = n->m_len;
340 bcopy(mtod(n, caddr_t), mtod(m, caddr_t)+m->m_len, cnt);
341 len -= cnt;
342 m->m_len += cnt;
343 n->m_off += cnt;
344 n->m_len -= cnt;
345 if (n->m_len)
346 break;
347 n = m_free(n);
348 } while (n);
349 if (len) {
350 (void) m_free(m);
351 goto bad;
352 }
353 m->m_next = n;
354 return (m);
355bad:
82bff71e 356 m_freem(n);
7c733634
BJ
357 return (0);
358}