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