xref: /csrg-svn/sys/kern/uipc_mbuf.c (revision 4732)
1*4732Swnj /* uipc_mbuf.c 1.7 81/11/04 */
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"
114662Swnj #include "../inet/inet.h"
124662Swnj #include "../inet/inet_systm.h"
134669Swnj #include "../inet/ip.h"
144662Swnj #include "../inet/tcp.h"
154585Swnj #include "../h/vm.h"
164585Swnj 
17*4732Swnj m_reserve(mbufs)
18*4732Swnj 	int mbufs;
19*4732Swnj {
20*4732Swnj 
21*4732Swnj 	if (mbstat.m_lowat + mbufs > NNETPAGES * NMBPG - 32)
22*4732Swnj 		return (0);
23*4732Swnj 	mbstat.m_lowat += mbufs;
24*4732Swnj 	mbstat.m_hiwat = 2 * mbstat.m_lowat;
25*4732Swnj }
26*4732Swnj 
27*4732Swnj m_release(mbufs)
28*4732Swnj 	int mbufs;
29*4732Swnj {
30*4732Swnj 
31*4732Swnj 	mbstat.m_lowat -= mbufs;
32*4732Swnj 	mbstat.m_hiwat = 2 * mbstat.m_lowat;
33*4732Swnj }
34*4732Swnj 
354585Swnj struct mbuf *
364585Swnj m_get(canwait)
374585Swnj 	int canwait;
384585Swnj {
394585Swnj 	register struct mbuf *m;
404585Swnj 
414585Swnj COUNT(M_GET);
424585Swnj 	MGET(m, canwait);
434585Swnj 	return (m);
444585Swnj }
454585Swnj 
464585Swnj struct mbuf *
474585Swnj m_free(m)
484585Swnj 	struct mbuf *m;
494585Swnj {
504585Swnj 	register struct mbuf *n;
514585Swnj 
524585Swnj COUNT(M_FREE);
534585Swnj 	MFREE(m, n);
544585Swnj 	return (n);
554585Swnj }
564585Swnj 
574585Swnj struct mbuf *
584585Swnj m_more(type)
594585Swnj 	int type;
604585Swnj {
614585Swnj 	int s;
624585Swnj 	register struct mbuf *m;
634585Swnj 
644585Swnj COUNT(M_MORE);
654585Swnj 	if (!m_expand()) {
664585Swnj 		netstat.m_drops++;
674585Swnj 		return (NULL);
684585Swnj 	}
694585Swnj #define m_more(x) ((struct mbuf *)panic("m_more"))
704585Swnj 	MGET(m, 0);
714585Swnj 	return (m);
724585Swnj }
734585Swnj 
744669Swnj m_freem(m)
754585Swnj 	register struct mbuf *m;
764585Swnj {
774585Swnj 	register struct mbuf *n;
784585Swnj 	register int s, cnt;
794585Swnj 
804585Swnj COUNT(M_FREEM);
814585Swnj 	if (m == NULL)
824585Swnj 		return (0);
834585Swnj 	cnt = 0;
844662Swnj 	s = splimp();
854585Swnj 	do {
864669Swnj 		if (m->m_off > MMAXOFF)
874669Swnj 			cnt += NMBPG;
884669Swnj 		cnt++;
894585Swnj 		MFREE(m, n);
904585Swnj 	} while (m = n);
914585Swnj 	splx(s);
924585Swnj 	return (cnt);
934585Swnj }
944585Swnj 
954669Swnj mbufinit()
964585Swnj {
974585Swnj 	register struct mbuf *m;
984585Swnj 	register i;
994585Swnj 
1004585Swnj COUNT(MBUFINIT);
1014585Swnj 	m = (struct mbuf *)&netutl[0];  /* ->start of buffer virt mem */
1024585Swnj 	vmemall(&Netmap[0], 2, proc, CSYS);
1034585Swnj 	vmaccess(&Netmap[0], m, 2);
1044585Swnj 	for (i=0; i < NMBPG; i++) {
1054587Swnj 		m->m_off = 0;
1064585Swnj 		m_free(m);
1074585Swnj 		m++;
1084585Swnj 	}
1094585Swnj 	pg_alloc(3);
1104662Swnj 	mbstat.m_pages = 4;
1114662Swnj 	mbstat.m_bufs = 32;
1124662Swnj 	mbstat.m_lowat = 16;
1134662Swnj 	mbstat.m_hiwat = 32;
1144669Swnj 	{ int i,j,k,n;
1154669Swnj 	n = 32;
1164669Swnj 	k = n << 1;
1174669Swnj 	if ((i = rmalloc(netmap, n)) == 0)
1184669Swnj 		return (0);
1194669Swnj 	j = i<<1;
1204669Swnj 	m = pftom(i);
1214669Swnj 	/* should use vmemall sometimes */
1224669Swnj 	if (memall(&Netmap[j], k, proc, CSYS) == 0) {
1234669Swnj 		printf("botch\n");
1244669Swnj 		return;
1254669Swnj 	}
1264669Swnj 	vmaccess(&Netmap[j], (caddr_t)m, k);
1274669Swnj 	for (j=0; j < n; j++) {
1284669Swnj 		m->m_off = 0;
1294669Swnj 		m->m_next = mpfree;
1304669Swnj 		mpfree = m;
1314669Swnj 		m += NMBPG;
1324669Swnj 		nmpfree++;
1334669Swnj 	}
1344669Swnj 	}
1354585Swnj }
1364585Swnj 
1374585Swnj pg_alloc(n)
1384585Swnj 	register int n;
1394585Swnj {
1404585Swnj 	register i, j, k;
1414585Swnj 	register struct mbuf *m;
1424585Swnj 	int bufs, s;
1434585Swnj 
1444585Swnj COUNT(PG_ALLOC);
1454585Swnj 	k = n << 1;
1464585Swnj 	if ((i = rmalloc(netmap, n)) == 0)
1474585Swnj 		return (0);
1484585Swnj 	j = i<<1;
1494585Swnj 	m = pftom(i);
1504585Swnj 	/* should use vmemall sometimes */
1514585Swnj 	if (memall(&Netmap[j], k, proc, CSYS) == 0)
1524585Swnj 		return (0);
1534585Swnj 	vmaccess(&Netmap[j], (caddr_t)m, k);
1544585Swnj 	bufs = n << 3;
1554662Swnj 	s = splimp();
1564585Swnj 	for (j=0; j < bufs; j++) {
1574587Swnj 		m->m_off = 0;
1584585Swnj 		m_free(m);
1594585Swnj 		m++;
1604585Swnj 	}
1614585Swnj 	splx(s);
1624662Swnj 	mbstat.m_pages += n;
1634585Swnj 	return (1);
1644585Swnj }
1654585Swnj 
1664585Swnj m_expand()
1674585Swnj {
1684585Swnj 	register i;
1694585Swnj 	register struct mbuf *m, *n;
1704585Swnj 	int need, needp, needs;
1714585Swnj 
1724585Swnj COUNT(M_EXPAND);
1734662Swnj 	needs = need = mbstat.m_hiwat - mbstat.m_bufs;
1744662Swnj 	needp = need >> 3;
1754585Swnj 	if (pg_alloc(needp))
1764585Swnj 		return (1);
1774669Swnj 	for (i=0; i < needp; i++, need -= NMBPG)
1784669Swnj 		if (pg_alloc(1) == 0)
1794585Swnj 			goto steal;
1804585Swnj 	return (need < needs);
1814585Swnj steal:
1824669Swnj 	/* while (not enough) ask protocols to free code */
1834669Swnj 	;
1844585Swnj }
1854585Swnj 
1864585Swnj #ifdef notdef
1874585Swnj m_relse()
1884585Swnj {
1894669Swnj 
1904662Swnj COUNT(M_RELSE);
1914585Swnj }
1924585Swnj #endif
1934585Swnj 
1944669Swnj m_cat(m, n)
1954669Swnj 	register struct mbuf *m, *n;
1964669Swnj {
1974669Swnj 
1984669Swnj 	while (m->m_next)
1994669Swnj 		m = m->m_next;
2004669Swnj 	while (n)
2014669Swnj 		if (m->m_off + m->m_len + n->m_len <= MMAXOFF) {
2024669Swnj 			bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, n->m_len);
2034669Swnj 			m->m_len += n->m_len;
2044669Swnj 			n = m_free(n);
2054669Swnj 		} else {
2064669Swnj 			m->m_next = n;
2074669Swnj 			m = n;
2084669Swnj 			n = m->m_next;
2094669Swnj 		}
2104669Swnj }
2114669Swnj 
2124585Swnj m_adj(mp, len)
2134585Swnj 	struct mbuf *mp;
2144585Swnj 	register len;
2154585Swnj {
2164585Swnj 	register struct mbuf *m, *n;
2174585Swnj 
2184669Swnj /*
2194669Swnj 	for (m = mp; m; m = m->m_next) {
2204669Swnj 		printf("a %x %d\n", m, m->m_len);
2214669Swnj 	}
2224669Swnj */
2234585Swnj COUNT(M_ADJ);
2244585Swnj 	if ((m = mp) == NULL)
2254585Swnj 		return;
2264585Swnj 	if (len >= 0) {                 /* adjust from top of msg chain */
2274585Swnj 		while (m != NULL && len > 0) {
2284585Swnj 			if (m->m_len <= len) {          /* free this mbuf */
2294585Swnj 				len -= m->m_len;
2304585Swnj 				m->m_len = 0;
2314585Swnj 				m = m->m_next;
2324585Swnj 			} else {                        /* adjust mbuf */
2334585Swnj 				m->m_len -= len;
2344585Swnj 				m->m_off += len;
2354585Swnj 				break;
2364585Swnj 			}
2374585Swnj 		}
2384585Swnj 
2394585Swnj 	} else {                        /* adjust from bottom of msg chain */
2404585Swnj 		len = -len;
2414585Swnj 		while (len > 0 && m->m_len != 0) {
2424585Swnj 			/* find end of chain */
2434585Swnj 			while (m != NULL && m->m_len != 0) {
2444585Swnj 				n = m;
2454585Swnj 				m = m->m_next;
2464585Swnj 			}
2474585Swnj 			if (n->m_len <= len) {          /* last mbuf */
2484585Swnj 				len -= n->m_len;
2494585Swnj 				n->m_len = 0;
2504585Swnj 				m = mp;
2514585Swnj 			} else {                        /* adjust length */
2524585Swnj 				n->m_len -= len;
2534585Swnj 				break;
2544585Swnj 			}
2554585Swnj 		}
2564585Swnj 	}
2574585Swnj }
2584585Swnj 
2594585Swnj /*
2604585Swnj  * convert mbuf virtual to physical addr for uballoc
2614585Swnj  */
2624585Swnj mtophys(m)
2634585Swnj 	register struct mbuf *m;
2644585Swnj {
2654585Swnj 	register i;
2664585Swnj 	register unsigned long addr;
2674585Swnj 	register struct pte *pte;
2684585Swnj 
2694585Swnj COUNT(MTOPHYS);
2704585Swnj 	i = (((int)m & ~PGOFSET) - (int)netutl) >> PGSHIFT;
2714585Swnj 	pte = &Netmap[i];
2724585Swnj 	addr = (pte->pg_pfnum << PGSHIFT) | ((int)m & PGOFSET);
2734585Swnj 	return (addr);
2744585Swnj }
275