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