xref: /csrg-svn/sys/kern/uipc_mbuf.c (revision 5147)
1 /*	uipc_mbuf.c	1.18	81/11/30	*/
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/in_systm.h"		/* XXX */
12 #include "../h/vm.h"
13 
14 m_reserve(mbufs)
15 	int mbufs;
16 {
17 
18 /*
19 	printf("reserve %d\n", mbufs);
20 */
21 	if (mbstat.m_lowat + (mbufs>>1) > (NMBCLUSTERS-32) * CLBYTES)
22 		return (0);
23 	mbstat.m_hiwat += mbufs;
24 	mbstat.m_lowat = mbstat.m_hiwat >> 1;
25 	return (1);
26 }
27 
28 m_release(mbufs)
29 	int mbufs;
30 {
31 
32 /*
33 	printf("release %d\n", mbufs);
34 */
35 	mbstat.m_hiwat -= mbufs;
36 	mbstat.m_lowat = mbstat.m_hiwat >> 1;
37 }
38 
39 struct mbuf *
40 m_get(canwait)
41 	int canwait;
42 {
43 	register struct mbuf *m;
44 
45 COUNT(M_GET);
46 	MGET(m, canwait);
47 	return (m);
48 }
49 
50 struct mbuf *
51 m_getclr(canwait)
52 	int canwait;
53 {
54 	register struct mbuf *m;
55 
56 COUNT(M_GETCLR);
57 	m = m_get(canwait);
58 	if (m == 0)
59 		return (0);
60 	m->m_off = MMINOFF;
61 	bzero(mtod(m, caddr_t), MLEN);
62 	return (m);
63 }
64 
65 struct mbuf *
66 m_free(m)
67 	struct mbuf *m;
68 {
69 	register struct mbuf *n;
70 
71 COUNT(M_FREE);
72 	MFREE(m, n);
73 	return (n);
74 }
75 
76 /*ARGSUSED*/
77 struct mbuf *
78 m_more(type)
79 	int type;
80 {
81 	register struct mbuf *m;
82 
83 COUNT(M_MORE);
84 	if (!m_expand()) {
85 		mbstat.m_drops++;
86 		return (NULL);
87 	}
88 #define m_more(x) (panic("m_more"), (struct mbuf *)0)
89 	MGET(m, type);
90 	return (m);
91 }
92 
93 m_freem(m)
94 	register struct mbuf *m;
95 {
96 	register struct mbuf *n;
97 	register int s;
98 
99 COUNT(M_FREEM);
100 	if (m == NULL)
101 		return;
102 	s = splimp();
103 	do {
104 		MFREE(m, n);
105 	} while (m = n);
106 	splx(s);
107 }
108 
109 /*ARGSUSED*/
110 m_pullup(m, len)
111 	struct mbuf *m;
112 	int len;
113 {
114 
115 	return (0);
116 }
117 
118 struct mbuf *
119 m_copy(m, off, len)
120 	register struct mbuf *m;
121 	int off;
122 	register int len;
123 {
124 	register struct mbuf *n, **np;
125 	struct mbuf *top, *p;
126 COUNT(M_COPY);
127 
128 	if (len == 0)
129 		return (0);
130 	if (off < 0 || len < 0)
131 		panic("m_copy");
132 	while (off > 0) {
133 		if (m == 0)
134 			panic("m_copy");
135 		if (off < m->m_len)
136 			break;
137 		off -= m->m_len;
138 		m = m->m_next;
139 	}
140 	np = &top;
141 	top = 0;
142 	while (len > 0) {
143 		MGET(n, 1);
144 		*np = n;
145 		if (n == 0)
146 			goto nospace;
147 		if (m == 0)
148 			panic("m_copy");
149 		n->m_len = MIN(len, m->m_len - off);
150 		if (m->m_off > MMAXOFF) {
151 			p = mtod(m, struct mbuf *);
152 			n->m_off = ((int)p - (int)n) + off;
153 			mclrefcnt[mtocl(p)]++;
154 		} else {
155 			n->m_off = MMINOFF;
156 			bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
157 			    (unsigned)n->m_len);
158 		}
159 		len -= n->m_len;
160 		off = 0;
161 		m = m->m_next;
162 		np = &n->m_next;
163 	}
164 	return (top);
165 nospace:
166 	printf("m_copy: no space\n");
167 	m_freem(top);
168 	return (0);
169 }
170 
171 mbinit()
172 {
173 	register struct mbuf *m;
174 	register i;
175 
176 COUNT(MBUFINIT);
177 	m = (struct mbuf *)&mbutl[0];  /* ->start of buffer virt mem */
178 	(void) vmemall(&Mbmap[0], 2, proc, CSYS);
179 	vmaccess(&Mbmap[0], (caddr_t)m, 2);
180 	for (i=0; i < CLBYTES / sizeof (struct mbuf); i++) {
181 		m->m_off = 0;
182 		(void) m_free(m);
183 		m++;
184 	}
185 	(void) m_pgalloc(3);
186 	mbstat.m_pages = 4;
187 	mbstat.m_bufs = 32;
188 	mbstat.m_lowat = 16;
189 	mbstat.m_hiwat = 32;
190 	{ int j,k,n;
191 	n = 32;
192 	k = n << 1;
193 	if ((i = rmalloc(mbmap, n)) == 0)
194 		panic("mbinit");
195 	j = i<<1;
196 	m = cltom(i);
197 	/* should use vmemall sometimes */
198 	if (memall(&Mbmap[j], k, proc, CSYS) == 0) {
199 		printf("botch\n");
200 		return;
201 	}
202 	vmaccess(&Mbmap[j], (caddr_t)m, k);
203 	for (j=0; j < n; j++) {
204 		m->m_off = 0;
205 		m->m_next = mclfree;
206 		mclfree = m;
207 		m += CLBYTES / sizeof (*m);
208 		nmclfree++;
209 	}
210 	}
211 }
212 
213 m_pgalloc(n)
214 	register int n;
215 {
216 	register i, j, k;
217 	register struct mbuf *m;
218 	int bufs, s;
219 
220 COUNT(M_PGALLOC);
221 	k = n << 1;
222 	if ((i = rmalloc(mbmap, n)) == 0)
223 		return (0);
224 	j = i<<1;
225 	m = cltom(i);
226 	/* should use vmemall sometimes */
227 	if (memall(&Mbmap[j], k, proc, CSYS) == 0)
228 		return (0);
229 	vmaccess(&Mbmap[j], (caddr_t)m, k);
230 	bufs = n << 3;
231 	s = splimp();
232 	for (j=0; j < bufs; j++) {
233 		m->m_off = 0;
234 		(void) m_free(m);
235 		m++;
236 	}
237 	splx(s);
238 	mbstat.m_pages += n;
239 	return (1);
240 }
241 
242 /*ARGSUSED*/
243 m_pgfree(addr, n)
244 	caddr_t addr;
245 	int n;
246 {
247 
248 COUNT(M_PGFREE);
249 	printf("m_pgfree %x %d\n", addr, n);
250 }
251 
252 m_expand()
253 {
254 	register i;
255 	int need, needp, needs;
256 
257 COUNT(M_EXPAND);
258 	needs = need = mbstat.m_hiwat - mbstat.m_bufs;
259 	needp = need >> 3;
260 	if (m_pgalloc(needp))
261 		return (1);
262 	for (i=0; i < needp; i++, need -= CLBYTES / sizeof (struct mbuf))
263 		if (m_pgalloc(1) == 0)
264 			goto steal;
265 	return (need < needs);
266 steal:
267 	/* while (not enough) ask protocols to free code */
268 	;
269 	return (0);
270 }
271 
272 #ifdef notdef
273 m_relse()
274 {
275 
276 COUNT(M_RELSE);
277 }
278 #endif
279 
280 m_cat(m, n)
281 	register struct mbuf *m, *n;
282 {
283 
284 	while (m->m_next)
285 		m = m->m_next;
286 	while (n)
287 		if (m->m_off + m->m_len + n->m_len <= MMAXOFF) {
288 			bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
289 			    (u_int)n->m_len);
290 			m->m_len += n->m_len;
291 			n = m_free(n);
292 		} else {
293 			m->m_next = n;
294 			m = n;
295 			n = m->m_next;
296 		}
297 }
298 
299 m_adj(mp, len)
300 	struct mbuf *mp;
301 	register int len;
302 {
303 	register struct mbuf *m, *n;
304 
305 COUNT(M_ADJ);
306 	if ((m = mp) == NULL)
307 		return;
308 	if (len >= 0) {
309 		while (m != NULL && len > 0) {
310 			if (m->m_len <= len) {
311 				len -= m->m_len;
312 				m->m_len = 0;
313 				m = m->m_next;
314 			} else {
315 				m->m_len -= len;
316 				m->m_off += len;
317 				break;
318 			}
319 		}
320 	} else {
321 		/* a 2 pass algorithm might be better */
322 		len = -len;
323 		while (len > 0 && m->m_len != 0) {
324 			while (m != NULL && m->m_len != 0) {
325 				n = m;
326 				m = m->m_next;
327 			}
328 			if (n->m_len <= len) {
329 				len -= n->m_len;
330 				n->m_len = 0;
331 				m = mp;
332 			} else {
333 				n->m_len -= len;
334 				break;
335 			}
336 		}
337 	}
338 }
339