xref: /csrg-svn/sys/kern/uipc_mbuf.c (revision 4916)
1*4916Swnj /*	uipc_mbuf.c	1.10	81/11/16	*/
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"
11*4916Swnj #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;
22*4916Swnj 	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);
51*4916Swnj 	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 
70*4916Swnj /*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 	}
82*4916Swnj #define m_more(x) (panic("m_more"), (struct mbuf *)0)
83*4916Swnj 	MGET(m, type);
844585Swnj 	return (m);
854585Swnj }
864585Swnj 
874669Swnj m_freem(m)
884585Swnj 	register struct mbuf *m;
894585Swnj {
904585Swnj 	register struct mbuf *n;
91*4916Swnj 	register int s, i;
924585Swnj 
934585Swnj COUNT(M_FREEM);
944585Swnj 	if (m == NULL)
95*4916Swnj 		return;
96*4916Swnj 	i = 0;
974662Swnj 	s = splimp();
984585Swnj 	do {
994669Swnj 		if (m->m_off > MMAXOFF)
100*4916Swnj 			i += NMBPG;
101*4916Swnj 		i++;
1024585Swnj 		MFREE(m, n);
1034585Swnj 	} while (m = n);
1044585Swnj 	splx(s);
105*4916Swnj 	return;
1064585Swnj }
1074585Swnj 
1084822Swnj mbinit()
1094585Swnj {
1104585Swnj 	register struct mbuf *m;
1114585Swnj 	register i;
1124585Swnj 
1134585Swnj COUNT(MBUFINIT);
1144822Swnj 	m = (struct mbuf *)&mbutl[0];  /* ->start of buffer virt mem */
115*4916Swnj 	(void) vmemall(&Mbmap[0], 2, proc, CSYS);
116*4916Swnj 	vmaccess(&Mbmap[0], (caddr_t)m, 2);
1174585Swnj 	for (i=0; i < NMBPG; i++) {
1184587Swnj 		m->m_off = 0;
1194585Swnj 		m_free(m);
1204585Swnj 		m++;
1214585Swnj 	}
122*4916Swnj 	(void) pg_alloc(3);
1234662Swnj 	mbstat.m_pages = 4;
1244662Swnj 	mbstat.m_bufs = 32;
1254662Swnj 	mbstat.m_lowat = 16;
1264662Swnj 	mbstat.m_hiwat = 32;
127*4916Swnj 	{ int j,k,n;
1284669Swnj 	n = 32;
1294669Swnj 	k = n << 1;
1304822Swnj 	if ((i = rmalloc(mbmap, n)) == 0)
131*4916Swnj 		panic("mbinit");
1324669Swnj 	j = i<<1;
1334669Swnj 	m = pftom(i);
1344669Swnj 	/* should use vmemall sometimes */
1354822Swnj 	if (memall(&Mbmap[j], k, proc, CSYS) == 0) {
1364669Swnj 		printf("botch\n");
1374669Swnj 		return;
1384669Swnj 	}
1394822Swnj 	vmaccess(&Mbmap[j], (caddr_t)m, k);
1404669Swnj 	for (j=0; j < n; j++) {
1414669Swnj 		m->m_off = 0;
1424669Swnj 		m->m_next = mpfree;
1434669Swnj 		mpfree = m;
1444669Swnj 		m += NMBPG;
1454669Swnj 		nmpfree++;
1464669Swnj 	}
1474669Swnj 	}
1484585Swnj }
1494585Swnj 
1504585Swnj pg_alloc(n)
1514585Swnj 	register int n;
1524585Swnj {
1534585Swnj 	register i, j, k;
1544585Swnj 	register struct mbuf *m;
1554585Swnj 	int bufs, s;
1564585Swnj 
1574585Swnj COUNT(PG_ALLOC);
1584585Swnj 	k = n << 1;
1594822Swnj 	if ((i = rmalloc(mbmap, n)) == 0)
1604585Swnj 		return (0);
1614585Swnj 	j = i<<1;
1624585Swnj 	m = pftom(i);
1634585Swnj 	/* should use vmemall sometimes */
1644822Swnj 	if (memall(&Mbmap[j], k, proc, CSYS) == 0)
1654585Swnj 		return (0);
1664822Swnj 	vmaccess(&Mbmap[j], (caddr_t)m, k);
1674585Swnj 	bufs = n << 3;
1684662Swnj 	s = splimp();
1694585Swnj 	for (j=0; j < bufs; j++) {
1704587Swnj 		m->m_off = 0;
1714585Swnj 		m_free(m);
1724585Swnj 		m++;
1734585Swnj 	}
1744585Swnj 	splx(s);
1754662Swnj 	mbstat.m_pages += n;
1764585Swnj 	return (1);
1774585Swnj }
1784585Swnj 
1794585Swnj m_expand()
1804585Swnj {
1814585Swnj 	register i;
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 	;
196*4916Swnj 	return (0);
1974585Swnj }
1984585Swnj 
1994585Swnj #ifdef notdef
2004585Swnj m_relse()
2014585Swnj {
2024669Swnj 
2034662Swnj COUNT(M_RELSE);
2044585Swnj }
2054585Swnj #endif
2064585Swnj 
2074669Swnj m_cat(m, n)
2084669Swnj 	register struct mbuf *m, *n;
2094669Swnj {
2104669Swnj 
2114669Swnj 	while (m->m_next)
2124669Swnj 		m = m->m_next;
2134669Swnj 	while (n)
2144669Swnj 		if (m->m_off + m->m_len + n->m_len <= MMAXOFF) {
215*4916Swnj 			bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
216*4916Swnj 			    (u_int)n->m_len);
2174669Swnj 			m->m_len += n->m_len;
2184669Swnj 			n = m_free(n);
2194669Swnj 		} else {
2204669Swnj 			m->m_next = n;
2214669Swnj 			m = n;
2224669Swnj 			n = m->m_next;
2234669Swnj 		}
2244669Swnj }
2254669Swnj 
2264585Swnj m_adj(mp, len)
2274585Swnj 	struct mbuf *mp;
228*4916Swnj 	register int len;
2294585Swnj {
2304585Swnj 	register struct mbuf *m, *n;
2314585Swnj 
2324585Swnj COUNT(M_ADJ);
2334585Swnj 	if ((m = mp) == NULL)
2344585Swnj 		return;
2354822Swnj 	if (len >= 0) {
2364585Swnj 		while (m != NULL && len > 0) {
2374822Swnj 			if (m->m_len <= len) {
2384585Swnj 				len -= m->m_len;
2394585Swnj 				m->m_len = 0;
2404585Swnj 				m = m->m_next;
2414822Swnj 			} else {
2424585Swnj 				m->m_len -= len;
2434585Swnj 				m->m_off += len;
2444585Swnj 				break;
2454585Swnj 			}
2464585Swnj 		}
2474822Swnj 	} else {
2484822Swnj 		/* a 2 pass algorithm might be better */
2494585Swnj 		len = -len;
2504585Swnj 		while (len > 0 && m->m_len != 0) {
2514585Swnj 			while (m != NULL && m->m_len != 0) {
2524585Swnj 				n = m;
2534585Swnj 				m = m->m_next;
2544585Swnj 			}
2554822Swnj 			if (n->m_len <= len) {
2564585Swnj 				len -= n->m_len;
2574585Swnj 				n->m_len = 0;
2584585Swnj 				m = mp;
2594822Swnj 			} else {
2604585Swnj 				n->m_len -= len;
2614585Swnj 				break;
2624585Swnj 			}
2634585Swnj 		}
2644585Swnj 	}
2654585Swnj }
266