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