1*5609Swnj /* uipc_mbuf.c 1.27 82/01/24 */ 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); 595228Swnj nmclfree++; 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; 695228Swnj (void) m_free(m); 705228Swnj m++; 715228Swnj } 725228Swnj mbstat.m_clusters += ncl; 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); 845228Swnj } 855228Swnj 865228Swnj m_expand() 875228Swnj { 885228Swnj 895228Swnj COUNT(M_EXPAND); 905228Swnj if (mbstat.m_bufs >= mbstat.m_hiwat) 915228Swnj return (0); 925228Swnj if (m_clalloc(1, MPG_MBUFS) == 0) 935228Swnj goto steal; 945228Swnj return (1); 955228Swnj steal: 965228Swnj /* should ask protocols to free code */ 975228Swnj return (0); 985228Swnj } 995228Swnj 1005228Swnj /* NEED SOME WAY TO RELEASE SPACE */ 1015228Swnj 1025228Swnj /* 1035228Swnj * Space reservation routines 1045228Swnj */ 1055015Sroot m_reserve(mbufs) 1065015Sroot int mbufs; 1074732Swnj { 1084732Swnj 1095147Swnj if (mbstat.m_lowat + (mbufs>>1) > (NMBCLUSTERS-32) * CLBYTES) 1104732Swnj return (0); 1115016Swnj mbstat.m_hiwat += mbufs; 1125016Swnj mbstat.m_lowat = mbstat.m_hiwat >> 1; 1134916Swnj return (1); 1144732Swnj } 1154732Swnj 1165015Sroot m_release(mbufs) 1175015Sroot int mbufs; 1184732Swnj { 1194732Swnj 1205016Swnj mbstat.m_hiwat -= mbufs; 1215016Swnj mbstat.m_lowat = mbstat.m_hiwat >> 1; 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) { 228*5609Swnj if (m == 0) { 229*5609Swnj if (len != M_COPYALL) 230*5609Swnj panic("m_copy"); 231*5609Swnj break; 232*5609Swnj } 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 } 247*5609Swnj if (len != M_COPYALL) 248*5609Swnj 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 2634669Swnj while (m->m_next) 2644669Swnj m = m->m_next; 2654669Swnj while (n) 2664669Swnj if (m->m_off + m->m_len + n->m_len <= MMAXOFF) { 2674916Swnj bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, 2684916Swnj (u_int)n->m_len); 2694669Swnj m->m_len += n->m_len; 2704669Swnj n = m_free(n); 2714669Swnj } else { 2724669Swnj m->m_next = n; 2734669Swnj m = n; 2744669Swnj n = m->m_next; 2754669Swnj } 2764669Swnj } 2774669Swnj 2784585Swnj m_adj(mp, len) 2794585Swnj struct mbuf *mp; 2804916Swnj register int len; 2814585Swnj { 2824585Swnj register struct mbuf *m, *n; 2834585Swnj 2844585Swnj COUNT(M_ADJ); 2854585Swnj if ((m = mp) == NULL) 2864585Swnj return; 2874822Swnj if (len >= 0) { 2884585Swnj while (m != NULL && len > 0) { 2894822Swnj if (m->m_len <= len) { 2904585Swnj len -= m->m_len; 2914585Swnj m->m_len = 0; 2924585Swnj m = m->m_next; 2934822Swnj } else { 2944585Swnj m->m_len -= len; 2954585Swnj m->m_off += len; 2964585Swnj break; 2974585Swnj } 2984585Swnj } 2994822Swnj } else { 3004822Swnj /* a 2 pass algorithm might be better */ 3014585Swnj len = -len; 3024585Swnj while (len > 0 && m->m_len != 0) { 3034585Swnj while (m != NULL && m->m_len != 0) { 3044585Swnj n = m; 3054585Swnj m = m->m_next; 3064585Swnj } 3074822Swnj if (n->m_len <= len) { 3084585Swnj len -= n->m_len; 3094585Swnj n->m_len = 0; 3104585Swnj m = mp; 3114822Swnj } else { 3124585Swnj n->m_len -= len; 3134585Swnj break; 3144585Swnj } 3154585Swnj } 3164585Swnj } 3174585Swnj } 3185228Swnj 3195310Sroot struct mbuf * 3205310Sroot m_pullup(m0, len) 3215310Sroot struct mbuf *m0; 3225228Swnj int len; 3235228Swnj { 3245310Sroot register struct mbuf *m, *n; 3255310Sroot int cnt; 3265228Swnj 3275310Sroot if (len > MLEN) 3285310Sroot goto bad; 3295310Sroot MGET(m, 0); 3305310Sroot if (m == 0) 3315310Sroot goto bad; 3325310Sroot m->m_off = MMINOFF; 3335310Sroot m->m_len = 0; 3345310Sroot n = m0; 3355310Sroot do { 3365310Sroot cnt = MIN(MLEN - m->m_len, len); 3375310Sroot if (cnt > n->m_len) 3385310Sroot cnt = n->m_len; 3395310Sroot bcopy(mtod(n, caddr_t), mtod(m, caddr_t)+m->m_len, cnt); 3405310Sroot len -= cnt; 3415310Sroot m->m_len += cnt; 3425310Sroot n->m_off += cnt; 3435310Sroot n->m_len -= cnt; 3445310Sroot if (n->m_len) 3455310Sroot break; 3465310Sroot n = m_free(n); 3475310Sroot } while (n); 3485310Sroot if (len) { 3495310Sroot (void) m_free(m); 3505310Sroot goto bad; 3515310Sroot } 3525310Sroot m->m_next = n; 3535310Sroot return (m); 3545310Sroot bad: 3555310Sroot m_freem(m0); 3565228Swnj return (0); 3575228Swnj } 358