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