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