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