1*6839Ssam /* uipc_mbuf.c 1.33 82/05/18 */ 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" 115090Swnj #include "../net/in_systm.h" /* XXX */ 124585Swnj #include "../h/vm.h" 134585Swnj 145228Swnj mbinit() 155228Swnj { 165228Swnj 175228Swnj COUNT(MBINIT); 185228Swnj if (m_reserve(32) == 0) 195228Swnj goto bad; 205228Swnj if (m_clalloc(4, MPG_MBUFS) == 0) 215228Swnj goto bad; 225228Swnj if (m_clalloc(32, MPG_CLUSTERS) == 0) 235228Swnj goto bad; 245228Swnj return; 255228Swnj bad: 265228Swnj panic("mbinit"); 275228Swnj } 285228Swnj 295228Swnj caddr_t 305228Swnj m_clalloc(ncl, how) 315228Swnj register int ncl; 325228Swnj int how; 335228Swnj { 345228Swnj int npg, mbx; 355228Swnj register struct mbuf *m; 365228Swnj register int i; 375228Swnj int s; 385228Swnj 395228Swnj COUNT(M_CLALLOC); 405228Swnj npg = ncl * CLSIZE; 415581Swnj s = splimp(); /* careful: rmalloc isn't reentrant */ 425228Swnj mbx = rmalloc(mbmap, npg); 435581Swnj splx(s); 445228Swnj if (mbx == 0) 455228Swnj return (0); 465228Swnj m = cltom(mbx / CLSIZE); 475228Swnj if (memall(&Mbmap[mbx], ncl * CLSIZE, proc, CSYS) == 0) 485228Swnj return (0); 495228Swnj vmaccess(&Mbmap[mbx], (caddr_t)m, npg); 505228Swnj switch (how) { 515228Swnj 525228Swnj case MPG_CLUSTERS: 535228Swnj s = splimp(); 545228Swnj for (i = 0; i < ncl; i++) { 555228Swnj m->m_off = 0; 565228Swnj m->m_next = mclfree; 575228Swnj mclfree = m; 585228Swnj m += CLBYTES / sizeof (*m); 59*6839Ssam mbstat.m_clfree++; 605228Swnj } 615228Swnj mbstat.m_clusters += ncl; 625228Swnj splx(s); 635228Swnj break; 645228Swnj 655228Swnj case MPG_MBUFS: 665228Swnj for (i = ncl * CLBYTES / sizeof (*m); i > 0; i--) { 675228Swnj m->m_off = 0; 685273Sroot m->m_free = 0; 69*6839Ssam mbstat.m_mbufs++; 705228Swnj (void) m_free(m); 715228Swnj m++; 725228Swnj } 735232Swnj break; 745228Swnj } 755228Swnj return ((caddr_t)m); 765228Swnj } 775228Swnj 785228Swnj m_pgfree(addr, n) 795228Swnj caddr_t addr; 805228Swnj int n; 815228Swnj { 825228Swnj 835228Swnj COUNT(M_PGFREE); 846141Ssam #ifdef lint 856141Ssam addr = addr; n = n; 866141Ssam #endif 875228Swnj } 885228Swnj 895228Swnj m_expand() 905228Swnj { 915228Swnj 925228Swnj COUNT(M_EXPAND); 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 reservation routines 1055228Swnj */ 1065015Sroot m_reserve(mbufs) 1075015Sroot int mbufs; 1084732Swnj { 1094732Swnj 110*6839Ssam if (mbstat.m_mbcommitted + mbufs > 111*6839Ssam (nmbclusters * NMBPCL) * MBUFOVERALLOCFRACTION) 1124732Swnj return (0); 113*6839Ssam mbstat.m_mbcommitted += mbufs; 1144916Swnj return (1); 1154732Swnj } 1164732Swnj 1175015Sroot m_release(mbufs) 1185015Sroot int mbufs; 1194732Swnj { 1204732Swnj 121*6839Ssam mbstat.m_mbcommitted -= mbufs; 1224732Swnj } 1234732Swnj 1245228Swnj /* 1255228Swnj * Space allocation routines. 1265228Swnj * These are also available as macros 1275228Swnj * for critical paths. 1285228Swnj */ 1294585Swnj struct mbuf * 1304585Swnj m_get(canwait) 1314585Swnj int canwait; 1324585Swnj { 1334585Swnj register struct mbuf *m; 1344585Swnj 1354585Swnj COUNT(M_GET); 1364585Swnj MGET(m, canwait); 1374585Swnj return (m); 1384585Swnj } 1394585Swnj 1404585Swnj struct mbuf * 1414890Swnj m_getclr(canwait) 1424890Swnj int canwait; 1434890Swnj { 1444890Swnj register struct mbuf *m; 1454890Swnj 1464890Swnj COUNT(M_GETCLR); 1474916Swnj m = m_get(canwait); 1484890Swnj if (m == 0) 1494890Swnj return (0); 1504890Swnj m->m_off = MMINOFF; 1514890Swnj bzero(mtod(m, caddr_t), MLEN); 1524890Swnj return (m); 1534890Swnj } 1544890Swnj 1554890Swnj struct mbuf * 1564585Swnj m_free(m) 1574585Swnj struct mbuf *m; 1584585Swnj { 1594585Swnj register struct mbuf *n; 1604585Swnj 1614585Swnj COUNT(M_FREE); 1624585Swnj MFREE(m, n); 1634585Swnj return (n); 1644585Swnj } 1654585Swnj 1664916Swnj /*ARGSUSED*/ 1674585Swnj struct mbuf * 1684585Swnj m_more(type) 1694585Swnj int type; 1704585Swnj { 1714585Swnj register struct mbuf *m; 1724585Swnj 1734585Swnj COUNT(M_MORE); 1744585Swnj if (!m_expand()) { 1754822Swnj mbstat.m_drops++; 1764585Swnj return (NULL); 1774585Swnj } 1784916Swnj #define m_more(x) (panic("m_more"), (struct mbuf *)0) 1794916Swnj MGET(m, type); 1805282Sroot #undef m_more 1814585Swnj return (m); 1824585Swnj } 1834585Swnj 1844669Swnj m_freem(m) 1854585Swnj register struct mbuf *m; 1864585Swnj { 1874585Swnj register struct mbuf *n; 1884927Swnj register int s; 1894585Swnj 1904585Swnj COUNT(M_FREEM); 1914585Swnj if (m == NULL) 1924916Swnj return; 1934662Swnj s = splimp(); 1944585Swnj do { 1954585Swnj MFREE(m, n); 1964585Swnj } while (m = n); 1974585Swnj splx(s); 1984585Swnj } 1994585Swnj 2005228Swnj /* 2015228Swnj * Mbuffer utility routines. 2025228Swnj */ 2034927Swnj struct mbuf * 2044927Swnj m_copy(m, off, len) 2054927Swnj register struct mbuf *m; 2064927Swnj int off; 2074927Swnj register int len; 2084927Swnj { 2094927Swnj register struct mbuf *n, **np; 2104927Swnj struct mbuf *top, *p; 2114927Swnj COUNT(M_COPY); 2124927Swnj 2134927Swnj if (len == 0) 2144927Swnj return (0); 2154927Swnj if (off < 0 || len < 0) 2164927Swnj panic("m_copy"); 2174927Swnj while (off > 0) { 2184927Swnj if (m == 0) 2194927Swnj panic("m_copy"); 2204927Swnj if (off < m->m_len) 2214927Swnj break; 2224927Swnj off -= m->m_len; 2234927Swnj m = m->m_next; 2244927Swnj } 2254927Swnj np = ⊤ 2264927Swnj top = 0; 2274927Swnj while (len > 0) { 2285609Swnj if (m == 0) { 2295609Swnj if (len != M_COPYALL) 2305609Swnj panic("m_copy"); 2315609Swnj break; 2325609Swnj } 2334927Swnj MGET(n, 1); 2344927Swnj *np = n; 2354927Swnj if (n == 0) 2364927Swnj goto nospace; 2374927Swnj n->m_len = MIN(len, m->m_len - off); 2384927Swnj if (m->m_off > MMAXOFF) { 2394927Swnj p = mtod(m, struct mbuf *); 2404927Swnj n->m_off = ((int)p - (int)n) + off; 2415090Swnj mclrefcnt[mtocl(p)]++; 2424927Swnj } else { 2434927Swnj n->m_off = MMINOFF; 2444927Swnj bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t), 2454927Swnj (unsigned)n->m_len); 2464927Swnj } 2475609Swnj if (len != M_COPYALL) 2485609Swnj len -= n->m_len; 2494927Swnj off = 0; 2504927Swnj m = m->m_next; 2514927Swnj np = &n->m_next; 2524927Swnj } 2534927Swnj return (top); 2544927Swnj nospace: 2554927Swnj m_freem(top); 2564927Swnj return (0); 2574927Swnj } 2584927Swnj 2594669Swnj m_cat(m, n) 2604669Swnj register struct mbuf *m, *n; 2614669Swnj { 2624669Swnj while (m->m_next) 2634669Swnj m = m->m_next; 2646091Sroot while (n) { 2656091Sroot if (m->m_off >= MMAXOFF || 2666091Sroot m->m_off + m->m_len + n->m_len > MMAXOFF) { 2676091Sroot /* just join the two chains */ 2684669Swnj m->m_next = n; 2696091Sroot return; 2704669Swnj } 2716091Sroot /* splat the data from one into the other */ 2726091Sroot bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, 2736091Sroot (u_int)n->m_len); 2746091Sroot m->m_len += n->m_len; 2756091Sroot n = m_free(n); 2766091Sroot } 2774669Swnj } 2784669Swnj 2794585Swnj m_adj(mp, len) 2804585Swnj struct mbuf *mp; 2814916Swnj register int len; 2824585Swnj { 2834585Swnj register struct mbuf *m, *n; 2844585Swnj 2854585Swnj COUNT(M_ADJ); 2864585Swnj if ((m = mp) == NULL) 2874585Swnj return; 2884822Swnj if (len >= 0) { 2894585Swnj while (m != NULL && len > 0) { 2904822Swnj if (m->m_len <= len) { 2914585Swnj len -= m->m_len; 2924585Swnj m->m_len = 0; 2934585Swnj m = m->m_next; 2944822Swnj } else { 2954585Swnj m->m_len -= len; 2964585Swnj m->m_off += len; 2974585Swnj break; 2984585Swnj } 2994585Swnj } 3004822Swnj } else { 3014822Swnj /* a 2 pass algorithm might be better */ 3024585Swnj len = -len; 3034585Swnj while (len > 0 && m->m_len != 0) { 3044585Swnj while (m != NULL && m->m_len != 0) { 3054585Swnj n = m; 3064585Swnj m = m->m_next; 3074585Swnj } 3084822Swnj if (n->m_len <= len) { 3094585Swnj len -= n->m_len; 3104585Swnj n->m_len = 0; 3114585Swnj m = mp; 3124822Swnj } else { 3134585Swnj n->m_len -= len; 3144585Swnj break; 3154585Swnj } 3164585Swnj } 3174585Swnj } 3184585Swnj } 3195228Swnj 3205310Sroot struct mbuf * 3215310Sroot m_pullup(m0, len) 3225310Sroot struct mbuf *m0; 3235228Swnj int len; 3245228Swnj { 3255310Sroot register struct mbuf *m, *n; 3266164Ssam int count; 3275228Swnj 3285732Sroot n = m0; 3295310Sroot if (len > MLEN) 3305310Sroot goto bad; 3315310Sroot MGET(m, 0); 3325310Sroot if (m == 0) 3335310Sroot goto bad; 3345310Sroot m->m_off = MMINOFF; 3355310Sroot m->m_len = 0; 3365310Sroot do { 3376164Ssam count = MIN(MLEN - m->m_len, len); 3386164Ssam if (count > n->m_len) 3396164Ssam count = n->m_len; 3406164Ssam bcopy(mtod(n, caddr_t), mtod(m, caddr_t)+m->m_len, 3416164Ssam (unsigned)count); 3426164Ssam len -= count; 3436164Ssam m->m_len += count; 3446164Ssam n->m_off += count; 3456164Ssam n->m_len -= count; 3465310Sroot if (n->m_len) 3475310Sroot break; 3485310Sroot n = m_free(n); 3495310Sroot } while (n); 3505310Sroot if (len) { 3515310Sroot (void) m_free(m); 3525310Sroot goto bad; 3535310Sroot } 3545310Sroot m->m_next = n; 3555310Sroot return (m); 3565310Sroot bad: 3575732Sroot m_freem(n); 3585228Swnj return (0); 3595228Swnj } 360