xref: /csrg-svn/sys/kern/uipc_mbuf.c (revision 4950)
1 /*	uipc_mbuf.c	1.12	81/11/20	*/
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;
92 
93 COUNT(M_FREEM);
94 	if (m == NULL)
95 		return;
96 	s = splimp();
97 	do {
98 		MFREE(m, n);
99 	} while (m = n);
100 	splx(s);
101 }
102 
103 /*ARGSUSED*/
104 m_pullup(m, len)
105 	struct mbuf *m;
106 	int len;
107 {
108 
109 	return (0);
110 }
111 
112 struct mbuf *
113 m_copy(m, off, len)
114 	register struct mbuf *m;
115 	int off;
116 	register int len;
117 {
118 	register struct mbuf *n, **np;
119 	struct mbuf *top, *p;
120 COUNT(M_COPY);
121 
122 	if (len == 0)
123 		return (0);
124 	if (off < 0 || len < 0)
125 		panic("m_copy");
126 	while (off > 0) {
127 		if (m == 0)
128 			panic("m_copy");
129 		if (off < m->m_len)
130 			break;
131 		off -= m->m_len;
132 		m = m->m_next;
133 	}
134 	np = &top;
135 	top = 0;
136 	while (len > 0) {
137 		MGET(n, 1);
138 		*np = n;
139 		if (n == 0)
140 			goto nospace;
141 		if (m == 0)
142 			panic("m_copy");
143 		n->m_len = MIN(len, m->m_len - off);
144 		if (m->m_off > MMAXOFF) {
145 			p = mtod(m, struct mbuf *);
146 			n->m_off = ((int)p - (int)n) + off;
147 			mprefcnt[mtopf(p)]++;
148 		} else {
149 			n->m_off = MMINOFF;
150 			bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
151 			    (unsigned)n->m_len);
152 		}
153 		len -= n->m_len;
154 		off = 0;
155 		m = m->m_next;
156 		np = &n->m_next;
157 	}
158 	return (top);
159 nospace:
160 	printf("m_copy: no space\n");
161 	m_freem(top);
162 	return (0);
163 }
164 
165 mbinit()
166 {
167 	register struct mbuf *m;
168 	register i;
169 
170 COUNT(MBUFINIT);
171 	m = (struct mbuf *)&mbutl[0];  /* ->start of buffer virt mem */
172 	(void) vmemall(&Mbmap[0], 2, proc, CSYS);
173 	vmaccess(&Mbmap[0], (caddr_t)m, 2);
174 	for (i=0; i < NMBPG; i++) {
175 		m->m_off = 0;
176 		m_free(m);
177 		m++;
178 	}
179 	(void) pg_alloc(3);
180 	mbstat.m_pages = 4;
181 	mbstat.m_bufs = 32;
182 	mbstat.m_lowat = 16;
183 	mbstat.m_hiwat = 32;
184 	{ int j,k,n;
185 	n = 32;
186 	k = n << 1;
187 	if ((i = rmalloc(mbmap, n)) == 0)
188 		panic("mbinit");
189 	j = i<<1;
190 	m = pftom(i);
191 	/* should use vmemall sometimes */
192 	if (memall(&Mbmap[j], k, proc, CSYS) == 0) {
193 		printf("botch\n");
194 		return;
195 	}
196 	vmaccess(&Mbmap[j], (caddr_t)m, k);
197 	for (j=0; j < n; j++) {
198 		m->m_off = 0;
199 		m->m_next = mpfree;
200 		mpfree = m;
201 		m += NMBPG;
202 		nmpfree++;
203 	}
204 	}
205 }
206 
207 pg_alloc(n)
208 	register int n;
209 {
210 	register i, j, k;
211 	register struct mbuf *m;
212 	int bufs, s;
213 
214 COUNT(PG_ALLOC);
215 	k = n << 1;
216 	if ((i = rmalloc(mbmap, n)) == 0)
217 		return (0);
218 	j = i<<1;
219 	m = pftom(i);
220 	/* should use vmemall sometimes */
221 	if (memall(&Mbmap[j], k, proc, CSYS) == 0)
222 		return (0);
223 	vmaccess(&Mbmap[j], (caddr_t)m, k);
224 	bufs = n << 3;
225 	s = splimp();
226 	for (j=0; j < bufs; j++) {
227 		m->m_off = 0;
228 		m_free(m);
229 		m++;
230 	}
231 	splx(s);
232 	mbstat.m_pages += n;
233 	return (1);
234 }
235 
236 m_expand()
237 {
238 	register i;
239 	int need, needp, needs;
240 
241 COUNT(M_EXPAND);
242 	needs = need = mbstat.m_hiwat - mbstat.m_bufs;
243 	needp = need >> 3;
244 	if (pg_alloc(needp))
245 		return (1);
246 	for (i=0; i < needp; i++, need -= NMBPG)
247 		if (pg_alloc(1) == 0)
248 			goto steal;
249 	return (need < needs);
250 steal:
251 	/* while (not enough) ask protocols to free code */
252 	;
253 	return (0);
254 }
255 
256 #ifdef notdef
257 m_relse()
258 {
259 
260 COUNT(M_RELSE);
261 }
262 #endif
263 
264 m_cat(m, n)
265 	register struct mbuf *m, *n;
266 {
267 
268 	while (m->m_next)
269 		m = m->m_next;
270 	while (n)
271 		if (m->m_off + m->m_len + n->m_len <= MMAXOFF) {
272 			bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
273 			    (u_int)n->m_len);
274 			m->m_len += n->m_len;
275 			n = m_free(n);
276 		} else {
277 			m->m_next = n;
278 			m = n;
279 			n = m->m_next;
280 		}
281 }
282 
283 m_adj(mp, len)
284 	struct mbuf *mp;
285 	register int len;
286 {
287 	register struct mbuf *m, *n;
288 
289 COUNT(M_ADJ);
290 	if ((m = mp) == NULL)
291 		return;
292 	if (len >= 0) {
293 		while (m != NULL && len > 0) {
294 			if (m->m_len <= len) {
295 				len -= m->m_len;
296 				m->m_len = 0;
297 				m = m->m_next;
298 			} else {
299 				m->m_len -= len;
300 				m->m_off += len;
301 				break;
302 			}
303 		}
304 	} else {
305 		/* a 2 pass algorithm might be better */
306 		len = -len;
307 		while (len > 0 && m->m_len != 0) {
308 			while (m != NULL && m->m_len != 0) {
309 				n = m;
310 				m = m->m_next;
311 			}
312 			if (n->m_len <= len) {
313 				len -= n->m_len;
314 				n->m_len = 0;
315 				m = mp;
316 			} else {
317 				n->m_len -= len;
318 				break;
319 			}
320 		}
321 	}
322 }
323