xref: /csrg-svn/sys/kern/uipc_mbuf.c (revision 4669)
1*4669Swnj /* uipc_mbuf.c 1.6 81/10/30 */
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"
13*4669Swnj #include "../inet/ip.h"
144662Swnj #include "../inet/tcp.h"
154585Swnj #include "../h/vm.h"
164585Swnj 
174585Swnj struct mbuf *
184585Swnj m_get(canwait)
194585Swnj 	int canwait;
204585Swnj {
214585Swnj 	register struct mbuf *m;
224585Swnj 
234585Swnj COUNT(M_GET);
244585Swnj 	MGET(m, canwait);
254585Swnj 	return (m);
264585Swnj }
274585Swnj 
284585Swnj struct mbuf *
294585Swnj m_free(m)
304585Swnj 	struct mbuf *m;
314585Swnj {
324585Swnj 	register struct mbuf *n;
334585Swnj 
344585Swnj COUNT(M_FREE);
354585Swnj 	MFREE(m, n);
364585Swnj 	return (n);
374585Swnj }
384585Swnj 
394585Swnj struct mbuf *
404585Swnj m_more(type)
414585Swnj 	int type;
424585Swnj {
434585Swnj 	int s;
444585Swnj 	register struct mbuf *m;
454585Swnj 
464585Swnj COUNT(M_MORE);
474585Swnj 	if (!m_expand()) {
484585Swnj 		netstat.m_drops++;
494585Swnj 		return (NULL);
504585Swnj 	}
514585Swnj #define m_more(x) ((struct mbuf *)panic("m_more"))
524585Swnj 	MGET(m, 0);
534585Swnj 	return (m);
544585Swnj }
554585Swnj 
56*4669Swnj m_freem(m)
574585Swnj 	register struct mbuf *m;
584585Swnj {
594585Swnj 	register struct mbuf *n;
604585Swnj 	register int s, cnt;
614585Swnj 
624585Swnj COUNT(M_FREEM);
634585Swnj 	if (m == NULL)
644585Swnj 		return (0);
654585Swnj 	cnt = 0;
664662Swnj 	s = splimp();
674585Swnj 	do {
68*4669Swnj 		if (m->m_off > MMAXOFF)
69*4669Swnj 			cnt += NMBPG;
70*4669Swnj 		cnt++;
714585Swnj 		MFREE(m, n);
724585Swnj 	} while (m = n);
734585Swnj 	splx(s);
744585Swnj 	return (cnt);
754585Swnj }
764585Swnj 
77*4669Swnj mbufinit()
784585Swnj {
794585Swnj 	register struct mbuf *m;
804585Swnj 	register i;
814585Swnj 
824585Swnj COUNT(MBUFINIT);
834585Swnj 	m = (struct mbuf *)&netutl[0];  /* ->start of buffer virt mem */
844585Swnj 	vmemall(&Netmap[0], 2, proc, CSYS);
854585Swnj 	vmaccess(&Netmap[0], m, 2);
864585Swnj 	for (i=0; i < NMBPG; i++) {
874587Swnj 		m->m_off = 0;
884585Swnj 		m_free(m);
894585Swnj 		m++;
904585Swnj 	}
914585Swnj 	pg_alloc(3);
924662Swnj 	mbstat.m_pages = 4;
934662Swnj 	mbstat.m_bufs = 32;
944662Swnj 	mbstat.m_lowat = 16;
954662Swnj 	mbstat.m_hiwat = 32;
96*4669Swnj 	{ int i,j,k,n;
97*4669Swnj 	n = 32;
98*4669Swnj 	k = n << 1;
99*4669Swnj 	if ((i = rmalloc(netmap, n)) == 0)
100*4669Swnj 		return (0);
101*4669Swnj 	j = i<<1;
102*4669Swnj 	m = pftom(i);
103*4669Swnj 	/* should use vmemall sometimes */
104*4669Swnj 	if (memall(&Netmap[j], k, proc, CSYS) == 0) {
105*4669Swnj 		printf("botch\n");
106*4669Swnj 		return;
107*4669Swnj 	}
108*4669Swnj 	vmaccess(&Netmap[j], (caddr_t)m, k);
109*4669Swnj 	for (j=0; j < n; j++) {
110*4669Swnj 		m->m_off = 0;
111*4669Swnj 		m->m_next = mpfree;
112*4669Swnj 		mpfree = m;
113*4669Swnj 		m += NMBPG;
114*4669Swnj 		nmpfree++;
115*4669Swnj 	}
116*4669Swnj 	}
1174585Swnj }
1184585Swnj 
1194585Swnj pg_alloc(n)
1204585Swnj 	register int n;
1214585Swnj {
1224585Swnj 	register i, j, k;
1234585Swnj 	register struct mbuf *m;
1244585Swnj 	int bufs, s;
1254585Swnj 
1264585Swnj COUNT(PG_ALLOC);
1274585Swnj 	k = n << 1;
1284585Swnj 	if ((i = rmalloc(netmap, n)) == 0)
1294585Swnj 		return (0);
1304585Swnj 	j = i<<1;
1314585Swnj 	m = pftom(i);
1324585Swnj 	/* should use vmemall sometimes */
1334585Swnj 	if (memall(&Netmap[j], k, proc, CSYS) == 0)
1344585Swnj 		return (0);
1354585Swnj 	vmaccess(&Netmap[j], (caddr_t)m, k);
1364585Swnj 	bufs = n << 3;
1374662Swnj 	s = splimp();
1384585Swnj 	for (j=0; j < bufs; j++) {
1394587Swnj 		m->m_off = 0;
1404585Swnj 		m_free(m);
1414585Swnj 		m++;
1424585Swnj 	}
1434585Swnj 	splx(s);
1444662Swnj 	mbstat.m_pages += n;
1454585Swnj 	return (1);
1464585Swnj }
1474585Swnj 
1484585Swnj m_expand()
1494585Swnj {
1504585Swnj 	register i;
1514585Swnj 	register struct mbuf *m, *n;
1524585Swnj 	int need, needp, needs;
1534585Swnj 
1544585Swnj COUNT(M_EXPAND);
1554662Swnj 	needs = need = mbstat.m_hiwat - mbstat.m_bufs;
1564662Swnj 	needp = need >> 3;
1574585Swnj 	if (pg_alloc(needp))
1584585Swnj 		return (1);
159*4669Swnj 	for (i=0; i < needp; i++, need -= NMBPG)
160*4669Swnj 		if (pg_alloc(1) == 0)
1614585Swnj 			goto steal;
1624585Swnj 	return (need < needs);
1634585Swnj steal:
164*4669Swnj 	/* while (not enough) ask protocols to free code */
165*4669Swnj 	;
1664585Swnj }
1674585Swnj 
1684585Swnj #ifdef notdef
1694585Swnj m_relse()
1704585Swnj {
171*4669Swnj 
1724662Swnj COUNT(M_RELSE);
1734585Swnj }
1744585Swnj #endif
1754585Swnj 
176*4669Swnj m_cat(m, n)
177*4669Swnj 	register struct mbuf *m, *n;
178*4669Swnj {
179*4669Swnj 
180*4669Swnj 	while (m->m_next)
181*4669Swnj 		m = m->m_next;
182*4669Swnj 	while (n)
183*4669Swnj 		if (m->m_off + m->m_len + n->m_len <= MMAXOFF) {
184*4669Swnj 			bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, n->m_len);
185*4669Swnj 			m->m_len += n->m_len;
186*4669Swnj 			n = m_free(n);
187*4669Swnj 		} else {
188*4669Swnj 			m->m_next = n;
189*4669Swnj 			m = n;
190*4669Swnj 			n = m->m_next;
191*4669Swnj 		}
192*4669Swnj }
193*4669Swnj 
1944585Swnj m_adj(mp, len)
1954585Swnj 	struct mbuf *mp;
1964585Swnj 	register len;
1974585Swnj {
1984585Swnj 	register struct mbuf *m, *n;
1994585Swnj 
200*4669Swnj /*
201*4669Swnj 	for (m = mp; m; m = m->m_next) {
202*4669Swnj 		printf("a %x %d\n", m, m->m_len);
203*4669Swnj 	}
204*4669Swnj */
2054585Swnj COUNT(M_ADJ);
2064585Swnj 	if ((m = mp) == NULL)
2074585Swnj 		return;
2084585Swnj 	if (len >= 0) {                 /* adjust from top of msg chain */
2094585Swnj 		while (m != NULL && len > 0) {
2104585Swnj 			if (m->m_len <= len) {          /* free this mbuf */
2114585Swnj 				len -= m->m_len;
2124585Swnj 				m->m_len = 0;
2134585Swnj 				m = m->m_next;
2144585Swnj 			} else {                        /* adjust mbuf */
2154585Swnj 				m->m_len -= len;
2164585Swnj 				m->m_off += len;
2174585Swnj 				break;
2184585Swnj 			}
2194585Swnj 		}
2204585Swnj 
2214585Swnj 	} else {                        /* adjust from bottom of msg chain */
2224585Swnj 		len = -len;
2234585Swnj 		while (len > 0 && m->m_len != 0) {
2244585Swnj 			/* find end of chain */
2254585Swnj 			while (m != NULL && m->m_len != 0) {
2264585Swnj 				n = m;
2274585Swnj 				m = m->m_next;
2284585Swnj 			}
2294585Swnj 			if (n->m_len <= len) {          /* last mbuf */
2304585Swnj 				len -= n->m_len;
2314585Swnj 				n->m_len = 0;
2324585Swnj 				m = mp;
2334585Swnj 			} else {                        /* adjust length */
2344585Swnj 				n->m_len -= len;
2354585Swnj 				break;
2364585Swnj 			}
2374585Swnj 		}
2384585Swnj 	}
2394585Swnj }
2404585Swnj 
2414585Swnj /*
2424585Swnj  * convert mbuf virtual to physical addr for uballoc
2434585Swnj  */
2444585Swnj mtophys(m)
2454585Swnj 	register struct mbuf *m;
2464585Swnj {
2474585Swnj 	register i;
2484585Swnj 	register unsigned long addr;
2494585Swnj 	register struct pte *pte;
2504585Swnj 
2514585Swnj COUNT(MTOPHYS);
2524585Swnj 	i = (((int)m & ~PGOFSET) - (int)netutl) >> PGSHIFT;
2534585Swnj 	pte = &Netmap[i];
2544585Swnj 	addr = (pte->pg_pfnum << PGSHIFT) | ((int)m & PGOFSET);
2554585Swnj 	return (addr);
2564585Swnj }
257