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