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