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