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