xref: /csrg-svn/sys/kern/uipc_mbuf.c (revision 4916)
1 /*	uipc_mbuf.c	1.10	81/11/16	*/
2 
3 #include "../h/param.h"
4 #include "../h/dir.h"
5 #include "../h/user.h"
6 #include "../h/proc.h"
7 #include "../h/pte.h"
8 #include "../h/cmap.h"
9 #include "../h/map.h"
10 #include "../h/mbuf.h"
11 #include "../net/inet_systm.h"		/* XXX */
12 #include "../h/vm.h"
13 
14 m_reserve(mbufs)
15 	int mbufs;
16 {
17 
18 	if (mbstat.m_lowat + mbufs > NMBPAGES * NMBPG - 32)
19 		return (0);
20 	mbstat.m_lowat += mbufs;
21 	mbstat.m_hiwat = 2 * mbstat.m_lowat;
22 	return (1);
23 }
24 
25 m_release(mbufs)
26 	int mbufs;
27 {
28 
29 	mbstat.m_lowat -= mbufs;
30 	mbstat.m_hiwat = 2 * mbstat.m_lowat;
31 }
32 
33 struct mbuf *
34 m_get(canwait)
35 	int canwait;
36 {
37 	register struct mbuf *m;
38 
39 COUNT(M_GET);
40 	MGET(m, canwait);
41 	return (m);
42 }
43 
44 struct mbuf *
45 m_getclr(canwait)
46 	int canwait;
47 {
48 	register struct mbuf *m;
49 
50 COUNT(M_GETCLR);
51 	m = m_get(canwait);
52 	if (m == 0)
53 		return (0);
54 	m->m_off = MMINOFF;
55 	bzero(mtod(m, caddr_t), MLEN);
56 	return (m);
57 }
58 
59 struct mbuf *
60 m_free(m)
61 	struct mbuf *m;
62 {
63 	register struct mbuf *n;
64 
65 COUNT(M_FREE);
66 	MFREE(m, n);
67 	return (n);
68 }
69 
70 /*ARGSUSED*/
71 struct mbuf *
72 m_more(type)
73 	int type;
74 {
75 	register struct mbuf *m;
76 
77 COUNT(M_MORE);
78 	if (!m_expand()) {
79 		mbstat.m_drops++;
80 		return (NULL);
81 	}
82 #define m_more(x) (panic("m_more"), (struct mbuf *)0)
83 	MGET(m, type);
84 	return (m);
85 }
86 
87 m_freem(m)
88 	register struct mbuf *m;
89 {
90 	register struct mbuf *n;
91 	register int s, i;
92 
93 COUNT(M_FREEM);
94 	if (m == NULL)
95 		return;
96 	i = 0;
97 	s = splimp();
98 	do {
99 		if (m->m_off > MMAXOFF)
100 			i += NMBPG;
101 		i++;
102 		MFREE(m, n);
103 	} while (m = n);
104 	splx(s);
105 	return;
106 }
107 
108 mbinit()
109 {
110 	register struct mbuf *m;
111 	register i;
112 
113 COUNT(MBUFINIT);
114 	m = (struct mbuf *)&mbutl[0];  /* ->start of buffer virt mem */
115 	(void) vmemall(&Mbmap[0], 2, proc, CSYS);
116 	vmaccess(&Mbmap[0], (caddr_t)m, 2);
117 	for (i=0; i < NMBPG; i++) {
118 		m->m_off = 0;
119 		m_free(m);
120 		m++;
121 	}
122 	(void) pg_alloc(3);
123 	mbstat.m_pages = 4;
124 	mbstat.m_bufs = 32;
125 	mbstat.m_lowat = 16;
126 	mbstat.m_hiwat = 32;
127 	{ int j,k,n;
128 	n = 32;
129 	k = n << 1;
130 	if ((i = rmalloc(mbmap, n)) == 0)
131 		panic("mbinit");
132 	j = i<<1;
133 	m = pftom(i);
134 	/* should use vmemall sometimes */
135 	if (memall(&Mbmap[j], k, proc, CSYS) == 0) {
136 		printf("botch\n");
137 		return;
138 	}
139 	vmaccess(&Mbmap[j], (caddr_t)m, k);
140 	for (j=0; j < n; j++) {
141 		m->m_off = 0;
142 		m->m_next = mpfree;
143 		mpfree = m;
144 		m += NMBPG;
145 		nmpfree++;
146 	}
147 	}
148 }
149 
150 pg_alloc(n)
151 	register int n;
152 {
153 	register i, j, k;
154 	register struct mbuf *m;
155 	int bufs, s;
156 
157 COUNT(PG_ALLOC);
158 	k = n << 1;
159 	if ((i = rmalloc(mbmap, n)) == 0)
160 		return (0);
161 	j = i<<1;
162 	m = pftom(i);
163 	/* should use vmemall sometimes */
164 	if (memall(&Mbmap[j], k, proc, CSYS) == 0)
165 		return (0);
166 	vmaccess(&Mbmap[j], (caddr_t)m, k);
167 	bufs = n << 3;
168 	s = splimp();
169 	for (j=0; j < bufs; j++) {
170 		m->m_off = 0;
171 		m_free(m);
172 		m++;
173 	}
174 	splx(s);
175 	mbstat.m_pages += n;
176 	return (1);
177 }
178 
179 m_expand()
180 {
181 	register i;
182 	int need, needp, needs;
183 
184 COUNT(M_EXPAND);
185 	needs = need = mbstat.m_hiwat - mbstat.m_bufs;
186 	needp = need >> 3;
187 	if (pg_alloc(needp))
188 		return (1);
189 	for (i=0; i < needp; i++, need -= NMBPG)
190 		if (pg_alloc(1) == 0)
191 			goto steal;
192 	return (need < needs);
193 steal:
194 	/* while (not enough) ask protocols to free code */
195 	;
196 	return (0);
197 }
198 
199 #ifdef notdef
200 m_relse()
201 {
202 
203 COUNT(M_RELSE);
204 }
205 #endif
206 
207 m_cat(m, n)
208 	register struct mbuf *m, *n;
209 {
210 
211 	while (m->m_next)
212 		m = m->m_next;
213 	while (n)
214 		if (m->m_off + m->m_len + n->m_len <= MMAXOFF) {
215 			bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
216 			    (u_int)n->m_len);
217 			m->m_len += n->m_len;
218 			n = m_free(n);
219 		} else {
220 			m->m_next = n;
221 			m = n;
222 			n = m->m_next;
223 		}
224 }
225 
226 m_adj(mp, len)
227 	struct mbuf *mp;
228 	register int len;
229 {
230 	register struct mbuf *m, *n;
231 
232 COUNT(M_ADJ);
233 	if ((m = mp) == NULL)
234 		return;
235 	if (len >= 0) {
236 		while (m != NULL && len > 0) {
237 			if (m->m_len <= len) {
238 				len -= m->m_len;
239 				m->m_len = 0;
240 				m = m->m_next;
241 			} else {
242 				m->m_len -= len;
243 				m->m_off += len;
244 				break;
245 			}
246 		}
247 	} else {
248 		/* a 2 pass algorithm might be better */
249 		len = -len;
250 		while (len > 0 && m->m_len != 0) {
251 			while (m != NULL && m->m_len != 0) {
252 				n = m;
253 				m = m->m_next;
254 			}
255 			if (n->m_len <= len) {
256 				len -= n->m_len;
257 				n->m_len = 0;
258 				m = mp;
259 			} else {
260 				n->m_len -= len;
261 				break;
262 			}
263 		}
264 	}
265 }
266