Commit | Line | Data |
---|---|---|
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 |
15 | mbinit() |
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; |
26 | bad: | |
27 | panic("mbinit"); | |
28 | } | |
29 | ||
9c59be2b MK |
30 | /* |
31 | * Must be called at splimp. | |
32 | */ | |
7c733634 | 33 | caddr_t |
9c59be2b | 34 | m_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 | ||
82 | m_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 | */ | |
95 | m_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); | |
102 | steal: | |
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 | 114 | struct mbuf * |
cce93e4b SL |
115 | m_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 | 124 | struct mbuf * |
cce93e4b SL |
125 | m_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 |
137 | struct mbuf * |
138 | m_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 | 152 | struct mbuf * |
cce93e4b SL |
153 | m_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 | 173 | m_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 |
197 | struct mbuf * |
198 | m_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 = ⊤ | |
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); | |
245 | nospace: | |
2b4b57cd BJ |
246 | m_freem(top); |
247 | return (0); | |
d80cae33 BJ |
248 | } |
249 | ||
8f3e7457 BJ |
250 | m_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 |
270 | m_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 |
310 | struct mbuf * |
311 | m_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); | |
345 | bad: | |
82bff71e | 346 | m_freem(n); |
7c733634 BJ |
347 | return (0); |
348 | } |