1 /* uipc_mbuf.c 1.35 82/06/14 */ 2 3 #include "../h/param.h" 4 #include "../h/dir.h" 5 #include "../h/user.h" 6 #include "../h/proc.h" 7 #include "../h/pte.h" 8 #include "../h/cmap.h" 9 #include "../h/map.h" 10 #include "../h/mbuf.h" 11 #include "../net/in_systm.h" /* XXX */ 12 #include "../h/vm.h" 13 14 mbinit() 15 { 16 17 COUNT(MBINIT); 18 if (m_clalloc(4, MPG_MBUFS) == 0) 19 goto bad; 20 if (m_clalloc(32, 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 COUNT(M_CLALLOC); 38 npg = ncl * CLSIZE; 39 s = splimp(); /* careful: rmalloc isn't reentrant */ 40 mbx = rmalloc(mbmap, npg); 41 splx(s); 42 if (mbx == 0) 43 return (0); 44 m = cltom(mbx / CLSIZE); 45 if (memall(&Mbmap[mbx], npg, proc, CSYS) == 0) 46 return (0); 47 vmaccess(&Mbmap[mbx], (caddr_t)m, npg); 48 switch (how) { 49 50 case MPG_CLUSTERS: 51 s = splimp(); 52 for (i = 0; i < ncl; i++) { 53 m->m_off = 0; 54 m->m_next = mclfree; 55 mclfree = m; 56 m += CLBYTES / sizeof (*m); 57 mbstat.m_clfree++; 58 } 59 mbstat.m_clusters += ncl; 60 splx(s); 61 break; 62 63 case MPG_MBUFS: 64 for (i = ncl * CLBYTES / sizeof (*m); i > 0; i--) { 65 m->m_off = 0; 66 m->m_free = 0; 67 mbstat.m_mbufs++; 68 (void) m_free(m); 69 m++; 70 } 71 break; 72 } 73 return ((caddr_t)m); 74 } 75 76 m_pgfree(addr, n) 77 caddr_t addr; 78 int n; 79 { 80 81 COUNT(M_PGFREE); 82 #ifdef lint 83 addr = addr; n = n; 84 #endif 85 } 86 87 m_expand() 88 { 89 90 COUNT(M_EXPAND); 91 if (m_clalloc(1, MPG_MBUFS) == 0) 92 goto steal; 93 return (1); 94 steal: 95 /* should ask protocols to free code */ 96 return (0); 97 } 98 99 /* NEED SOME WAY TO RELEASE SPACE */ 100 101 /* 102 * Space allocation routines. 103 * These are also available as macros 104 * for critical paths. 105 */ 106 struct mbuf * 107 m_get(canwait) 108 int canwait; 109 { 110 register struct mbuf *m; 111 112 COUNT(M_GET); 113 MGET(m, canwait); 114 return (m); 115 } 116 117 struct mbuf * 118 m_getclr(canwait) 119 int canwait; 120 { 121 register struct mbuf *m; 122 123 COUNT(M_GETCLR); 124 m = m_get(canwait); 125 if (m == 0) 126 return (0); 127 m->m_off = MMINOFF; 128 bzero(mtod(m, caddr_t), MLEN); 129 return (m); 130 } 131 132 struct mbuf * 133 m_free(m) 134 struct mbuf *m; 135 { 136 register struct mbuf *n; 137 138 COUNT(M_FREE); 139 MFREE(m, n); 140 return (n); 141 } 142 143 /*ARGSUSED*/ 144 struct mbuf * 145 m_more(type) 146 int type; 147 { 148 register struct mbuf *m; 149 150 COUNT(M_MORE); 151 if (!m_expand()) { 152 mbstat.m_drops++; 153 return (NULL); 154 } 155 #define m_more(x) (panic("m_more"), (struct mbuf *)0) 156 MGET(m, type); 157 #undef m_more 158 return (m); 159 } 160 161 m_freem(m) 162 register struct mbuf *m; 163 { 164 register struct mbuf *n; 165 register int s; 166 167 COUNT(M_FREEM); 168 if (m == NULL) 169 return; 170 s = splimp(); 171 do { 172 MFREE(m, n); 173 } while (m = n); 174 splx(s); 175 } 176 177 /* 178 * Mbuffer utility routines. 179 */ 180 struct mbuf * 181 m_copy(m, off, len) 182 register struct mbuf *m; 183 int off; 184 register int len; 185 { 186 register struct mbuf *n, **np; 187 struct mbuf *top, *p; 188 COUNT(M_COPY); 189 190 if (len == 0) 191 return (0); 192 if (off < 0 || len < 0) 193 panic("m_copy"); 194 while (off > 0) { 195 if (m == 0) 196 panic("m_copy"); 197 if (off < m->m_len) 198 break; 199 off -= m->m_len; 200 m = m->m_next; 201 } 202 np = ⊤ 203 top = 0; 204 while (len > 0) { 205 if (m == 0) { 206 if (len != M_COPYALL) 207 panic("m_copy"); 208 break; 209 } 210 MGET(n, 1); 211 *np = n; 212 if (n == 0) 213 goto nospace; 214 n->m_len = MIN(len, m->m_len - off); 215 if (m->m_off > MMAXOFF) { 216 p = mtod(m, struct mbuf *); 217 n->m_off = ((int)p - (int)n) + off; 218 mclrefcnt[mtocl(p)]++; 219 } else { 220 n->m_off = MMINOFF; 221 bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t), 222 (unsigned)n->m_len); 223 } 224 if (len != M_COPYALL) 225 len -= n->m_len; 226 off = 0; 227 m = m->m_next; 228 np = &n->m_next; 229 } 230 return (top); 231 nospace: 232 m_freem(top); 233 return (0); 234 } 235 236 m_cat(m, n) 237 register struct mbuf *m, *n; 238 { 239 while (m->m_next) 240 m = m->m_next; 241 while (n) { 242 if (m->m_off >= MMAXOFF || 243 m->m_off + m->m_len + n->m_len > MMAXOFF) { 244 /* just join the two chains */ 245 m->m_next = n; 246 return; 247 } 248 /* splat the data from one into the other */ 249 bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, 250 (u_int)n->m_len); 251 m->m_len += n->m_len; 252 n = m_free(n); 253 } 254 } 255 256 m_adj(mp, len) 257 struct mbuf *mp; 258 register int len; 259 { 260 register struct mbuf *m, *n; 261 262 COUNT(M_ADJ); 263 if ((m = mp) == NULL) 264 return; 265 if (len >= 0) { 266 while (m != NULL && len > 0) { 267 if (m->m_len <= len) { 268 len -= m->m_len; 269 m->m_len = 0; 270 m = m->m_next; 271 } else { 272 m->m_len -= len; 273 m->m_off += len; 274 break; 275 } 276 } 277 } else { 278 /* a 2 pass algorithm might be better */ 279 len = -len; 280 while (len > 0 && m->m_len != 0) { 281 while (m != NULL && m->m_len != 0) { 282 n = m; 283 m = m->m_next; 284 } 285 if (n->m_len <= len) { 286 len -= n->m_len; 287 n->m_len = 0; 288 m = mp; 289 } else { 290 n->m_len -= len; 291 break; 292 } 293 } 294 } 295 } 296 297 struct mbuf * 298 m_pullup(m0, len) 299 struct mbuf *m0; 300 int len; 301 { 302 register struct mbuf *m, *n; 303 int count; 304 305 n = m0; 306 if (len > MLEN) 307 goto bad; 308 MGET(m, 0); 309 if (m == 0) 310 goto bad; 311 m->m_off = MMINOFF; 312 m->m_len = 0; 313 do { 314 count = MIN(MLEN - m->m_len, len); 315 if (count > n->m_len) 316 count = n->m_len; 317 bcopy(mtod(n, caddr_t), mtod(m, caddr_t)+m->m_len, 318 (unsigned)count); 319 len -= count; 320 m->m_len += count; 321 n->m_off += count; 322 n->m_len -= count; 323 if (n->m_len) 324 break; 325 n = m_free(n); 326 } while (n); 327 if (len) { 328 (void) m_free(m); 329 goto bad; 330 } 331 m->m_next = n; 332 return (m); 333 bad: 334 m_freem(n); 335 return (0); 336 } 337