Commit | Line | Data |
---|---|---|
88a7a62a | 1 | /* uipc_mbuf.c 1.43 83/05/27 */ |
961945a8 SL |
2 | |
3 | #include "../machine/pte.h" | |
d80cae33 BJ |
4 | |
5 | #include "../h/param.h" | |
6 | #include "../h/dir.h" | |
7 | #include "../h/user.h" | |
8 | #include "../h/proc.h" | |
d80cae33 BJ |
9 | #include "../h/cmap.h" |
10 | #include "../h/map.h" | |
e6dd2097 | 11 | #include "../h/mbuf.h" |
d80cae33 | 12 | #include "../h/vm.h" |
39d536e6 | 13 | #include "../h/kernel.h" |
d80cae33 | 14 | |
7c733634 BJ |
15 | mbinit() |
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; | |
23 | bad: | |
24 | panic("mbinit"); | |
25 | } | |
26 | ||
27 | caddr_t | |
28 | m_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 | ||
80 | m_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 | ||
90 | m_expand() | |
91 | { | |
92 | ||
7c733634 BJ |
93 | if (m_clalloc(1, MPG_MBUFS) == 0) |
94 | goto steal; | |
95 | return (1); | |
96 | steal: | |
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 | 108 | struct mbuf * |
cce93e4b SL |
109 | m_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 | 118 | struct mbuf * |
cce93e4b SL |
119 | m_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 |
131 | struct mbuf * |
132 | m_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 | 142 | struct mbuf * |
cce93e4b SL |
143 | m_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 | 158 | m_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 |
176 | struct mbuf * |
177 | m_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; | |
cce93e4b | 184 | int type; |
2b4b57cd BJ |
185 | |
186 | if (len == 0) | |
187 | return (0); | |
188 | if (off < 0 || len < 0) | |
189 | panic("m_copy"); | |
cce93e4b | 190 | type = m->m_type; |
2b4b57cd BJ |
191 | while (off > 0) { |
192 | if (m == 0) | |
193 | panic("m_copy"); | |
194 | if (off < m->m_len) | |
195 | break; | |
196 | off -= m->m_len; | |
197 | m = m->m_next; | |
198 | } | |
199 | np = ⊤ | |
200 | top = 0; | |
201 | while (len > 0) { | |
842ff042 BJ |
202 | if (m == 0) { |
203 | if (len != M_COPYALL) | |
204 | panic("m_copy"); | |
205 | break; | |
206 | } | |
cce93e4b | 207 | MGET(n, M_WAIT, type); |
2b4b57cd BJ |
208 | *np = n; |
209 | if (n == 0) | |
210 | goto nospace; | |
2b4b57cd BJ |
211 | n->m_len = MIN(len, m->m_len - off); |
212 | if (m->m_off > MMAXOFF) { | |
213 | p = mtod(m, struct mbuf *); | |
214 | n->m_off = ((int)p - (int)n) + off; | |
0ef33f87 | 215 | mclrefcnt[mtocl(p)]++; |
970108c7 | 216 | } else |
2b4b57cd BJ |
217 | bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t), |
218 | (unsigned)n->m_len); | |
842ff042 BJ |
219 | if (len != M_COPYALL) |
220 | len -= n->m_len; | |
2b4b57cd BJ |
221 | off = 0; |
222 | m = m->m_next; | |
223 | np = &n->m_next; | |
224 | } | |
225 | return (top); | |
226 | nospace: | |
2b4b57cd BJ |
227 | m_freem(top); |
228 | return (0); | |
d80cae33 BJ |
229 | } |
230 | ||
8f3e7457 BJ |
231 | m_cat(m, n) |
232 | register struct mbuf *m, *n; | |
233 | { | |
8f3e7457 BJ |
234 | while (m->m_next) |
235 | m = m->m_next; | |
e495e1cc BJ |
236 | while (n) { |
237 | if (m->m_off >= MMAXOFF || | |
238 | m->m_off + m->m_len + n->m_len > MMAXOFF) { | |
239 | /* just join the two chains */ | |
8f3e7457 | 240 | m->m_next = n; |
e495e1cc | 241 | return; |
8f3e7457 | 242 | } |
e495e1cc BJ |
243 | /* splat the data from one into the other */ |
244 | bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, | |
245 | (u_int)n->m_len); | |
246 | m->m_len += n->m_len; | |
247 | n = m_free(n); | |
248 | } | |
8f3e7457 BJ |
249 | } |
250 | ||
d80cae33 BJ |
251 | m_adj(mp, len) |
252 | struct mbuf *mp; | |
ae921915 | 253 | register int len; |
d80cae33 BJ |
254 | { |
255 | register struct mbuf *m, *n; | |
256 | ||
d80cae33 BJ |
257 | if ((m = mp) == NULL) |
258 | return; | |
6d19f7ef | 259 | if (len >= 0) { |
d80cae33 | 260 | while (m != NULL && len > 0) { |
6d19f7ef | 261 | if (m->m_len <= len) { |
d80cae33 BJ |
262 | len -= m->m_len; |
263 | m->m_len = 0; | |
264 | m = m->m_next; | |
6d19f7ef | 265 | } else { |
d80cae33 BJ |
266 | m->m_len -= len; |
267 | m->m_off += len; | |
268 | break; | |
269 | } | |
270 | } | |
6d19f7ef BJ |
271 | } else { |
272 | /* a 2 pass algorithm might be better */ | |
d80cae33 BJ |
273 | len = -len; |
274 | while (len > 0 && m->m_len != 0) { | |
d80cae33 BJ |
275 | while (m != NULL && m->m_len != 0) { |
276 | n = m; | |
277 | m = m->m_next; | |
278 | } | |
6d19f7ef | 279 | if (n->m_len <= len) { |
d80cae33 BJ |
280 | len -= n->m_len; |
281 | n->m_len = 0; | |
282 | m = mp; | |
6d19f7ef | 283 | } else { |
d80cae33 BJ |
284 | n->m_len -= len; |
285 | break; | |
286 | } | |
287 | } | |
288 | } | |
289 | } | |
7c733634 | 290 | |
10103653 BJ |
291 | struct mbuf * |
292 | m_pullup(m0, len) | |
293 | struct mbuf *m0; | |
7c733634 BJ |
294 | int len; |
295 | { | |
10103653 | 296 | register struct mbuf *m, *n; |
668cc26d | 297 | int count; |
7c733634 | 298 | |
82bff71e | 299 | n = m0; |
10103653 BJ |
300 | if (len > MLEN) |
301 | goto bad; | |
cce93e4b | 302 | MGET(m, M_DONTWAIT, n->m_type); |
10103653 BJ |
303 | if (m == 0) |
304 | goto bad; | |
10103653 | 305 | m->m_len = 0; |
10103653 | 306 | do { |
668cc26d SL |
307 | count = MIN(MLEN - m->m_len, len); |
308 | if (count > n->m_len) | |
309 | count = n->m_len; | |
310 | bcopy(mtod(n, caddr_t), mtod(m, caddr_t)+m->m_len, | |
311 | (unsigned)count); | |
312 | len -= count; | |
313 | m->m_len += count; | |
314 | n->m_off += count; | |
315 | n->m_len -= count; | |
10103653 BJ |
316 | if (n->m_len) |
317 | break; | |
318 | n = m_free(n); | |
319 | } while (n); | |
320 | if (len) { | |
321 | (void) m_free(m); | |
322 | goto bad; | |
323 | } | |
324 | m->m_next = n; | |
325 | return (m); | |
326 | bad: | |
82bff71e | 327 | m_freem(n); |
7c733634 BJ |
328 | return (0); |
329 | } |