xref: /csrg-svn/sys/kern/uipc_mbuf.c (revision 5228)
1*5228Swnj /*	uipc_mbuf.c	1.19	81/12/09	*/
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"
115090Swnj #include "../net/in_systm.h"		/* XXX */
124585Swnj #include "../h/vm.h"
134585Swnj 
14*5228Swnj mbinit()
15*5228Swnj {
16*5228Swnj 	register struct mbuf *m;
17*5228Swnj 	register i;
18*5228Swnj 
19*5228Swnj COUNT(MBINIT);
20*5228Swnj 	if (m_reserve(32) == 0)
21*5228Swnj 		goto bad;
22*5228Swnj 	if (m_clalloc(4, MPG_MBUFS) == 0)
23*5228Swnj 		goto bad;
24*5228Swnj 	if (m_clalloc(32, MPG_CLUSTERS) == 0)
25*5228Swnj 		goto bad;
26*5228Swnj 	return;
27*5228Swnj bad:
28*5228Swnj 	panic("mbinit");
29*5228Swnj }
30*5228Swnj 
31*5228Swnj caddr_t
32*5228Swnj m_clalloc(ncl, how)
33*5228Swnj 	register int ncl;
34*5228Swnj 	int how;
35*5228Swnj {
36*5228Swnj 	int npg, mbx;
37*5228Swnj 	register struct mbuf *m;
38*5228Swnj 	register int i;
39*5228Swnj 	int s;
40*5228Swnj 
41*5228Swnj COUNT(M_CLALLOC);
42*5228Swnj 	npg = ncl * CLSIZE;
43*5228Swnj 	mbx = rmalloc(mbmap, npg);
44*5228Swnj printf("ncl %d how %d npg %d mbx %d\n", ncl, how, npg, mbx);
45*5228Swnj 	if (mbx == 0)
46*5228Swnj 		return (0);
47*5228Swnj 	m = cltom(mbx / CLSIZE);
48*5228Swnj 	if (memall(&Mbmap[mbx], ncl * CLSIZE, proc, CSYS) == 0)
49*5228Swnj 		return (0);
50*5228Swnj 	vmaccess(&Mbmap[mbx], (caddr_t)m, npg);
51*5228Swnj printf("m %x &Mbmap[mbx] %x\n", m, &Mbmap[mbx]);
52*5228Swnj 	switch (how) {
53*5228Swnj 
54*5228Swnj 	case MPG_CLUSTERS:
55*5228Swnj 		s = splimp();
56*5228Swnj 		for (i = 0; i < ncl; i++) {
57*5228Swnj 			m->m_off = 0;
58*5228Swnj 			m->m_next = mclfree;
59*5228Swnj 			mclfree = m;
60*5228Swnj 			m += CLBYTES / sizeof (*m);
61*5228Swnj 			nmclfree++;
62*5228Swnj 		}
63*5228Swnj 		mbstat.m_clusters += ncl;
64*5228Swnj 		splx(s);
65*5228Swnj 		break;
66*5228Swnj 
67*5228Swnj 	case MPG_MBUFS:
68*5228Swnj 		for (i = ncl * CLBYTES / sizeof (*m); i > 0; i--) {
69*5228Swnj 			m->m_off = 0;
70*5228Swnj 			(void) m_free(m);
71*5228Swnj 			m++;
72*5228Swnj 		}
73*5228Swnj 		mbstat.m_clusters += ncl;
74*5228Swnj 	}
75*5228Swnj 	return ((caddr_t)m);
76*5228Swnj }
77*5228Swnj 
78*5228Swnj m_pgfree(addr, n)
79*5228Swnj 	caddr_t addr;
80*5228Swnj 	int n;
81*5228Swnj {
82*5228Swnj 
83*5228Swnj COUNT(M_PGFREE);
84*5228Swnj 	printf("m_pgfree %x %d\n", addr, n);
85*5228Swnj }
86*5228Swnj 
87*5228Swnj m_expand()
88*5228Swnj {
89*5228Swnj 
90*5228Swnj COUNT(M_EXPAND);
91*5228Swnj 	if (mbstat.m_bufs >= mbstat.m_hiwat)
92*5228Swnj 		return (0);
93*5228Swnj 	if (m_clalloc(1, MPG_MBUFS) == 0)
94*5228Swnj 		goto steal;
95*5228Swnj 	return (1);
96*5228Swnj steal:
97*5228Swnj 	/* should ask protocols to free code */
98*5228Swnj 	return (0);
99*5228Swnj }
100*5228Swnj 
101*5228Swnj /* NEED SOME WAY TO RELEASE SPACE */
102*5228Swnj 
103*5228Swnj /*
104*5228Swnj  * Space reservation routines
105*5228Swnj  */
1065015Sroot m_reserve(mbufs)
1075015Sroot 	int mbufs;
1084732Swnj {
1094732Swnj 
1105147Swnj 	if (mbstat.m_lowat + (mbufs>>1) > (NMBCLUSTERS-32) * CLBYTES)
1114732Swnj 		return (0);
1125016Swnj 	mbstat.m_hiwat += mbufs;
1135016Swnj 	mbstat.m_lowat = mbstat.m_hiwat >> 1;
1144916Swnj 	return (1);
1154732Swnj }
1164732Swnj 
1175015Sroot m_release(mbufs)
1185015Sroot 	int mbufs;
1194732Swnj {
1204732Swnj 
1215016Swnj 	mbstat.m_hiwat -= mbufs;
1225016Swnj 	mbstat.m_lowat = mbstat.m_hiwat >> 1;
1234732Swnj }
1244732Swnj 
125*5228Swnj /*
126*5228Swnj  * Space allocation routines.
127*5228Swnj  * These are also available as macros
128*5228Swnj  * for critical paths.
129*5228Swnj  */
1304585Swnj struct mbuf *
1314585Swnj m_get(canwait)
1324585Swnj 	int canwait;
1334585Swnj {
1344585Swnj 	register struct mbuf *m;
1354585Swnj 
1364585Swnj COUNT(M_GET);
1374585Swnj 	MGET(m, canwait);
1384585Swnj 	return (m);
1394585Swnj }
1404585Swnj 
1414585Swnj struct mbuf *
1424890Swnj m_getclr(canwait)
1434890Swnj 	int canwait;
1444890Swnj {
1454890Swnj 	register struct mbuf *m;
1464890Swnj 
1474890Swnj COUNT(M_GETCLR);
1484916Swnj 	m = m_get(canwait);
1494890Swnj 	if (m == 0)
1504890Swnj 		return (0);
1514890Swnj 	m->m_off = MMINOFF;
1524890Swnj 	bzero(mtod(m, caddr_t), MLEN);
1534890Swnj 	return (m);
1544890Swnj }
1554890Swnj 
1564890Swnj struct mbuf *
1574585Swnj m_free(m)
1584585Swnj 	struct mbuf *m;
1594585Swnj {
1604585Swnj 	register struct mbuf *n;
1614585Swnj 
1624585Swnj COUNT(M_FREE);
1634585Swnj 	MFREE(m, n);
1644585Swnj 	return (n);
1654585Swnj }
1664585Swnj 
1674916Swnj /*ARGSUSED*/
1684585Swnj struct mbuf *
1694585Swnj m_more(type)
1704585Swnj 	int type;
1714585Swnj {
1724585Swnj 	register struct mbuf *m;
1734585Swnj 
1744585Swnj COUNT(M_MORE);
1754585Swnj 	if (!m_expand()) {
1764822Swnj 		mbstat.m_drops++;
1774585Swnj 		return (NULL);
1784585Swnj 	}
1794916Swnj #define m_more(x) (panic("m_more"), (struct mbuf *)0)
1804916Swnj 	MGET(m, type);
1814585Swnj 	return (m);
1824585Swnj }
1834585Swnj 
1844669Swnj m_freem(m)
1854585Swnj 	register struct mbuf *m;
1864585Swnj {
1874585Swnj 	register struct mbuf *n;
1884927Swnj 	register int s;
1894585Swnj 
1904585Swnj COUNT(M_FREEM);
1914585Swnj 	if (m == NULL)
1924916Swnj 		return;
1934662Swnj 	s = splimp();
1944585Swnj 	do {
1954585Swnj 		MFREE(m, n);
1964585Swnj 	} while (m = n);
1974585Swnj 	splx(s);
1984585Swnj }
1994585Swnj 
200*5228Swnj /*
201*5228Swnj  * Mbuffer utility routines.
202*5228Swnj  */
2034927Swnj struct mbuf *
2044927Swnj m_copy(m, off, len)
2054927Swnj 	register struct mbuf *m;
2064927Swnj 	int off;
2074927Swnj 	register int len;
2084927Swnj {
2094927Swnj 	register struct mbuf *n, **np;
2104927Swnj 	struct mbuf *top, *p;
2114927Swnj COUNT(M_COPY);
2124927Swnj 
2134927Swnj 	if (len == 0)
2144927Swnj 		return (0);
2154927Swnj 	if (off < 0 || len < 0)
2164927Swnj 		panic("m_copy");
2174927Swnj 	while (off > 0) {
2184927Swnj 		if (m == 0)
2194927Swnj 			panic("m_copy");
2204927Swnj 		if (off < m->m_len)
2214927Swnj 			break;
2224927Swnj 		off -= m->m_len;
2234927Swnj 		m = m->m_next;
2244927Swnj 	}
2254927Swnj 	np = &top;
2264927Swnj 	top = 0;
2274927Swnj 	while (len > 0) {
2284927Swnj 		MGET(n, 1);
2294927Swnj 		*np = n;
2304927Swnj 		if (n == 0)
2314927Swnj 			goto nospace;
2324927Swnj 		if (m == 0)
2334927Swnj 			panic("m_copy");
2344927Swnj 		n->m_len = MIN(len, m->m_len - off);
2354927Swnj 		if (m->m_off > MMAXOFF) {
2364927Swnj 			p = mtod(m, struct mbuf *);
2374927Swnj 			n->m_off = ((int)p - (int)n) + off;
2385090Swnj 			mclrefcnt[mtocl(p)]++;
2394927Swnj 		} else {
2404927Swnj 			n->m_off = MMINOFF;
2414927Swnj 			bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
2424927Swnj 			    (unsigned)n->m_len);
2434927Swnj 		}
2444927Swnj 		len -= n->m_len;
2454927Swnj 		off = 0;
2464927Swnj 		m = m->m_next;
2474927Swnj 		np = &n->m_next;
2484927Swnj 	}
2494927Swnj 	return (top);
2504927Swnj nospace:
2514927Swnj 	printf("m_copy: no space\n");
2524927Swnj 	m_freem(top);
2534927Swnj 	return (0);
2544927Swnj }
2554927Swnj 
2564669Swnj m_cat(m, n)
2574669Swnj 	register struct mbuf *m, *n;
2584669Swnj {
2594669Swnj 
2604669Swnj 	while (m->m_next)
2614669Swnj 		m = m->m_next;
2624669Swnj 	while (n)
2634669Swnj 		if (m->m_off + m->m_len + n->m_len <= MMAXOFF) {
2644916Swnj 			bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
2654916Swnj 			    (u_int)n->m_len);
2664669Swnj 			m->m_len += n->m_len;
2674669Swnj 			n = m_free(n);
2684669Swnj 		} else {
2694669Swnj 			m->m_next = n;
2704669Swnj 			m = n;
2714669Swnj 			n = m->m_next;
2724669Swnj 		}
2734669Swnj }
2744669Swnj 
2754585Swnj m_adj(mp, len)
2764585Swnj 	struct mbuf *mp;
2774916Swnj 	register int len;
2784585Swnj {
2794585Swnj 	register struct mbuf *m, *n;
2804585Swnj 
2814585Swnj COUNT(M_ADJ);
2824585Swnj 	if ((m = mp) == NULL)
2834585Swnj 		return;
2844822Swnj 	if (len >= 0) {
2854585Swnj 		while (m != NULL && len > 0) {
2864822Swnj 			if (m->m_len <= len) {
2874585Swnj 				len -= m->m_len;
2884585Swnj 				m->m_len = 0;
2894585Swnj 				m = m->m_next;
2904822Swnj 			} else {
2914585Swnj 				m->m_len -= len;
2924585Swnj 				m->m_off += len;
2934585Swnj 				break;
2944585Swnj 			}
2954585Swnj 		}
2964822Swnj 	} else {
2974822Swnj 		/* a 2 pass algorithm might be better */
2984585Swnj 		len = -len;
2994585Swnj 		while (len > 0 && m->m_len != 0) {
3004585Swnj 			while (m != NULL && m->m_len != 0) {
3014585Swnj 				n = m;
3024585Swnj 				m = m->m_next;
3034585Swnj 			}
3044822Swnj 			if (n->m_len <= len) {
3054585Swnj 				len -= n->m_len;
3064585Swnj 				n->m_len = 0;
3074585Swnj 				m = mp;
3084822Swnj 			} else {
3094585Swnj 				n->m_len -= len;
3104585Swnj 				break;
3114585Swnj 			}
3124585Swnj 		}
3134585Swnj 	}
3144585Swnj }
315*5228Swnj 
316*5228Swnj /*ARGSUSED*/
317*5228Swnj m_pullup(m, len)
318*5228Swnj 	struct mbuf *m;
319*5228Swnj 	int len;
320*5228Swnj {
321*5228Swnj 
322*5228Swnj 	return (0);
323*5228Swnj }
324