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