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