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