xref: /csrg-svn/sys/kern/uipc_mbuf.c (revision 4890)
1*4890Swnj /* uipc_mbuf.c 1.9 81/11/14 */
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"
114822Swnj #include "../net/inet_systm.h"		/* ### */
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;
224732Swnj }
234732Swnj 
244732Swnj m_release(mbufs)
254732Swnj 	int mbufs;
264732Swnj {
274732Swnj 
284732Swnj 	mbstat.m_lowat -= mbufs;
294732Swnj 	mbstat.m_hiwat = 2 * mbstat.m_lowat;
304732Swnj }
314732Swnj 
324585Swnj struct mbuf *
334585Swnj m_get(canwait)
344585Swnj 	int canwait;
354585Swnj {
364585Swnj 	register struct mbuf *m;
374585Swnj 
384585Swnj COUNT(M_GET);
394585Swnj 	MGET(m, canwait);
404585Swnj 	return (m);
414585Swnj }
424585Swnj 
434585Swnj struct mbuf *
44*4890Swnj m_getclr(canwait)
45*4890Swnj 	int canwait;
46*4890Swnj {
47*4890Swnj 	register struct mbuf *m;
48*4890Swnj 
49*4890Swnj COUNT(M_GETCLR);
50*4890Swnj 	m = m_get(m, canwait);
51*4890Swnj 	if (m == 0)
52*4890Swnj 		return (0);
53*4890Swnj 	m->m_off = MMINOFF;
54*4890Swnj 	bzero(mtod(m, caddr_t), MLEN);
55*4890Swnj 	return (m);
56*4890Swnj }
57*4890Swnj 
58*4890Swnj struct mbuf *
594585Swnj m_free(m)
604585Swnj 	struct mbuf *m;
614585Swnj {
624585Swnj 	register struct mbuf *n;
634585Swnj 
644585Swnj COUNT(M_FREE);
654585Swnj 	MFREE(m, n);
664585Swnj 	return (n);
674585Swnj }
684585Swnj 
694585Swnj struct mbuf *
704585Swnj m_more(type)
714585Swnj 	int type;
724585Swnj {
734585Swnj 	int s;
744585Swnj 	register struct mbuf *m;
754585Swnj 
764585Swnj COUNT(M_MORE);
774585Swnj 	if (!m_expand()) {
784822Swnj 		mbstat.m_drops++;
794585Swnj 		return (NULL);
804585Swnj 	}
814585Swnj #define m_more(x) ((struct mbuf *)panic("m_more"))
824585Swnj 	MGET(m, 0);
834585Swnj 	return (m);
844585Swnj }
854585Swnj 
864669Swnj m_freem(m)
874585Swnj 	register struct mbuf *m;
884585Swnj {
894585Swnj 	register struct mbuf *n;
904585Swnj 	register int s, cnt;
914585Swnj 
924585Swnj COUNT(M_FREEM);
934585Swnj 	if (m == NULL)
944585Swnj 		return (0);
954585Swnj 	cnt = 0;
964662Swnj 	s = splimp();
974585Swnj 	do {
984669Swnj 		if (m->m_off > MMAXOFF)
994669Swnj 			cnt += NMBPG;
1004669Swnj 		cnt++;
1014585Swnj 		MFREE(m, n);
1024585Swnj 	} while (m = n);
1034585Swnj 	splx(s);
1044585Swnj 	return (cnt);
1054585Swnj }
1064585Swnj 
1074822Swnj mbinit()
1084585Swnj {
1094585Swnj 	register struct mbuf *m;
1104585Swnj 	register i;
1114585Swnj 
1124585Swnj COUNT(MBUFINIT);
1134822Swnj 	m = (struct mbuf *)&mbutl[0];  /* ->start of buffer virt mem */
1144822Swnj 	vmemall(&Mbmap[0], 2, proc, CSYS);
1154822Swnj 	vmaccess(&Mbmap[0], m, 2);
1164585Swnj 	for (i=0; i < NMBPG; i++) {
1174587Swnj 		m->m_off = 0;
1184585Swnj 		m_free(m);
1194585Swnj 		m++;
1204585Swnj 	}
1214585Swnj 	pg_alloc(3);
1224662Swnj 	mbstat.m_pages = 4;
1234662Swnj 	mbstat.m_bufs = 32;
1244662Swnj 	mbstat.m_lowat = 16;
1254662Swnj 	mbstat.m_hiwat = 32;
1264669Swnj 	{ int i,j,k,n;
1274669Swnj 	n = 32;
1284669Swnj 	k = n << 1;
1294822Swnj 	if ((i = rmalloc(mbmap, n)) == 0)
1304669Swnj 		return (0);
1314669Swnj 	j = i<<1;
1324669Swnj 	m = pftom(i);
1334669Swnj 	/* should use vmemall sometimes */
1344822Swnj 	if (memall(&Mbmap[j], k, proc, CSYS) == 0) {
1354669Swnj 		printf("botch\n");
1364669Swnj 		return;
1374669Swnj 	}
1384822Swnj 	vmaccess(&Mbmap[j], (caddr_t)m, k);
1394669Swnj 	for (j=0; j < n; j++) {
1404669Swnj 		m->m_off = 0;
1414669Swnj 		m->m_next = mpfree;
1424669Swnj 		mpfree = m;
1434669Swnj 		m += NMBPG;
1444669Swnj 		nmpfree++;
1454669Swnj 	}
1464669Swnj 	}
1474585Swnj }
1484585Swnj 
1494585Swnj pg_alloc(n)
1504585Swnj 	register int n;
1514585Swnj {
1524585Swnj 	register i, j, k;
1534585Swnj 	register struct mbuf *m;
1544585Swnj 	int bufs, s;
1554585Swnj 
1564585Swnj COUNT(PG_ALLOC);
1574585Swnj 	k = n << 1;
1584822Swnj 	if ((i = rmalloc(mbmap, n)) == 0)
1594585Swnj 		return (0);
1604585Swnj 	j = i<<1;
1614585Swnj 	m = pftom(i);
1624585Swnj 	/* should use vmemall sometimes */
1634822Swnj 	if (memall(&Mbmap[j], k, proc, CSYS) == 0)
1644585Swnj 		return (0);
1654822Swnj 	vmaccess(&Mbmap[j], (caddr_t)m, k);
1664585Swnj 	bufs = n << 3;
1674662Swnj 	s = splimp();
1684585Swnj 	for (j=0; j < bufs; j++) {
1694587Swnj 		m->m_off = 0;
1704585Swnj 		m_free(m);
1714585Swnj 		m++;
1724585Swnj 	}
1734585Swnj 	splx(s);
1744662Swnj 	mbstat.m_pages += n;
1754585Swnj 	return (1);
1764585Swnj }
1774585Swnj 
1784585Swnj m_expand()
1794585Swnj {
1804585Swnj 	register i;
1814585Swnj 	register struct mbuf *m, *n;
1824585Swnj 	int need, needp, needs;
1834585Swnj 
1844585Swnj COUNT(M_EXPAND);
1854662Swnj 	needs = need = mbstat.m_hiwat - mbstat.m_bufs;
1864662Swnj 	needp = need >> 3;
1874585Swnj 	if (pg_alloc(needp))
1884585Swnj 		return (1);
1894669Swnj 	for (i=0; i < needp; i++, need -= NMBPG)
1904669Swnj 		if (pg_alloc(1) == 0)
1914585Swnj 			goto steal;
1924585Swnj 	return (need < needs);
1934585Swnj steal:
1944669Swnj 	/* while (not enough) ask protocols to free code */
1954669Swnj 	;
1964585Swnj }
1974585Swnj 
1984585Swnj #ifdef notdef
1994585Swnj m_relse()
2004585Swnj {
2014669Swnj 
2024662Swnj COUNT(M_RELSE);
2034585Swnj }
2044585Swnj #endif
2054585Swnj 
2064669Swnj m_cat(m, n)
2074669Swnj 	register struct mbuf *m, *n;
2084669Swnj {
2094669Swnj 
2104669Swnj 	while (m->m_next)
2114669Swnj 		m = m->m_next;
2124669Swnj 	while (n)
2134669Swnj 		if (m->m_off + m->m_len + n->m_len <= MMAXOFF) {
2144669Swnj 			bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, n->m_len);
2154669Swnj 			m->m_len += n->m_len;
2164669Swnj 			n = m_free(n);
2174669Swnj 		} else {
2184669Swnj 			m->m_next = n;
2194669Swnj 			m = n;
2204669Swnj 			n = m->m_next;
2214669Swnj 		}
2224669Swnj }
2234669Swnj 
2244585Swnj m_adj(mp, len)
2254585Swnj 	struct mbuf *mp;
2264585Swnj 	register len;
2274585Swnj {
2284585Swnj 	register struct mbuf *m, *n;
2294585Swnj 
2304585Swnj COUNT(M_ADJ);
2314585Swnj 	if ((m = mp) == NULL)
2324585Swnj 		return;
2334822Swnj 	if (len >= 0) {
2344585Swnj 		while (m != NULL && len > 0) {
2354822Swnj 			if (m->m_len <= len) {
2364585Swnj 				len -= m->m_len;
2374585Swnj 				m->m_len = 0;
2384585Swnj 				m = m->m_next;
2394822Swnj 			} else {
2404585Swnj 				m->m_len -= len;
2414585Swnj 				m->m_off += len;
2424585Swnj 				break;
2434585Swnj 			}
2444585Swnj 		}
2454822Swnj 	} else {
2464822Swnj 		/* a 2 pass algorithm might be better */
2474585Swnj 		len = -len;
2484585Swnj 		while (len > 0 && m->m_len != 0) {
2494585Swnj 			while (m != NULL && m->m_len != 0) {
2504585Swnj 				n = m;
2514585Swnj 				m = m->m_next;
2524585Swnj 			}
2534822Swnj 			if (n->m_len <= len) {
2544585Swnj 				len -= n->m_len;
2554585Swnj 				n->m_len = 0;
2564585Swnj 				m = mp;
2574822Swnj 			} else {
2584585Swnj 				n->m_len -= len;
2594585Swnj 				break;
2604585Swnj 			}
2614585Swnj 		}
2624585Swnj 	}
2634585Swnj }
264