1*4927Swnj /* uipc_mbuf.c 1.11 81/11/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" 114916Swnj #include "../net/inet_systm.h" /* XXX */ 124585Swnj #include "../h/vm.h" 134585Swnj 144732Swnj m_reserve(mbufs) 154732Swnj int mbufs; 164732Swnj { 174732Swnj 184822Swnj if (mbstat.m_lowat + mbufs > NMBPAGES * NMBPG - 32) 194732Swnj return (0); 204732Swnj mbstat.m_lowat += mbufs; 214732Swnj mbstat.m_hiwat = 2 * mbstat.m_lowat; 224916Swnj return (1); 234732Swnj } 244732Swnj 254732Swnj m_release(mbufs) 264732Swnj int mbufs; 274732Swnj { 284732Swnj 294732Swnj mbstat.m_lowat -= mbufs; 304732Swnj mbstat.m_hiwat = 2 * mbstat.m_lowat; 314732Swnj } 324732Swnj 334585Swnj struct mbuf * 344585Swnj m_get(canwait) 354585Swnj int canwait; 364585Swnj { 374585Swnj register struct mbuf *m; 384585Swnj 394585Swnj COUNT(M_GET); 404585Swnj MGET(m, canwait); 414585Swnj return (m); 424585Swnj } 434585Swnj 444585Swnj struct mbuf * 454890Swnj m_getclr(canwait) 464890Swnj int canwait; 474890Swnj { 484890Swnj register struct mbuf *m; 494890Swnj 504890Swnj COUNT(M_GETCLR); 514916Swnj m = m_get(canwait); 524890Swnj if (m == 0) 534890Swnj return (0); 544890Swnj m->m_off = MMINOFF; 554890Swnj bzero(mtod(m, caddr_t), MLEN); 564890Swnj return (m); 574890Swnj } 584890Swnj 594890Swnj struct mbuf * 604585Swnj m_free(m) 614585Swnj struct mbuf *m; 624585Swnj { 634585Swnj register struct mbuf *n; 644585Swnj 654585Swnj COUNT(M_FREE); 664585Swnj MFREE(m, n); 674585Swnj return (n); 684585Swnj } 694585Swnj 704916Swnj /*ARGSUSED*/ 714585Swnj struct mbuf * 724585Swnj m_more(type) 734585Swnj int type; 744585Swnj { 754585Swnj register struct mbuf *m; 764585Swnj 774585Swnj COUNT(M_MORE); 784585Swnj if (!m_expand()) { 794822Swnj mbstat.m_drops++; 804585Swnj return (NULL); 814585Swnj } 824916Swnj #define m_more(x) (panic("m_more"), (struct mbuf *)0) 834916Swnj MGET(m, type); 844585Swnj return (m); 854585Swnj } 864585Swnj 874669Swnj m_freem(m) 884585Swnj register struct mbuf *m; 894585Swnj { 904585Swnj register struct mbuf *n; 91*4927Swnj register int s; 924585Swnj 934585Swnj COUNT(M_FREEM); 944585Swnj if (m == NULL) 954916Swnj return; 964662Swnj s = splimp(); 974585Swnj do { 984585Swnj MFREE(m, n); 994585Swnj } while (m = n); 1004585Swnj splx(s); 1014585Swnj } 1024585Swnj 103*4927Swnj m_pullup(m, len) 104*4927Swnj struct mbuf *m; 105*4927Swnj int len; 106*4927Swnj { 107*4927Swnj 108*4927Swnj return (0); 109*4927Swnj } 110*4927Swnj 111*4927Swnj struct mbuf * 112*4927Swnj m_copy(m, off, len) 113*4927Swnj register struct mbuf *m; 114*4927Swnj int off; 115*4927Swnj register int len; 116*4927Swnj { 117*4927Swnj register struct mbuf *n, **np; 118*4927Swnj struct mbuf *top, *p; 119*4927Swnj COUNT(M_COPY); 120*4927Swnj 121*4927Swnj if (len == 0) 122*4927Swnj return (0); 123*4927Swnj if (off < 0 || len < 0) 124*4927Swnj panic("m_copy"); 125*4927Swnj while (off > 0) { 126*4927Swnj if (m == 0) 127*4927Swnj panic("m_copy"); 128*4927Swnj if (off < m->m_len) 129*4927Swnj break; 130*4927Swnj off -= m->m_len; 131*4927Swnj m = m->m_next; 132*4927Swnj } 133*4927Swnj np = ⊤ 134*4927Swnj top = 0; 135*4927Swnj while (len > 0) { 136*4927Swnj MGET(n, 1); 137*4927Swnj *np = n; 138*4927Swnj if (n == 0) 139*4927Swnj goto nospace; 140*4927Swnj if (m == 0) 141*4927Swnj panic("m_copy"); 142*4927Swnj n->m_len = MIN(len, m->m_len - off); 143*4927Swnj if (m->m_off > MMAXOFF) { 144*4927Swnj p = mtod(m, struct mbuf *); 145*4927Swnj n->m_off = ((int)p - (int)n) + off; 146*4927Swnj mprefcnt[mtopf(p)]++; 147*4927Swnj } else { 148*4927Swnj n->m_off = MMINOFF; 149*4927Swnj bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t), 150*4927Swnj (unsigned)n->m_len); 151*4927Swnj } 152*4927Swnj len -= n->m_len; 153*4927Swnj off = 0; 154*4927Swnj m = m->m_next; 155*4927Swnj np = &n->m_next; 156*4927Swnj } 157*4927Swnj return (top); 158*4927Swnj nospace: 159*4927Swnj printf("m_copy: no space\n"); 160*4927Swnj m_freem(top); 161*4927Swnj return (0); 162*4927Swnj } 163*4927Swnj 1644822Swnj mbinit() 1654585Swnj { 1664585Swnj register struct mbuf *m; 1674585Swnj register i; 1684585Swnj 1694585Swnj COUNT(MBUFINIT); 1704822Swnj m = (struct mbuf *)&mbutl[0]; /* ->start of buffer virt mem */ 1714916Swnj (void) vmemall(&Mbmap[0], 2, proc, CSYS); 1724916Swnj vmaccess(&Mbmap[0], (caddr_t)m, 2); 1734585Swnj for (i=0; i < NMBPG; i++) { 1744587Swnj m->m_off = 0; 1754585Swnj m_free(m); 1764585Swnj m++; 1774585Swnj } 1784916Swnj (void) pg_alloc(3); 1794662Swnj mbstat.m_pages = 4; 1804662Swnj mbstat.m_bufs = 32; 1814662Swnj mbstat.m_lowat = 16; 1824662Swnj mbstat.m_hiwat = 32; 1834916Swnj { int j,k,n; 1844669Swnj n = 32; 1854669Swnj k = n << 1; 1864822Swnj if ((i = rmalloc(mbmap, n)) == 0) 1874916Swnj panic("mbinit"); 1884669Swnj j = i<<1; 1894669Swnj m = pftom(i); 1904669Swnj /* should use vmemall sometimes */ 1914822Swnj if (memall(&Mbmap[j], k, proc, CSYS) == 0) { 1924669Swnj printf("botch\n"); 1934669Swnj return; 1944669Swnj } 1954822Swnj vmaccess(&Mbmap[j], (caddr_t)m, k); 1964669Swnj for (j=0; j < n; j++) { 1974669Swnj m->m_off = 0; 1984669Swnj m->m_next = mpfree; 1994669Swnj mpfree = m; 2004669Swnj m += NMBPG; 2014669Swnj nmpfree++; 2024669Swnj } 2034669Swnj } 2044585Swnj } 2054585Swnj 2064585Swnj pg_alloc(n) 2074585Swnj register int n; 2084585Swnj { 2094585Swnj register i, j, k; 2104585Swnj register struct mbuf *m; 2114585Swnj int bufs, s; 2124585Swnj 2134585Swnj COUNT(PG_ALLOC); 2144585Swnj k = n << 1; 2154822Swnj if ((i = rmalloc(mbmap, n)) == 0) 2164585Swnj return (0); 2174585Swnj j = i<<1; 2184585Swnj m = pftom(i); 2194585Swnj /* should use vmemall sometimes */ 2204822Swnj if (memall(&Mbmap[j], k, proc, CSYS) == 0) 2214585Swnj return (0); 2224822Swnj vmaccess(&Mbmap[j], (caddr_t)m, k); 2234585Swnj bufs = n << 3; 2244662Swnj s = splimp(); 2254585Swnj for (j=0; j < bufs; j++) { 2264587Swnj m->m_off = 0; 2274585Swnj m_free(m); 2284585Swnj m++; 2294585Swnj } 2304585Swnj splx(s); 2314662Swnj mbstat.m_pages += n; 2324585Swnj return (1); 2334585Swnj } 2344585Swnj 2354585Swnj m_expand() 2364585Swnj { 2374585Swnj register i; 2384585Swnj int need, needp, needs; 2394585Swnj 2404585Swnj COUNT(M_EXPAND); 2414662Swnj needs = need = mbstat.m_hiwat - mbstat.m_bufs; 2424662Swnj needp = need >> 3; 2434585Swnj if (pg_alloc(needp)) 2444585Swnj return (1); 2454669Swnj for (i=0; i < needp; i++, need -= NMBPG) 2464669Swnj if (pg_alloc(1) == 0) 2474585Swnj goto steal; 2484585Swnj return (need < needs); 2494585Swnj steal: 2504669Swnj /* while (not enough) ask protocols to free code */ 2514669Swnj ; 2524916Swnj return (0); 2534585Swnj } 2544585Swnj 2554585Swnj #ifdef notdef 2564585Swnj m_relse() 2574585Swnj { 2584669Swnj 2594662Swnj COUNT(M_RELSE); 2604585Swnj } 2614585Swnj #endif 2624585Swnj 2634669Swnj m_cat(m, n) 2644669Swnj register struct mbuf *m, *n; 2654669Swnj { 2664669Swnj 2674669Swnj while (m->m_next) 2684669Swnj m = m->m_next; 2694669Swnj while (n) 2704669Swnj if (m->m_off + m->m_len + n->m_len <= MMAXOFF) { 2714916Swnj bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, 2724916Swnj (u_int)n->m_len); 2734669Swnj m->m_len += n->m_len; 2744669Swnj n = m_free(n); 2754669Swnj } else { 2764669Swnj m->m_next = n; 2774669Swnj m = n; 2784669Swnj n = m->m_next; 2794669Swnj } 2804669Swnj } 2814669Swnj 2824585Swnj m_adj(mp, len) 2834585Swnj struct mbuf *mp; 2844916Swnj register int len; 2854585Swnj { 2864585Swnj register struct mbuf *m, *n; 2874585Swnj 2884585Swnj COUNT(M_ADJ); 2894585Swnj if ((m = mp) == NULL) 2904585Swnj return; 2914822Swnj if (len >= 0) { 2924585Swnj while (m != NULL && len > 0) { 2934822Swnj if (m->m_len <= len) { 2944585Swnj len -= m->m_len; 2954585Swnj m->m_len = 0; 2964585Swnj m = m->m_next; 2974822Swnj } else { 2984585Swnj m->m_len -= len; 2994585Swnj m->m_off += len; 3004585Swnj break; 3014585Swnj } 3024585Swnj } 3034822Swnj } else { 3044822Swnj /* a 2 pass algorithm might be better */ 3054585Swnj len = -len; 3064585Swnj while (len > 0 && m->m_len != 0) { 3074585Swnj while (m != NULL && m->m_len != 0) { 3084585Swnj n = m; 3094585Swnj m = m->m_next; 3104585Swnj } 3114822Swnj if (n->m_len <= len) { 3124585Swnj len -= n->m_len; 3134585Swnj n->m_len = 0; 3144585Swnj m = mp; 3154822Swnj } else { 3164585Swnj n->m_len -= len; 3174585Swnj break; 3184585Swnj } 3194585Swnj } 3204585Swnj } 3214585Swnj } 322