1*8792Sroot /* uipc_mbuf.c 1.40 82/10/21 */ 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 */ 38*8792Sroot 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; 645273Sroot m->m_free = 0; 656839Ssam mbstat.m_mbufs++; 665228Swnj (void) m_free(m); 675228Swnj m++; 685228Swnj } 695232Swnj break; 705228Swnj } 715228Swnj return ((caddr_t)m); 725228Swnj } 735228Swnj 745228Swnj m_pgfree(addr, n) 755228Swnj caddr_t addr; 765228Swnj int n; 775228Swnj { 785228Swnj 796141Ssam #ifdef lint 806141Ssam addr = addr; n = n; 816141Ssam #endif 825228Swnj } 835228Swnj 845228Swnj m_expand() 855228Swnj { 865228Swnj 875228Swnj if (m_clalloc(1, MPG_MBUFS) == 0) 885228Swnj goto steal; 895228Swnj return (1); 905228Swnj steal: 915228Swnj /* should ask protocols to free code */ 925228Swnj return (0); 935228Swnj } 945228Swnj 955228Swnj /* NEED SOME WAY TO RELEASE SPACE */ 965228Swnj 975228Swnj /* 985228Swnj * Space allocation routines. 995228Swnj * These are also available as macros 1005228Swnj * for critical paths. 1015228Swnj */ 1024585Swnj struct mbuf * 1034585Swnj m_get(canwait) 1044585Swnj int canwait; 1054585Swnj { 1064585Swnj register struct mbuf *m; 1074585Swnj 1084585Swnj MGET(m, canwait); 1094585Swnj return (m); 1104585Swnj } 1114585Swnj 1124585Swnj struct mbuf * 1134890Swnj m_getclr(canwait) 1144890Swnj int canwait; 1154890Swnj { 1164890Swnj register struct mbuf *m; 1174890Swnj 1184916Swnj m = m_get(canwait); 1194890Swnj if (m == 0) 1204890Swnj return (0); 1214890Swnj bzero(mtod(m, caddr_t), MLEN); 1224890Swnj return (m); 1234890Swnj } 1244890Swnj 1254890Swnj struct mbuf * 1264585Swnj m_free(m) 1274585Swnj struct mbuf *m; 1284585Swnj { 1294585Swnj register struct mbuf *n; 1304585Swnj 1314585Swnj MFREE(m, n); 1324585Swnj return (n); 1334585Swnj } 1344585Swnj 1354916Swnj /*ARGSUSED*/ 1364585Swnj struct mbuf * 1374585Swnj m_more(type) 1384585Swnj int type; 1394585Swnj { 1404585Swnj register struct mbuf *m; 1414585Swnj 1424585Swnj if (!m_expand()) { 1434822Swnj mbstat.m_drops++; 1444585Swnj return (NULL); 1454585Swnj } 1464916Swnj #define m_more(x) (panic("m_more"), (struct mbuf *)0) 1474916Swnj MGET(m, type); 1485282Sroot #undef m_more 1494585Swnj return (m); 1504585Swnj } 1514585Swnj 1524669Swnj m_freem(m) 1534585Swnj register struct mbuf *m; 1544585Swnj { 1554585Swnj register struct mbuf *n; 1564927Swnj register int s; 1574585Swnj 1584585Swnj if (m == NULL) 1594916Swnj return; 1604662Swnj s = splimp(); 1614585Swnj do { 1624585Swnj MFREE(m, n); 1634585Swnj } while (m = n); 1644585Swnj splx(s); 1654585Swnj } 1664585Swnj 1675228Swnj /* 1685228Swnj * Mbuffer utility routines. 1695228Swnj */ 1704927Swnj struct mbuf * 1714927Swnj m_copy(m, off, len) 1724927Swnj register struct mbuf *m; 1734927Swnj int off; 1744927Swnj register int len; 1754927Swnj { 1764927Swnj register struct mbuf *n, **np; 1774927Swnj struct mbuf *top, *p; 1784927Swnj 1794927Swnj if (len == 0) 1804927Swnj return (0); 1814927Swnj if (off < 0 || len < 0) 1824927Swnj panic("m_copy"); 1834927Swnj while (off > 0) { 1844927Swnj if (m == 0) 1854927Swnj panic("m_copy"); 1864927Swnj if (off < m->m_len) 1874927Swnj break; 1884927Swnj off -= m->m_len; 1894927Swnj m = m->m_next; 1904927Swnj } 1914927Swnj np = ⊤ 1924927Swnj top = 0; 1934927Swnj while (len > 0) { 1945609Swnj if (m == 0) { 1955609Swnj if (len != M_COPYALL) 1965609Swnj panic("m_copy"); 1975609Swnj break; 1985609Swnj } 1994927Swnj MGET(n, 1); 2004927Swnj *np = n; 2014927Swnj if (n == 0) 2024927Swnj goto nospace; 2034927Swnj n->m_len = MIN(len, m->m_len - off); 2044927Swnj if (m->m_off > MMAXOFF) { 2054927Swnj p = mtod(m, struct mbuf *); 2064927Swnj n->m_off = ((int)p - (int)n) + off; 2075090Swnj mclrefcnt[mtocl(p)]++; 2088318Sroot } else 2094927Swnj bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t), 2104927Swnj (unsigned)n->m_len); 2115609Swnj if (len != M_COPYALL) 2125609Swnj len -= n->m_len; 2134927Swnj off = 0; 2144927Swnj m = m->m_next; 2154927Swnj np = &n->m_next; 2164927Swnj } 2174927Swnj return (top); 2184927Swnj nospace: 2194927Swnj m_freem(top); 2204927Swnj return (0); 2214927Swnj } 2224927Swnj 2234669Swnj m_cat(m, n) 2244669Swnj register struct mbuf *m, *n; 2254669Swnj { 2264669Swnj while (m->m_next) 2274669Swnj m = m->m_next; 2286091Sroot while (n) { 2296091Sroot if (m->m_off >= MMAXOFF || 2306091Sroot m->m_off + m->m_len + n->m_len > MMAXOFF) { 2316091Sroot /* just join the two chains */ 2324669Swnj m->m_next = n; 2336091Sroot return; 2344669Swnj } 2356091Sroot /* splat the data from one into the other */ 2366091Sroot bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, 2376091Sroot (u_int)n->m_len); 2386091Sroot m->m_len += n->m_len; 2396091Sroot n = m_free(n); 2406091Sroot } 2414669Swnj } 2424669Swnj 2434585Swnj m_adj(mp, len) 2444585Swnj struct mbuf *mp; 2454916Swnj register int len; 2464585Swnj { 2474585Swnj register struct mbuf *m, *n; 2484585Swnj 2494585Swnj if ((m = mp) == NULL) 2504585Swnj return; 2514822Swnj if (len >= 0) { 2524585Swnj while (m != NULL && len > 0) { 2534822Swnj if (m->m_len <= len) { 2544585Swnj len -= m->m_len; 2554585Swnj m->m_len = 0; 2564585Swnj m = m->m_next; 2574822Swnj } else { 2584585Swnj m->m_len -= len; 2594585Swnj m->m_off += len; 2604585Swnj break; 2614585Swnj } 2624585Swnj } 2634822Swnj } else { 2644822Swnj /* a 2 pass algorithm might be better */ 2654585Swnj len = -len; 2664585Swnj while (len > 0 && m->m_len != 0) { 2674585Swnj while (m != NULL && m->m_len != 0) { 2684585Swnj n = m; 2694585Swnj m = m->m_next; 2704585Swnj } 2714822Swnj if (n->m_len <= len) { 2724585Swnj len -= n->m_len; 2734585Swnj n->m_len = 0; 2744585Swnj m = mp; 2754822Swnj } else { 2764585Swnj n->m_len -= len; 2774585Swnj break; 2784585Swnj } 2794585Swnj } 2804585Swnj } 2814585Swnj } 2825228Swnj 2835310Sroot struct mbuf * 2845310Sroot m_pullup(m0, len) 2855310Sroot struct mbuf *m0; 2865228Swnj int len; 2875228Swnj { 2885310Sroot register struct mbuf *m, *n; 2896164Ssam int count; 2905228Swnj 2915732Sroot n = m0; 2925310Sroot if (len > MLEN) 2935310Sroot goto bad; 2948318Sroot MGET(m, M_DONTWAIT); 2955310Sroot if (m == 0) 2965310Sroot goto bad; 2975310Sroot m->m_len = 0; 2985310Sroot do { 2996164Ssam count = MIN(MLEN - m->m_len, len); 3006164Ssam if (count > n->m_len) 3016164Ssam count = n->m_len; 3026164Ssam bcopy(mtod(n, caddr_t), mtod(m, caddr_t)+m->m_len, 3036164Ssam (unsigned)count); 3046164Ssam len -= count; 3056164Ssam m->m_len += count; 3066164Ssam n->m_off += count; 3076164Ssam n->m_len -= count; 3085310Sroot if (n->m_len) 3095310Sroot break; 3105310Sroot n = m_free(n); 3115310Sroot } while (n); 3125310Sroot if (len) { 3135310Sroot (void) m_free(m); 3145310Sroot goto bad; 3155310Sroot } 3165310Sroot m->m_next = n; 3175310Sroot return (m); 3185310Sroot bad: 3195732Sroot m_freem(n); 3205228Swnj return (0); 3215228Swnj } 322