xref: /csrg-svn/sys/kern/uipc_mbuf.c (revision 5310)
1*5310Sroot /*	uipc_mbuf.c	1.25	81/12/23	*/
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;
415228Swnj 	mbx = rmalloc(mbmap, npg);
425228Swnj 	if (mbx == 0)
435228Swnj 		return (0);
445228Swnj 	m = cltom(mbx / CLSIZE);
455228Swnj 	if (memall(&Mbmap[mbx], ncl * CLSIZE, proc, CSYS) == 0)
465228Swnj 		return (0);
475228Swnj 	vmaccess(&Mbmap[mbx], (caddr_t)m, npg);
485228Swnj 	switch (how) {
495228Swnj 
505228Swnj 	case MPG_CLUSTERS:
515228Swnj 		s = splimp();
525228Swnj 		for (i = 0; i < ncl; i++) {
535228Swnj 			m->m_off = 0;
545228Swnj 			m->m_next = mclfree;
555228Swnj 			mclfree = m;
565228Swnj 			m += CLBYTES / sizeof (*m);
575228Swnj 			nmclfree++;
585228Swnj 		}
595228Swnj 		mbstat.m_clusters += ncl;
605228Swnj 		splx(s);
615228Swnj 		break;
625228Swnj 
635228Swnj 	case MPG_MBUFS:
645228Swnj 		for (i = ncl * CLBYTES / sizeof (*m); i > 0; i--) {
655228Swnj 			m->m_off = 0;
665273Sroot 			m->m_free = 0;
675228Swnj 			(void) m_free(m);
685228Swnj 			m++;
695228Swnj 		}
705228Swnj 		mbstat.m_clusters += ncl;
715232Swnj 		break;
725228Swnj 	}
735228Swnj 	return ((caddr_t)m);
745228Swnj }
755228Swnj 
765228Swnj m_pgfree(addr, n)
775228Swnj 	caddr_t addr;
785228Swnj 	int n;
795228Swnj {
805228Swnj 
815228Swnj COUNT(M_PGFREE);
825228Swnj }
835228Swnj 
845228Swnj m_expand()
855228Swnj {
865228Swnj 
875228Swnj COUNT(M_EXPAND);
885228Swnj 	if (mbstat.m_bufs >= mbstat.m_hiwat)
895228Swnj 		return (0);
905228Swnj 	if (m_clalloc(1, MPG_MBUFS) == 0)
915228Swnj 		goto steal;
925228Swnj 	return (1);
935228Swnj steal:
945228Swnj 	/* should ask protocols to free code */
955228Swnj 	return (0);
965228Swnj }
975228Swnj 
985228Swnj /* NEED SOME WAY TO RELEASE SPACE */
995228Swnj 
1005228Swnj /*
1015228Swnj  * Space reservation routines
1025228Swnj  */
1035015Sroot m_reserve(mbufs)
1045015Sroot 	int mbufs;
1054732Swnj {
1064732Swnj 
1075147Swnj 	if (mbstat.m_lowat + (mbufs>>1) > (NMBCLUSTERS-32) * CLBYTES)
1084732Swnj 		return (0);
1095016Swnj 	mbstat.m_hiwat += mbufs;
1105016Swnj 	mbstat.m_lowat = mbstat.m_hiwat >> 1;
1114916Swnj 	return (1);
1124732Swnj }
1134732Swnj 
1145015Sroot m_release(mbufs)
1155015Sroot 	int mbufs;
1164732Swnj {
1174732Swnj 
1185016Swnj 	mbstat.m_hiwat -= mbufs;
1195016Swnj 	mbstat.m_lowat = mbstat.m_hiwat >> 1;
1204732Swnj }
1214732Swnj 
1225228Swnj /*
1235228Swnj  * Space allocation routines.
1245228Swnj  * These are also available as macros
1255228Swnj  * for critical paths.
1265228Swnj  */
1274585Swnj struct mbuf *
1284585Swnj m_get(canwait)
1294585Swnj 	int canwait;
1304585Swnj {
1314585Swnj 	register struct mbuf *m;
1324585Swnj 
1334585Swnj COUNT(M_GET);
1344585Swnj 	MGET(m, canwait);
1354585Swnj 	return (m);
1364585Swnj }
1374585Swnj 
1384585Swnj struct mbuf *
1394890Swnj m_getclr(canwait)
1404890Swnj 	int canwait;
1414890Swnj {
1424890Swnj 	register struct mbuf *m;
1434890Swnj 
1444890Swnj COUNT(M_GETCLR);
1454916Swnj 	m = m_get(canwait);
1464890Swnj 	if (m == 0)
1474890Swnj 		return (0);
1484890Swnj 	m->m_off = MMINOFF;
1494890Swnj 	bzero(mtod(m, caddr_t), MLEN);
1504890Swnj 	return (m);
1514890Swnj }
1524890Swnj 
1534890Swnj struct mbuf *
1544585Swnj m_free(m)
1554585Swnj 	struct mbuf *m;
1564585Swnj {
1574585Swnj 	register struct mbuf *n;
1584585Swnj 
1594585Swnj COUNT(M_FREE);
1604585Swnj 	MFREE(m, n);
1614585Swnj 	return (n);
1624585Swnj }
1634585Swnj 
1644916Swnj /*ARGSUSED*/
1654585Swnj struct mbuf *
1664585Swnj m_more(type)
1674585Swnj 	int type;
1684585Swnj {
1694585Swnj 	register struct mbuf *m;
1704585Swnj 
1714585Swnj COUNT(M_MORE);
1724585Swnj 	if (!m_expand()) {
1734822Swnj 		mbstat.m_drops++;
1744585Swnj 		return (NULL);
1754585Swnj 	}
1764916Swnj #define m_more(x) (panic("m_more"), (struct mbuf *)0)
1774916Swnj 	MGET(m, type);
1785282Sroot #undef m_more
1794585Swnj 	return (m);
1804585Swnj }
1814585Swnj 
1824669Swnj m_freem(m)
1834585Swnj 	register struct mbuf *m;
1844585Swnj {
1854585Swnj 	register struct mbuf *n;
1864927Swnj 	register int s;
1874585Swnj 
1884585Swnj COUNT(M_FREEM);
1894585Swnj 	if (m == NULL)
1904916Swnj 		return;
1914662Swnj 	s = splimp();
1924585Swnj 	do {
1934585Swnj 		MFREE(m, n);
1944585Swnj 	} while (m = n);
1954585Swnj 	splx(s);
1964585Swnj }
1974585Swnj 
1985228Swnj /*
1995228Swnj  * Mbuffer utility routines.
2005228Swnj  */
2014927Swnj struct mbuf *
2024927Swnj m_copy(m, off, len)
2034927Swnj 	register struct mbuf *m;
2044927Swnj 	int off;
2054927Swnj 	register int len;
2064927Swnj {
2074927Swnj 	register struct mbuf *n, **np;
2084927Swnj 	struct mbuf *top, *p;
2094927Swnj COUNT(M_COPY);
2104927Swnj 
2114927Swnj 	if (len == 0)
2124927Swnj 		return (0);
2134927Swnj 	if (off < 0 || len < 0)
2144927Swnj 		panic("m_copy");
2154927Swnj 	while (off > 0) {
2164927Swnj 		if (m == 0)
2174927Swnj 			panic("m_copy");
2184927Swnj 		if (off < m->m_len)
2194927Swnj 			break;
2204927Swnj 		off -= m->m_len;
2214927Swnj 		m = m->m_next;
2224927Swnj 	}
2234927Swnj 	np = &top;
2244927Swnj 	top = 0;
2254927Swnj 	while (len > 0) {
2264927Swnj 		MGET(n, 1);
2274927Swnj 		*np = n;
2284927Swnj 		if (n == 0)
2294927Swnj 			goto nospace;
2304927Swnj 		if (m == 0)
2314927Swnj 			panic("m_copy");
2324927Swnj 		n->m_len = MIN(len, m->m_len - off);
2334927Swnj 		if (m->m_off > MMAXOFF) {
2344927Swnj 			p = mtod(m, struct mbuf *);
2354927Swnj 			n->m_off = ((int)p - (int)n) + off;
2365090Swnj 			mclrefcnt[mtocl(p)]++;
2374927Swnj 		} else {
2384927Swnj 			n->m_off = MMINOFF;
2394927Swnj 			bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
2404927Swnj 			    (unsigned)n->m_len);
2414927Swnj 		}
2424927Swnj 		len -= n->m_len;
2434927Swnj 		off = 0;
2444927Swnj 		m = m->m_next;
2454927Swnj 		np = &n->m_next;
2464927Swnj 	}
2474927Swnj 	return (top);
2484927Swnj nospace:
2494927Swnj 	m_freem(top);
2504927Swnj 	return (0);
2514927Swnj }
2524927Swnj 
2534669Swnj m_cat(m, n)
2544669Swnj 	register struct mbuf *m, *n;
2554669Swnj {
2564669Swnj 
2574669Swnj 	while (m->m_next)
2584669Swnj 		m = m->m_next;
2594669Swnj 	while (n)
2604669Swnj 		if (m->m_off + m->m_len + n->m_len <= MMAXOFF) {
2614916Swnj 			bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
2624916Swnj 			    (u_int)n->m_len);
2634669Swnj 			m->m_len += n->m_len;
2644669Swnj 			n = m_free(n);
2654669Swnj 		} else {
2664669Swnj 			m->m_next = n;
2674669Swnj 			m = n;
2684669Swnj 			n = m->m_next;
2694669Swnj 		}
2704669Swnj }
2714669Swnj 
2724585Swnj m_adj(mp, len)
2734585Swnj 	struct mbuf *mp;
2744916Swnj 	register int len;
2754585Swnj {
2764585Swnj 	register struct mbuf *m, *n;
2774585Swnj 
2784585Swnj COUNT(M_ADJ);
2794585Swnj 	if ((m = mp) == NULL)
2804585Swnj 		return;
2814822Swnj 	if (len >= 0) {
2824585Swnj 		while (m != NULL && len > 0) {
2834822Swnj 			if (m->m_len <= len) {
2844585Swnj 				len -= m->m_len;
2854585Swnj 				m->m_len = 0;
2864585Swnj 				m = m->m_next;
2874822Swnj 			} else {
2884585Swnj 				m->m_len -= len;
2894585Swnj 				m->m_off += len;
2904585Swnj 				break;
2914585Swnj 			}
2924585Swnj 		}
2934822Swnj 	} else {
2944822Swnj 		/* a 2 pass algorithm might be better */
2954585Swnj 		len = -len;
2964585Swnj 		while (len > 0 && m->m_len != 0) {
2974585Swnj 			while (m != NULL && m->m_len != 0) {
2984585Swnj 				n = m;
2994585Swnj 				m = m->m_next;
3004585Swnj 			}
3014822Swnj 			if (n->m_len <= len) {
3024585Swnj 				len -= n->m_len;
3034585Swnj 				n->m_len = 0;
3044585Swnj 				m = mp;
3054822Swnj 			} else {
3064585Swnj 				n->m_len -= len;
3074585Swnj 				break;
3084585Swnj 			}
3094585Swnj 		}
3104585Swnj 	}
3114585Swnj }
3125228Swnj 
313*5310Sroot struct mbuf *
314*5310Sroot m_pullup(m0, len)
315*5310Sroot 	struct mbuf *m0;
3165228Swnj 	int len;
3175228Swnj {
318*5310Sroot 	register struct mbuf *m, *n;
319*5310Sroot 	int cnt;
3205228Swnj 
321*5310Sroot 	if (len > MLEN)
322*5310Sroot 		goto bad;
323*5310Sroot 	MGET(m, 0);
324*5310Sroot 	if (m == 0)
325*5310Sroot 		goto bad;
326*5310Sroot 	m->m_off = MMINOFF;
327*5310Sroot 	m->m_len = 0;
328*5310Sroot 	n = m0;
329*5310Sroot 	do {
330*5310Sroot 		cnt = MIN(MLEN - m->m_len, len);
331*5310Sroot 		if (cnt > n->m_len)
332*5310Sroot 			cnt = n->m_len;
333*5310Sroot 		bcopy(mtod(n, caddr_t), mtod(m, caddr_t)+m->m_len, cnt);
334*5310Sroot 		len -= cnt;
335*5310Sroot 		m->m_len += cnt;
336*5310Sroot 		n->m_off += cnt;
337*5310Sroot 		n->m_len -= cnt;
338*5310Sroot 		if (n->m_len)
339*5310Sroot 			break;
340*5310Sroot 		n = m_free(n);
341*5310Sroot 	} while (n);
342*5310Sroot 	if (len) {
343*5310Sroot 		(void) m_free(m);
344*5310Sroot 		goto bad;
345*5310Sroot 	}
346*5310Sroot 	m->m_next = n;
347*5310Sroot 	return (m);
348*5310Sroot bad:
349*5310Sroot 	m_freem(m0);
3505228Swnj 	return (0);
3515228Swnj }
352