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