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