1 /* uipc_mbuf.c 6.3 84/08/29 */ 2 3 #include "../machine/pte.h" 4 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" 14 15 mbinit() 16 { 17 18 if (m_clalloc(4096/CLBYTES, MPG_MBUFS) == 0) 19 goto bad; 20 if (m_clalloc(8*4096/CLBYTES, MPG_CLUSTERS) == 0) 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 37 npg = ncl * CLSIZE; 38 s = splimp(); /* careful: rmalloc isn't reentrant */ 39 mbx = rmalloc(mbmap, (long)npg); 40 splx(s); 41 if (mbx == 0) 42 return (0); 43 m = cltom(mbx / CLSIZE); 44 if (memall(&Mbmap[mbx], npg, proc, CSYS) == 0) { 45 s = splimp(); 46 rmfree(mbmap, (long)npg, (long)mbx); 47 splx(s); 48 return (0); 49 } 50 vmaccess(&Mbmap[mbx], (caddr_t)m, npg); 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); 60 mbstat.m_clfree++; 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; 69 m->m_type = MT_DATA; 70 mbstat.m_mtypes[MT_DATA]++; 71 mbstat.m_mbufs++; 72 (void) m_free(m); 73 m++; 74 } 75 break; 76 } 77 return ((caddr_t)m); 78 } 79 80 m_pgfree(addr, n) 81 caddr_t addr; 82 int n; 83 { 84 85 #ifdef lint 86 addr = addr; n = n; 87 #endif 88 } 89 90 m_expand() 91 { 92 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 103 /* 104 * Space allocation routines. 105 * These are also available as macros 106 * for critical paths. 107 */ 108 struct mbuf * 109 m_get(canwait, type) 110 int canwait, type; 111 { 112 register struct mbuf *m; 113 114 MGET(m, canwait, type); 115 return (m); 116 } 117 118 struct mbuf * 119 m_getclr(canwait, type) 120 int canwait, type; 121 { 122 register struct mbuf *m; 123 124 m = m_get(canwait, type); 125 if (m == 0) 126 return (0); 127 bzero(mtod(m, caddr_t), MLEN); 128 return (m); 129 } 130 131 struct mbuf * 132 m_free(m) 133 struct mbuf *m; 134 { 135 register struct mbuf *n; 136 137 MFREE(m, n); 138 return (n); 139 } 140 141 /*ARGSUSED*/ 142 struct mbuf * 143 m_more(canwait, type) 144 int canwait, type; 145 { 146 register struct mbuf *m; 147 148 if (!m_expand()) { 149 mbstat.m_drops++; 150 return (NULL); 151 } 152 #define m_more(x,y) (panic("m_more"), (struct mbuf *)0) 153 MGET(m, canwait, type); 154 #undef m_more 155 return (m); 156 } 157 158 m_freem(m) 159 register struct mbuf *m; 160 { 161 register struct mbuf *n; 162 register int s; 163 164 if (m == NULL) 165 return; 166 s = splimp(); 167 do { 168 MFREE(m, n); 169 } while (m = n); 170 splx(s); 171 } 172 173 /* 174 * Mbuffer utility routines. 175 */ 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; 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) { 200 if (m == 0) { 201 if (len != M_COPYALL) 202 panic("m_copy"); 203 break; 204 } 205 MGET(n, M_WAIT, m->m_type); 206 *np = n; 207 if (n == 0) 208 goto nospace; 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; 213 mclrefcnt[mtocl(p)]++; 214 } else 215 bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t), 216 (unsigned)n->m_len); 217 if (len != M_COPYALL) 218 len -= n->m_len; 219 off = 0; 220 m = m->m_next; 221 np = &n->m_next; 222 } 223 return (top); 224 nospace: 225 m_freem(top); 226 return (0); 227 } 228 229 m_cat(m, n) 230 register struct mbuf *m, *n; 231 { 232 while (m->m_next) 233 m = m->m_next; 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 */ 238 m->m_next = n; 239 return; 240 } 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 } 247 } 248 249 m_adj(mp, len) 250 struct mbuf *mp; 251 register int len; 252 { 253 register struct mbuf *m, *n; 254 255 if ((m = mp) == NULL) 256 return; 257 if (len >= 0) { 258 while (m != NULL && len > 0) { 259 if (m->m_len <= len) { 260 len -= m->m_len; 261 m->m_len = 0; 262 m = m->m_next; 263 } else { 264 m->m_len -= len; 265 m->m_off += len; 266 break; 267 } 268 } 269 } else { 270 /* a 2 pass algorithm might be better */ 271 len = -len; 272 while (len > 0 && m->m_len != 0) { 273 while (m != NULL && m->m_len != 0) { 274 n = m; 275 m = m->m_next; 276 } 277 if (n->m_len <= len) { 278 len -= n->m_len; 279 n->m_len = 0; 280 m = mp; 281 } else { 282 n->m_len -= len; 283 break; 284 } 285 } 286 } 287 } 288 289 struct mbuf * 290 m_pullup(m0, len) 291 struct mbuf *m0; 292 int len; 293 { 294 register struct mbuf *m, *n; 295 int count; 296 297 n = m0; 298 if (len > MLEN) 299 goto bad; 300 MGET(m, M_DONTWAIT, n->m_type); 301 if (m == 0) 302 goto bad; 303 m->m_len = 0; 304 do { 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; 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: 325 m_freem(n); 326 return (0); 327 } 328