1*9634Ssam /* uipc_mbuf.c 1.41 82/12/14 */ 24585Swnj 34585Swnj #include "../h/param.h" 44585Swnj #include "../h/dir.h" 54585Swnj #include "../h/user.h" 64585Swnj #include "../h/proc.h" 74585Swnj #include "../h/pte.h" 84585Swnj #include "../h/cmap.h" 94585Swnj #include "../h/map.h" 104641Swnj #include "../h/mbuf.h" 114585Swnj #include "../h/vm.h" 128770Sroot #include "../h/kernel.h" 134585Swnj 145228Swnj mbinit() 155228Swnj { 165228Swnj 175228Swnj if (m_clalloc(4, MPG_MBUFS) == 0) 185228Swnj goto bad; 195228Swnj if (m_clalloc(32, MPG_CLUSTERS) == 0) 205228Swnj goto bad; 215228Swnj return; 225228Swnj bad: 235228Swnj panic("mbinit"); 245228Swnj } 255228Swnj 265228Swnj caddr_t 275228Swnj m_clalloc(ncl, how) 285228Swnj register int ncl; 295228Swnj int how; 305228Swnj { 315228Swnj int npg, mbx; 325228Swnj register struct mbuf *m; 335228Swnj register int i; 345228Swnj int s; 355228Swnj 365228Swnj npg = ncl * CLSIZE; 375581Swnj s = splimp(); /* careful: rmalloc isn't reentrant */ 388792Sroot mbx = rmalloc(mbmap, (long)npg); 395581Swnj splx(s); 405228Swnj if (mbx == 0) 415228Swnj return (0); 425228Swnj m = cltom(mbx / CLSIZE); 436850Ssam if (memall(&Mbmap[mbx], npg, proc, CSYS) == 0) 445228Swnj return (0); 455228Swnj vmaccess(&Mbmap[mbx], (caddr_t)m, npg); 465228Swnj switch (how) { 475228Swnj 485228Swnj case MPG_CLUSTERS: 495228Swnj s = splimp(); 505228Swnj for (i = 0; i < ncl; i++) { 515228Swnj m->m_off = 0; 525228Swnj m->m_next = mclfree; 535228Swnj mclfree = m; 545228Swnj m += CLBYTES / sizeof (*m); 556839Ssam mbstat.m_clfree++; 565228Swnj } 575228Swnj mbstat.m_clusters += ncl; 585228Swnj splx(s); 595228Swnj break; 605228Swnj 615228Swnj case MPG_MBUFS: 625228Swnj for (i = ncl * CLBYTES / sizeof (*m); i > 0; i--) { 635228Swnj m->m_off = 0; 64*9634Ssam m->m_type = MT_DATA; 65*9634Ssam mbstat.m_mtypes[MT_DATA]++; 666839Ssam mbstat.m_mbufs++; 675228Swnj (void) m_free(m); 685228Swnj m++; 695228Swnj } 705232Swnj break; 715228Swnj } 725228Swnj return ((caddr_t)m); 735228Swnj } 745228Swnj 755228Swnj m_pgfree(addr, n) 765228Swnj caddr_t addr; 775228Swnj int n; 785228Swnj { 795228Swnj 806141Ssam #ifdef lint 816141Ssam addr = addr; n = n; 826141Ssam #endif 835228Swnj } 845228Swnj 855228Swnj m_expand() 865228Swnj { 875228Swnj 885228Swnj if (m_clalloc(1, MPG_MBUFS) == 0) 895228Swnj goto steal; 905228Swnj return (1); 915228Swnj steal: 925228Swnj /* should ask protocols to free code */ 935228Swnj return (0); 945228Swnj } 955228Swnj 965228Swnj /* NEED SOME WAY TO RELEASE SPACE */ 975228Swnj 985228Swnj /* 995228Swnj * Space allocation routines. 1005228Swnj * These are also available as macros 1015228Swnj * for critical paths. 1025228Swnj */ 1034585Swnj struct mbuf * 104*9634Ssam m_get(canwait, type) 105*9634Ssam int canwait, type; 1064585Swnj { 1074585Swnj register struct mbuf *m; 1084585Swnj 109*9634Ssam MGET(m, canwait, type); 1104585Swnj return (m); 1114585Swnj } 1124585Swnj 1134585Swnj struct mbuf * 114*9634Ssam m_getclr(canwait, type) 115*9634Ssam int canwait, type; 1164890Swnj { 1174890Swnj register struct mbuf *m; 1184890Swnj 119*9634Ssam m = m_get(canwait, type); 1204890Swnj if (m == 0) 1214890Swnj return (0); 1224890Swnj bzero(mtod(m, caddr_t), MLEN); 1234890Swnj return (m); 1244890Swnj } 1254890Swnj 1264890Swnj struct mbuf * 1274585Swnj m_free(m) 1284585Swnj struct mbuf *m; 1294585Swnj { 1304585Swnj register struct mbuf *n; 1314585Swnj 1324585Swnj MFREE(m, n); 1334585Swnj return (n); 1344585Swnj } 1354585Swnj 1364916Swnj /*ARGSUSED*/ 1374585Swnj struct mbuf * 138*9634Ssam m_more(canwait, type) 139*9634Ssam int canwait, type; 1404585Swnj { 1414585Swnj register struct mbuf *m; 1424585Swnj 1434585Swnj if (!m_expand()) { 1444822Swnj mbstat.m_drops++; 1454585Swnj return (NULL); 1464585Swnj } 147*9634Ssam #define m_more(x,y) (panic("m_more"), (struct mbuf *)0) 148*9634Ssam MGET(m, canwait, type); 1495282Sroot #undef m_more 1504585Swnj return (m); 1514585Swnj } 1524585Swnj 1534669Swnj m_freem(m) 1544585Swnj register struct mbuf *m; 1554585Swnj { 1564585Swnj register struct mbuf *n; 1574927Swnj register int s; 1584585Swnj 1594585Swnj if (m == NULL) 1604916Swnj return; 1614662Swnj s = splimp(); 1624585Swnj do { 1634585Swnj MFREE(m, n); 1644585Swnj } while (m = n); 1654585Swnj splx(s); 1664585Swnj } 1674585Swnj 1685228Swnj /* 1695228Swnj * Mbuffer utility routines. 1705228Swnj */ 1714927Swnj struct mbuf * 1724927Swnj m_copy(m, off, len) 1734927Swnj register struct mbuf *m; 1744927Swnj int off; 1754927Swnj register int len; 1764927Swnj { 1774927Swnj register struct mbuf *n, **np; 1784927Swnj struct mbuf *top, *p; 179*9634Ssam int type; 1804927Swnj 1814927Swnj if (len == 0) 1824927Swnj return (0); 1834927Swnj if (off < 0 || len < 0) 1844927Swnj panic("m_copy"); 185*9634Ssam type = m->m_type; 1864927Swnj while (off > 0) { 1874927Swnj if (m == 0) 1884927Swnj panic("m_copy"); 1894927Swnj if (off < m->m_len) 1904927Swnj break; 1914927Swnj off -= m->m_len; 1924927Swnj m = m->m_next; 1934927Swnj } 1944927Swnj np = ⊤ 1954927Swnj top = 0; 1964927Swnj while (len > 0) { 1975609Swnj if (m == 0) { 1985609Swnj if (len != M_COPYALL) 1995609Swnj panic("m_copy"); 2005609Swnj break; 2015609Swnj } 202*9634Ssam MGET(n, M_WAIT, type); 2034927Swnj *np = n; 2044927Swnj if (n == 0) 2054927Swnj goto nospace; 2064927Swnj n->m_len = MIN(len, m->m_len - off); 2074927Swnj if (m->m_off > MMAXOFF) { 2084927Swnj p = mtod(m, struct mbuf *); 2094927Swnj n->m_off = ((int)p - (int)n) + off; 2105090Swnj mclrefcnt[mtocl(p)]++; 2118318Sroot } else 2124927Swnj bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t), 2134927Swnj (unsigned)n->m_len); 2145609Swnj if (len != M_COPYALL) 2155609Swnj len -= n->m_len; 2164927Swnj off = 0; 2174927Swnj m = m->m_next; 2184927Swnj np = &n->m_next; 2194927Swnj } 2204927Swnj return (top); 2214927Swnj nospace: 2224927Swnj m_freem(top); 2234927Swnj return (0); 2244927Swnj } 2254927Swnj 2264669Swnj m_cat(m, n) 2274669Swnj register struct mbuf *m, *n; 2284669Swnj { 2294669Swnj while (m->m_next) 2304669Swnj m = m->m_next; 2316091Sroot while (n) { 2326091Sroot if (m->m_off >= MMAXOFF || 2336091Sroot m->m_off + m->m_len + n->m_len > MMAXOFF) { 2346091Sroot /* just join the two chains */ 2354669Swnj m->m_next = n; 2366091Sroot return; 2374669Swnj } 2386091Sroot /* splat the data from one into the other */ 2396091Sroot bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, 2406091Sroot (u_int)n->m_len); 2416091Sroot m->m_len += n->m_len; 2426091Sroot n = m_free(n); 2436091Sroot } 2444669Swnj } 2454669Swnj 2464585Swnj m_adj(mp, len) 2474585Swnj struct mbuf *mp; 2484916Swnj register int len; 2494585Swnj { 2504585Swnj register struct mbuf *m, *n; 2514585Swnj 2524585Swnj if ((m = mp) == NULL) 2534585Swnj return; 2544822Swnj if (len >= 0) { 2554585Swnj while (m != NULL && len > 0) { 2564822Swnj if (m->m_len <= len) { 2574585Swnj len -= m->m_len; 2584585Swnj m->m_len = 0; 2594585Swnj m = m->m_next; 2604822Swnj } else { 2614585Swnj m->m_len -= len; 2624585Swnj m->m_off += len; 2634585Swnj break; 2644585Swnj } 2654585Swnj } 2664822Swnj } else { 2674822Swnj /* a 2 pass algorithm might be better */ 2684585Swnj len = -len; 2694585Swnj while (len > 0 && m->m_len != 0) { 2704585Swnj while (m != NULL && m->m_len != 0) { 2714585Swnj n = m; 2724585Swnj m = m->m_next; 2734585Swnj } 2744822Swnj if (n->m_len <= len) { 2754585Swnj len -= n->m_len; 2764585Swnj n->m_len = 0; 2774585Swnj m = mp; 2784822Swnj } else { 2794585Swnj n->m_len -= len; 2804585Swnj break; 2814585Swnj } 2824585Swnj } 2834585Swnj } 2844585Swnj } 2855228Swnj 2865310Sroot struct mbuf * 2875310Sroot m_pullup(m0, len) 2885310Sroot struct mbuf *m0; 2895228Swnj int len; 2905228Swnj { 2915310Sroot register struct mbuf *m, *n; 2926164Ssam int count; 2935228Swnj 2945732Sroot n = m0; 2955310Sroot if (len > MLEN) 2965310Sroot goto bad; 297*9634Ssam MGET(m, M_DONTWAIT, n->m_type); 2985310Sroot if (m == 0) 2995310Sroot goto bad; 3005310Sroot m->m_len = 0; 3015310Sroot do { 3026164Ssam count = MIN(MLEN - m->m_len, len); 3036164Ssam if (count > n->m_len) 3046164Ssam count = n->m_len; 3056164Ssam bcopy(mtod(n, caddr_t), mtod(m, caddr_t)+m->m_len, 3066164Ssam (unsigned)count); 3076164Ssam len -= count; 3086164Ssam m->m_len += count; 3096164Ssam n->m_off += count; 3106164Ssam n->m_len -= count; 3115310Sroot if (n->m_len) 3125310Sroot break; 3135310Sroot n = m_free(n); 3145310Sroot } while (n); 3155310Sroot if (len) { 3165310Sroot (void) m_free(m); 3175310Sroot goto bad; 3185310Sroot } 3195310Sroot m->m_next = n; 3205310Sroot return (m); 3215310Sroot bad: 3225732Sroot m_freem(n); 3235228Swnj return (0); 3245228Swnj } 325