Commit | Line | Data |
---|---|---|
a21231e3 | 1 | /* uipc_mbuf.c 6.2 84/02/22 */ |
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; | |
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 = ⊤ | |
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); | |
224 | nospace: | |
2b4b57cd BJ |
225 | m_freem(top); |
226 | return (0); | |
d80cae33 BJ |
227 | } |
228 | ||
8f3e7457 BJ |
229 | m_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 |
249 | m_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 |
289 | struct mbuf * |
290 | m_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); | |
324 | bad: | |
82bff71e | 325 | m_freem(n); |
7c733634 BJ |
326 | return (0); |
327 | } |