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