xref: /csrg-svn/sys/kern/uipc_mbuf.c (revision 4927)
1*4927Swnj /*	uipc_mbuf.c	1.11	81/11/18	*/
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"
114916Swnj #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;
224916Swnj 	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);
514916Swnj 	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 
704916Swnj /*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 	}
824916Swnj #define m_more(x) (panic("m_more"), (struct mbuf *)0)
834916Swnj 	MGET(m, type);
844585Swnj 	return (m);
854585Swnj }
864585Swnj 
874669Swnj m_freem(m)
884585Swnj 	register struct mbuf *m;
894585Swnj {
904585Swnj 	register struct mbuf *n;
91*4927Swnj 	register int s;
924585Swnj 
934585Swnj COUNT(M_FREEM);
944585Swnj 	if (m == NULL)
954916Swnj 		return;
964662Swnj 	s = splimp();
974585Swnj 	do {
984585Swnj 		MFREE(m, n);
994585Swnj 	} while (m = n);
1004585Swnj 	splx(s);
1014585Swnj }
1024585Swnj 
103*4927Swnj m_pullup(m, len)
104*4927Swnj 	struct mbuf *m;
105*4927Swnj 	int len;
106*4927Swnj {
107*4927Swnj 
108*4927Swnj 	return (0);
109*4927Swnj }
110*4927Swnj 
111*4927Swnj struct mbuf *
112*4927Swnj m_copy(m, off, len)
113*4927Swnj 	register struct mbuf *m;
114*4927Swnj 	int off;
115*4927Swnj 	register int len;
116*4927Swnj {
117*4927Swnj 	register struct mbuf *n, **np;
118*4927Swnj 	struct mbuf *top, *p;
119*4927Swnj COUNT(M_COPY);
120*4927Swnj 
121*4927Swnj 	if (len == 0)
122*4927Swnj 		return (0);
123*4927Swnj 	if (off < 0 || len < 0)
124*4927Swnj 		panic("m_copy");
125*4927Swnj 	while (off > 0) {
126*4927Swnj 		if (m == 0)
127*4927Swnj 			panic("m_copy");
128*4927Swnj 		if (off < m->m_len)
129*4927Swnj 			break;
130*4927Swnj 		off -= m->m_len;
131*4927Swnj 		m = m->m_next;
132*4927Swnj 	}
133*4927Swnj 	np = &top;
134*4927Swnj 	top = 0;
135*4927Swnj 	while (len > 0) {
136*4927Swnj 		MGET(n, 1);
137*4927Swnj 		*np = n;
138*4927Swnj 		if (n == 0)
139*4927Swnj 			goto nospace;
140*4927Swnj 		if (m == 0)
141*4927Swnj 			panic("m_copy");
142*4927Swnj 		n->m_len = MIN(len, m->m_len - off);
143*4927Swnj 		if (m->m_off > MMAXOFF) {
144*4927Swnj 			p = mtod(m, struct mbuf *);
145*4927Swnj 			n->m_off = ((int)p - (int)n) + off;
146*4927Swnj 			mprefcnt[mtopf(p)]++;
147*4927Swnj 		} else {
148*4927Swnj 			n->m_off = MMINOFF;
149*4927Swnj 			bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
150*4927Swnj 			    (unsigned)n->m_len);
151*4927Swnj 		}
152*4927Swnj 		len -= n->m_len;
153*4927Swnj 		off = 0;
154*4927Swnj 		m = m->m_next;
155*4927Swnj 		np = &n->m_next;
156*4927Swnj 	}
157*4927Swnj 	return (top);
158*4927Swnj nospace:
159*4927Swnj 	printf("m_copy: no space\n");
160*4927Swnj 	m_freem(top);
161*4927Swnj 	return (0);
162*4927Swnj }
163*4927Swnj 
1644822Swnj mbinit()
1654585Swnj {
1664585Swnj 	register struct mbuf *m;
1674585Swnj 	register i;
1684585Swnj 
1694585Swnj COUNT(MBUFINIT);
1704822Swnj 	m = (struct mbuf *)&mbutl[0];  /* ->start of buffer virt mem */
1714916Swnj 	(void) vmemall(&Mbmap[0], 2, proc, CSYS);
1724916Swnj 	vmaccess(&Mbmap[0], (caddr_t)m, 2);
1734585Swnj 	for (i=0; i < NMBPG; i++) {
1744587Swnj 		m->m_off = 0;
1754585Swnj 		m_free(m);
1764585Swnj 		m++;
1774585Swnj 	}
1784916Swnj 	(void) pg_alloc(3);
1794662Swnj 	mbstat.m_pages = 4;
1804662Swnj 	mbstat.m_bufs = 32;
1814662Swnj 	mbstat.m_lowat = 16;
1824662Swnj 	mbstat.m_hiwat = 32;
1834916Swnj 	{ int j,k,n;
1844669Swnj 	n = 32;
1854669Swnj 	k = n << 1;
1864822Swnj 	if ((i = rmalloc(mbmap, n)) == 0)
1874916Swnj 		panic("mbinit");
1884669Swnj 	j = i<<1;
1894669Swnj 	m = pftom(i);
1904669Swnj 	/* should use vmemall sometimes */
1914822Swnj 	if (memall(&Mbmap[j], k, proc, CSYS) == 0) {
1924669Swnj 		printf("botch\n");
1934669Swnj 		return;
1944669Swnj 	}
1954822Swnj 	vmaccess(&Mbmap[j], (caddr_t)m, k);
1964669Swnj 	for (j=0; j < n; j++) {
1974669Swnj 		m->m_off = 0;
1984669Swnj 		m->m_next = mpfree;
1994669Swnj 		mpfree = m;
2004669Swnj 		m += NMBPG;
2014669Swnj 		nmpfree++;
2024669Swnj 	}
2034669Swnj 	}
2044585Swnj }
2054585Swnj 
2064585Swnj pg_alloc(n)
2074585Swnj 	register int n;
2084585Swnj {
2094585Swnj 	register i, j, k;
2104585Swnj 	register struct mbuf *m;
2114585Swnj 	int bufs, s;
2124585Swnj 
2134585Swnj COUNT(PG_ALLOC);
2144585Swnj 	k = n << 1;
2154822Swnj 	if ((i = rmalloc(mbmap, n)) == 0)
2164585Swnj 		return (0);
2174585Swnj 	j = i<<1;
2184585Swnj 	m = pftom(i);
2194585Swnj 	/* should use vmemall sometimes */
2204822Swnj 	if (memall(&Mbmap[j], k, proc, CSYS) == 0)
2214585Swnj 		return (0);
2224822Swnj 	vmaccess(&Mbmap[j], (caddr_t)m, k);
2234585Swnj 	bufs = n << 3;
2244662Swnj 	s = splimp();
2254585Swnj 	for (j=0; j < bufs; j++) {
2264587Swnj 		m->m_off = 0;
2274585Swnj 		m_free(m);
2284585Swnj 		m++;
2294585Swnj 	}
2304585Swnj 	splx(s);
2314662Swnj 	mbstat.m_pages += n;
2324585Swnj 	return (1);
2334585Swnj }
2344585Swnj 
2354585Swnj m_expand()
2364585Swnj {
2374585Swnj 	register i;
2384585Swnj 	int need, needp, needs;
2394585Swnj 
2404585Swnj COUNT(M_EXPAND);
2414662Swnj 	needs = need = mbstat.m_hiwat - mbstat.m_bufs;
2424662Swnj 	needp = need >> 3;
2434585Swnj 	if (pg_alloc(needp))
2444585Swnj 		return (1);
2454669Swnj 	for (i=0; i < needp; i++, need -= NMBPG)
2464669Swnj 		if (pg_alloc(1) == 0)
2474585Swnj 			goto steal;
2484585Swnj 	return (need < needs);
2494585Swnj steal:
2504669Swnj 	/* while (not enough) ask protocols to free code */
2514669Swnj 	;
2524916Swnj 	return (0);
2534585Swnj }
2544585Swnj 
2554585Swnj #ifdef notdef
2564585Swnj m_relse()
2574585Swnj {
2584669Swnj 
2594662Swnj COUNT(M_RELSE);
2604585Swnj }
2614585Swnj #endif
2624585Swnj 
2634669Swnj m_cat(m, n)
2644669Swnj 	register struct mbuf *m, *n;
2654669Swnj {
2664669Swnj 
2674669Swnj 	while (m->m_next)
2684669Swnj 		m = m->m_next;
2694669Swnj 	while (n)
2704669Swnj 		if (m->m_off + m->m_len + n->m_len <= MMAXOFF) {
2714916Swnj 			bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
2724916Swnj 			    (u_int)n->m_len);
2734669Swnj 			m->m_len += n->m_len;
2744669Swnj 			n = m_free(n);
2754669Swnj 		} else {
2764669Swnj 			m->m_next = n;
2774669Swnj 			m = n;
2784669Swnj 			n = m->m_next;
2794669Swnj 		}
2804669Swnj }
2814669Swnj 
2824585Swnj m_adj(mp, len)
2834585Swnj 	struct mbuf *mp;
2844916Swnj 	register int len;
2854585Swnj {
2864585Swnj 	register struct mbuf *m, *n;
2874585Swnj 
2884585Swnj COUNT(M_ADJ);
2894585Swnj 	if ((m = mp) == NULL)
2904585Swnj 		return;
2914822Swnj 	if (len >= 0) {
2924585Swnj 		while (m != NULL && len > 0) {
2934822Swnj 			if (m->m_len <= len) {
2944585Swnj 				len -= m->m_len;
2954585Swnj 				m->m_len = 0;
2964585Swnj 				m = m->m_next;
2974822Swnj 			} else {
2984585Swnj 				m->m_len -= len;
2994585Swnj 				m->m_off += len;
3004585Swnj 				break;
3014585Swnj 			}
3024585Swnj 		}
3034822Swnj 	} else {
3044822Swnj 		/* a 2 pass algorithm might be better */
3054585Swnj 		len = -len;
3064585Swnj 		while (len > 0 && m->m_len != 0) {
3074585Swnj 			while (m != NULL && m->m_len != 0) {
3084585Swnj 				n = m;
3094585Swnj 				m = m->m_next;
3104585Swnj 			}
3114822Swnj 			if (n->m_len <= len) {
3124585Swnj 				len -= n->m_len;
3134585Swnj 				n->m_len = 0;
3144585Swnj 				m = mp;
3154822Swnj 			} else {
3164585Swnj 				n->m_len -= len;
3174585Swnj 				break;
3184585Swnj 			}
3194585Swnj 		}
3204585Swnj 	}
3214585Swnj }
322