1*17102Sbloom /* uipc_mbuf.c 6.3 84/08/29 */ 24585Swnj 39765Ssam #include "../machine/pte.h" 49765Ssam 5*17102Sbloom #include "param.h" 6*17102Sbloom #include "dir.h" 7*17102Sbloom #include "user.h" 8*17102Sbloom #include "proc.h" 9*17102Sbloom #include "cmap.h" 10*17102Sbloom #include "map.h" 11*17102Sbloom #include "mbuf.h" 12*17102Sbloom #include "vm.h" 13*17102Sbloom #include "kernel.h" 144585Swnj 155228Swnj mbinit() 165228Swnj { 175228Swnj 189765Ssam if (m_clalloc(4096/CLBYTES, MPG_MBUFS) == 0) 195228Swnj goto bad; 209765Ssam if (m_clalloc(8*4096/CLBYTES, MPG_CLUSTERS) == 0) 215228Swnj goto bad; 225228Swnj return; 235228Swnj bad: 245228Swnj panic("mbinit"); 255228Swnj } 265228Swnj 275228Swnj caddr_t 285228Swnj m_clalloc(ncl, how) 295228Swnj register int ncl; 305228Swnj int how; 315228Swnj { 325228Swnj int npg, mbx; 335228Swnj register struct mbuf *m; 345228Swnj register int i; 355228Swnj int s; 365228Swnj 375228Swnj npg = ncl * CLSIZE; 385581Swnj s = splimp(); /* careful: rmalloc isn't reentrant */ 398792Sroot mbx = rmalloc(mbmap, (long)npg); 405581Swnj splx(s); 415228Swnj if (mbx == 0) 425228Swnj return (0); 435228Swnj m = cltom(mbx / CLSIZE); 449765Ssam if (memall(&Mbmap[mbx], npg, proc, CSYS) == 0) { 459765Ssam s = splimp(); 469765Ssam rmfree(mbmap, (long)npg, (long)mbx); 479765Ssam splx(s); 485228Swnj return (0); 499765Ssam } 505228Swnj vmaccess(&Mbmap[mbx], (caddr_t)m, npg); 515228Swnj switch (how) { 525228Swnj 535228Swnj case MPG_CLUSTERS: 545228Swnj s = splimp(); 555228Swnj for (i = 0; i < ncl; i++) { 565228Swnj m->m_off = 0; 575228Swnj m->m_next = mclfree; 585228Swnj mclfree = m; 595228Swnj m += CLBYTES / sizeof (*m); 606839Ssam mbstat.m_clfree++; 615228Swnj } 625228Swnj mbstat.m_clusters += ncl; 635228Swnj splx(s); 645228Swnj break; 655228Swnj 665228Swnj case MPG_MBUFS: 675228Swnj for (i = ncl * CLBYTES / sizeof (*m); i > 0; i--) { 685228Swnj m->m_off = 0; 699634Ssam m->m_type = MT_DATA; 709634Ssam mbstat.m_mtypes[MT_DATA]++; 716839Ssam mbstat.m_mbufs++; 725228Swnj (void) m_free(m); 735228Swnj m++; 745228Swnj } 755232Swnj break; 765228Swnj } 775228Swnj return ((caddr_t)m); 785228Swnj } 795228Swnj 805228Swnj m_pgfree(addr, n) 815228Swnj caddr_t addr; 825228Swnj int n; 835228Swnj { 845228Swnj 856141Ssam #ifdef lint 866141Ssam addr = addr; n = n; 876141Ssam #endif 885228Swnj } 895228Swnj 905228Swnj m_expand() 915228Swnj { 925228Swnj 935228Swnj if (m_clalloc(1, MPG_MBUFS) == 0) 945228Swnj goto steal; 955228Swnj return (1); 965228Swnj steal: 975228Swnj /* should ask protocols to free code */ 985228Swnj return (0); 995228Swnj } 1005228Swnj 1015228Swnj /* NEED SOME WAY TO RELEASE SPACE */ 1025228Swnj 1035228Swnj /* 1045228Swnj * Space allocation routines. 1055228Swnj * These are also available as macros 1065228Swnj * for critical paths. 1075228Swnj */ 1084585Swnj struct mbuf * 1099634Ssam m_get(canwait, type) 1109634Ssam int canwait, type; 1114585Swnj { 1124585Swnj register struct mbuf *m; 1134585Swnj 1149634Ssam MGET(m, canwait, type); 1154585Swnj return (m); 1164585Swnj } 1174585Swnj 1184585Swnj struct mbuf * 1199634Ssam m_getclr(canwait, type) 1209634Ssam int canwait, type; 1214890Swnj { 1224890Swnj register struct mbuf *m; 1234890Swnj 1249634Ssam m = m_get(canwait, type); 1254890Swnj if (m == 0) 1264890Swnj return (0); 1274890Swnj bzero(mtod(m, caddr_t), MLEN); 1284890Swnj return (m); 1294890Swnj } 1304890Swnj 1314890Swnj struct mbuf * 1324585Swnj m_free(m) 1334585Swnj struct mbuf *m; 1344585Swnj { 1354585Swnj register struct mbuf *n; 1364585Swnj 1374585Swnj MFREE(m, n); 1384585Swnj return (n); 1394585Swnj } 1404585Swnj 1414916Swnj /*ARGSUSED*/ 1424585Swnj struct mbuf * 1439634Ssam m_more(canwait, type) 1449634Ssam int canwait, type; 1454585Swnj { 1464585Swnj register struct mbuf *m; 1474585Swnj 1484585Swnj if (!m_expand()) { 1494822Swnj mbstat.m_drops++; 1504585Swnj return (NULL); 1514585Swnj } 1529634Ssam #define m_more(x,y) (panic("m_more"), (struct mbuf *)0) 1539634Ssam MGET(m, canwait, type); 1545282Sroot #undef m_more 1554585Swnj return (m); 1564585Swnj } 1574585Swnj 1584669Swnj m_freem(m) 1594585Swnj register struct mbuf *m; 1604585Swnj { 1614585Swnj register struct mbuf *n; 1624927Swnj register int s; 1634585Swnj 1644585Swnj if (m == NULL) 1654916Swnj return; 1664662Swnj s = splimp(); 1674585Swnj do { 1684585Swnj MFREE(m, n); 1694585Swnj } while (m = n); 1704585Swnj splx(s); 1714585Swnj } 1724585Swnj 1735228Swnj /* 1745228Swnj * Mbuffer utility routines. 1755228Swnj */ 1764927Swnj struct mbuf * 1774927Swnj m_copy(m, off, len) 1784927Swnj register struct mbuf *m; 1794927Swnj int off; 1804927Swnj register int len; 1814927Swnj { 1824927Swnj register struct mbuf *n, **np; 1834927Swnj struct mbuf *top, *p; 1844927Swnj 1854927Swnj if (len == 0) 1864927Swnj return (0); 1874927Swnj if (off < 0 || len < 0) 1884927Swnj panic("m_copy"); 1894927Swnj while (off > 0) { 1904927Swnj if (m == 0) 1914927Swnj panic("m_copy"); 1924927Swnj if (off < m->m_len) 1934927Swnj break; 1944927Swnj off -= m->m_len; 1954927Swnj m = m->m_next; 1964927Swnj } 1974927Swnj np = ⊤ 1984927Swnj top = 0; 1994927Swnj while (len > 0) { 2005609Swnj if (m == 0) { 2015609Swnj if (len != M_COPYALL) 2025609Swnj panic("m_copy"); 2035609Swnj break; 2045609Swnj } 20516075Skarels MGET(n, M_WAIT, m->m_type); 2064927Swnj *np = n; 2074927Swnj if (n == 0) 2084927Swnj goto nospace; 2094927Swnj n->m_len = MIN(len, m->m_len - off); 2104927Swnj if (m->m_off > MMAXOFF) { 2114927Swnj p = mtod(m, struct mbuf *); 2124927Swnj n->m_off = ((int)p - (int)n) + off; 2135090Swnj mclrefcnt[mtocl(p)]++; 2148318Sroot } else 2154927Swnj bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t), 2164927Swnj (unsigned)n->m_len); 2175609Swnj if (len != M_COPYALL) 2185609Swnj len -= n->m_len; 2194927Swnj off = 0; 2204927Swnj m = m->m_next; 2214927Swnj np = &n->m_next; 2224927Swnj } 2234927Swnj return (top); 2244927Swnj nospace: 2254927Swnj m_freem(top); 2264927Swnj return (0); 2274927Swnj } 2284927Swnj 2294669Swnj m_cat(m, n) 2304669Swnj register struct mbuf *m, *n; 2314669Swnj { 2324669Swnj while (m->m_next) 2334669Swnj m = m->m_next; 2346091Sroot while (n) { 2356091Sroot if (m->m_off >= MMAXOFF || 2366091Sroot m->m_off + m->m_len + n->m_len > MMAXOFF) { 2376091Sroot /* just join the two chains */ 2384669Swnj m->m_next = n; 2396091Sroot return; 2404669Swnj } 2416091Sroot /* splat the data from one into the other */ 2426091Sroot bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, 2436091Sroot (u_int)n->m_len); 2446091Sroot m->m_len += n->m_len; 2456091Sroot n = m_free(n); 2466091Sroot } 2474669Swnj } 2484669Swnj 2494585Swnj m_adj(mp, len) 2504585Swnj struct mbuf *mp; 2514916Swnj register int len; 2524585Swnj { 2534585Swnj register struct mbuf *m, *n; 2544585Swnj 2554585Swnj if ((m = mp) == NULL) 2564585Swnj return; 2574822Swnj if (len >= 0) { 2584585Swnj while (m != NULL && len > 0) { 2594822Swnj if (m->m_len <= len) { 2604585Swnj len -= m->m_len; 2614585Swnj m->m_len = 0; 2624585Swnj m = m->m_next; 2634822Swnj } else { 2644585Swnj m->m_len -= len; 2654585Swnj m->m_off += len; 2664585Swnj break; 2674585Swnj } 2684585Swnj } 2694822Swnj } else { 2704822Swnj /* a 2 pass algorithm might be better */ 2714585Swnj len = -len; 2724585Swnj while (len > 0 && m->m_len != 0) { 2734585Swnj while (m != NULL && m->m_len != 0) { 2744585Swnj n = m; 2754585Swnj m = m->m_next; 2764585Swnj } 2774822Swnj if (n->m_len <= len) { 2784585Swnj len -= n->m_len; 2794585Swnj n->m_len = 0; 2804585Swnj m = mp; 2814822Swnj } else { 2824585Swnj n->m_len -= len; 2834585Swnj break; 2844585Swnj } 2854585Swnj } 2864585Swnj } 2874585Swnj } 2885228Swnj 2895310Sroot struct mbuf * 2905310Sroot m_pullup(m0, len) 2915310Sroot struct mbuf *m0; 2925228Swnj int len; 2935228Swnj { 2945310Sroot register struct mbuf *m, *n; 2956164Ssam int count; 2965228Swnj 2975732Sroot n = m0; 2985310Sroot if (len > MLEN) 2995310Sroot goto bad; 3009634Ssam MGET(m, M_DONTWAIT, n->m_type); 3015310Sroot if (m == 0) 3025310Sroot goto bad; 3035310Sroot m->m_len = 0; 3045310Sroot do { 3056164Ssam count = MIN(MLEN - m->m_len, len); 3066164Ssam if (count > n->m_len) 3076164Ssam count = n->m_len; 3086164Ssam bcopy(mtod(n, caddr_t), mtod(m, caddr_t)+m->m_len, 3096164Ssam (unsigned)count); 3106164Ssam len -= count; 3116164Ssam m->m_len += count; 3126164Ssam n->m_off += count; 3136164Ssam n->m_len -= count; 3145310Sroot if (n->m_len) 3155310Sroot break; 3165310Sroot n = m_free(n); 3175310Sroot } while (n); 3185310Sroot if (len) { 3195310Sroot (void) m_free(m); 3205310Sroot goto bad; 3215310Sroot } 3225310Sroot m->m_next = n; 3235310Sroot return (m); 3245310Sroot bad: 3255732Sroot m_freem(n); 3265228Swnj return (0); 3275228Swnj } 328