1 /* uipc_mbuf.c 1.17 81/11/26 */ 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 m_reserve(mbufs) 15 int mbufs; 16 { 17 18 /* 19 printf("reserve %d\n", mbufs); 20 */ 21 if (mbstat.m_lowat + (mbufs>>1) > (NMBPAGES-32) * CLBYTES) 22 return (0); 23 mbstat.m_hiwat += mbufs; 24 mbstat.m_lowat = mbstat.m_hiwat >> 1; 25 return (1); 26 } 27 28 m_release(mbufs) 29 int mbufs; 30 { 31 32 /* 33 printf("release %d\n", mbufs); 34 */ 35 mbstat.m_hiwat -= mbufs; 36 mbstat.m_lowat = mbstat.m_hiwat >> 1; 37 } 38 39 struct mbuf * 40 m_get(canwait) 41 int canwait; 42 { 43 register struct mbuf *m; 44 45 COUNT(M_GET); 46 MGET(m, canwait); 47 return (m); 48 } 49 50 struct mbuf * 51 m_getclr(canwait) 52 int canwait; 53 { 54 register struct mbuf *m; 55 56 COUNT(M_GETCLR); 57 m = m_get(canwait); 58 if (m == 0) 59 return (0); 60 m->m_off = MMINOFF; 61 bzero(mtod(m, caddr_t), MLEN); 62 return (m); 63 } 64 65 struct mbuf * 66 m_free(m) 67 struct mbuf *m; 68 { 69 register struct mbuf *n; 70 71 COUNT(M_FREE); 72 MFREE(m, n); 73 return (n); 74 } 75 76 /*ARGSUSED*/ 77 struct mbuf * 78 m_more(type) 79 int type; 80 { 81 register struct mbuf *m; 82 83 COUNT(M_MORE); 84 if (!m_expand()) { 85 mbstat.m_drops++; 86 return (NULL); 87 } 88 #define m_more(x) (panic("m_more"), (struct mbuf *)0) 89 MGET(m, type); 90 return (m); 91 } 92 93 m_freem(m) 94 register struct mbuf *m; 95 { 96 register struct mbuf *n; 97 register int s; 98 99 COUNT(M_FREEM); 100 if (m == NULL) 101 return; 102 s = splimp(); 103 do { 104 MFREE(m, n); 105 } while (m = n); 106 splx(s); 107 } 108 109 /*ARGSUSED*/ 110 m_pullup(m, len) 111 struct mbuf *m; 112 int len; 113 { 114 115 return (0); 116 } 117 118 struct mbuf * 119 m_copy(m, off, len) 120 register struct mbuf *m; 121 int off; 122 register int len; 123 { 124 register struct mbuf *n, **np; 125 struct mbuf *top, *p; 126 COUNT(M_COPY); 127 128 if (len == 0) 129 return (0); 130 if (off < 0 || len < 0) 131 panic("m_copy"); 132 while (off > 0) { 133 if (m == 0) 134 panic("m_copy"); 135 if (off < m->m_len) 136 break; 137 off -= m->m_len; 138 m = m->m_next; 139 } 140 np = ⊤ 141 top = 0; 142 while (len > 0) { 143 MGET(n, 1); 144 *np = n; 145 if (n == 0) 146 goto nospace; 147 if (m == 0) 148 panic("m_copy"); 149 n->m_len = MIN(len, m->m_len - off); 150 if (m->m_off > MMAXOFF) { 151 p = mtod(m, struct mbuf *); 152 n->m_off = ((int)p - (int)n) + off; 153 mclrefcnt[mtocl(p)]++; 154 } else { 155 n->m_off = MMINOFF; 156 bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t), 157 (unsigned)n->m_len); 158 } 159 len -= n->m_len; 160 off = 0; 161 m = m->m_next; 162 np = &n->m_next; 163 } 164 return (top); 165 nospace: 166 printf("m_copy: no space\n"); 167 m_freem(top); 168 return (0); 169 } 170 171 mbinit() 172 { 173 register struct mbuf *m; 174 register i; 175 176 COUNT(MBUFINIT); 177 m = (struct mbuf *)&mbutl[0]; /* ->start of buffer virt mem */ 178 (void) vmemall(&Mbmap[0], 2, proc, CSYS); 179 vmaccess(&Mbmap[0], (caddr_t)m, 2); 180 for (i=0; i < CLBYTES / sizeof (struct mbuf); i++) { 181 m->m_off = 0; 182 (void) m_free(m); 183 m++; 184 } 185 (void) m_pgalloc(3); 186 mbstat.m_pages = 4; 187 mbstat.m_bufs = 32; 188 mbstat.m_lowat = 16; 189 mbstat.m_hiwat = 32; 190 { int j,k,n; 191 n = 32; 192 k = n << 1; 193 if ((i = rmalloc(mbmap, n)) == 0) 194 panic("mbinit"); 195 j = i<<1; 196 m = cltom(i); 197 /* should use vmemall sometimes */ 198 if (memall(&Mbmap[j], k, proc, CSYS) == 0) { 199 printf("botch\n"); 200 return; 201 } 202 vmaccess(&Mbmap[j], (caddr_t)m, k); 203 for (j=0; j < n; j++) { 204 m->m_off = 0; 205 m->m_next = mclfree; 206 mclfree = m; 207 m += CLBYTES / sizeof (*m); 208 nmclfree++; 209 } 210 } 211 } 212 213 m_pgalloc(n) 214 register int n; 215 { 216 register i, j, k; 217 register struct mbuf *m; 218 int bufs, s; 219 220 COUNT(M_PGALLOC); 221 k = n << 1; 222 if ((i = rmalloc(mbmap, n)) == 0) 223 return (0); 224 j = i<<1; 225 m = cltom(i); 226 /* should use vmemall sometimes */ 227 if (memall(&Mbmap[j], k, proc, CSYS) == 0) 228 return (0); 229 vmaccess(&Mbmap[j], (caddr_t)m, k); 230 bufs = n << 3; 231 s = splimp(); 232 for (j=0; j < bufs; j++) { 233 m->m_off = 0; 234 (void) m_free(m); 235 m++; 236 } 237 splx(s); 238 mbstat.m_pages += n; 239 return (1); 240 } 241 242 /*ARGSUSED*/ 243 m_pgfree(addr, n) 244 caddr_t addr; 245 int n; 246 { 247 248 COUNT(M_PGFREE); 249 printf("m_pgfree %x %d\n", addr, n); 250 } 251 252 m_expand() 253 { 254 register i; 255 int need, needp, needs; 256 257 COUNT(M_EXPAND); 258 needs = need = mbstat.m_hiwat - mbstat.m_bufs; 259 needp = need >> 3; 260 if (m_pgalloc(needp)) 261 return (1); 262 for (i=0; i < needp; i++, need -= CLBYTES / sizeof (struct mbuf)) 263 if (m_pgalloc(1) == 0) 264 goto steal; 265 return (need < needs); 266 steal: 267 /* while (not enough) ask protocols to free code */ 268 ; 269 return (0); 270 } 271 272 #ifdef notdef 273 m_relse() 274 { 275 276 COUNT(M_RELSE); 277 } 278 #endif 279 280 m_cat(m, n) 281 register struct mbuf *m, *n; 282 { 283 284 while (m->m_next) 285 m = m->m_next; 286 while (n) 287 if (m->m_off + m->m_len + n->m_len <= MMAXOFF) { 288 bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, 289 (u_int)n->m_len); 290 m->m_len += n->m_len; 291 n = m_free(n); 292 } else { 293 m->m_next = n; 294 m = n; 295 n = m->m_next; 296 } 297 } 298 299 m_adj(mp, len) 300 struct mbuf *mp; 301 register int len; 302 { 303 register struct mbuf *m, *n; 304 305 COUNT(M_ADJ); 306 if ((m = mp) == NULL) 307 return; 308 if (len >= 0) { 309 while (m != NULL && len > 0) { 310 if (m->m_len <= len) { 311 len -= m->m_len; 312 m->m_len = 0; 313 m = m->m_next; 314 } else { 315 m->m_len -= len; 316 m->m_off += len; 317 break; 318 } 319 } 320 } else { 321 /* a 2 pass algorithm might be better */ 322 len = -len; 323 while (len > 0 && m->m_len != 0) { 324 while (m != NULL && m->m_len != 0) { 325 n = m; 326 m = m->m_next; 327 } 328 if (n->m_len <= len) { 329 len -= n->m_len; 330 n->m_len = 0; 331 m = mp; 332 } else { 333 n->m_len -= len; 334 break; 335 } 336 } 337 } 338 } 339