xref: /csrg-svn/sys/kern/uipc_mbuf.c (revision 4662)
1 /* uipc_mbuf.c 1.5 81/10/29 */
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/tcp.h"
14 #include "../inet/ip.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)                      /* free mbuf chain headed by 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 		MFREE(m, n);
69 		cnt++;
70 	} while (m = n);
71 	splx(s);
72 	return (cnt);
73 }
74 
75 
76 mbufinit()                      /* init network buffer mgmt system */
77 {
78 	register struct mbuf *m;
79 	register i;
80 
81 COUNT(MBUFINIT);
82 	m = (struct mbuf *)&netutl[0];  /* ->start of buffer virt mem */
83 	vmemall(&Netmap[0], 2, proc, CSYS);
84 	vmaccess(&Netmap[0], m, 2);
85 	for (i=0; i < NMBPG; i++) {
86 		m->m_off = 0;
87 		m_free(m);
88 		m++;
89 	}
90 	pg_alloc(3);
91 	mbstat.m_pages = 4;
92 	mbstat.m_bufs = 32;
93 	mbstat.m_lowat = 16;
94 	mbstat.m_hiwat = 32;
95 }
96 
97 pg_alloc(n)
98 	register int n;
99 {
100 	register i, j, k;
101 	register struct mbuf *m;
102 	int bufs, s;
103 
104 COUNT(PG_ALLOC);
105 	k = n << 1;
106 	if ((i = rmalloc(netmap, n)) == 0)
107 		return (0);
108 	j = i<<1;
109 	m = pftom(i);
110 	/* should use vmemall sometimes */
111 	if (memall(&Netmap[j], k, proc, CSYS) == 0)
112 		return (0);
113 	vmaccess(&Netmap[j], (caddr_t)m, k);
114 	bufs = n << 3;
115 	s = splimp();
116 	for (j=0; j < bufs; j++) {
117 		m->m_off = 0;
118 		m_free(m);
119 		m++;
120 	}
121 	splx(s);
122 	mbstat.m_pages += n;
123 	return (1);
124 }
125 
126 m_expand()
127 {
128 	register i;
129 	register struct ipq *fp;
130 	register struct ip *q;
131 	register struct tcb *tp;
132 	register struct mbuf *m, *n;
133 	int need, needp, needs;
134 
135 COUNT(M_EXPAND);
136 	needs = need = mbstat.m_hiwat - mbstat.m_bufs;
137 	needp = need >> 3;
138 	if (pg_alloc(needp))
139 		return (1);
140 	for (i=0; i < needp; i++, need-=NMBPG)
141 		if (needp == 1 || pg_alloc(1) == 0)		/* ??? */
142 			goto steal;
143 	return (need < needs);
144 steal:
145 #ifdef notdef
146 	/* free fragments */
147 	/* free unacks */
148 #endif
149 	return (need < needs);
150 }
151 
152 #ifdef notdef
153 m_relse()
154 {
155 COUNT(M_RELSE);
156 
157 }
158 #endif
159 
160 struct mbuf *
161 m_adj(mp, len)
162 	struct mbuf *mp;
163 	register len;
164 {
165 	register struct mbuf *m, *n;
166 
167 COUNT(M_ADJ);
168 	if ((m = mp) == NULL)
169 		return;
170 	if (len >= 0) {                 /* adjust from top of msg chain */
171 		while (m != NULL && len > 0) {
172 			if (m->m_len <= len) {          /* free this mbuf */
173 				len -= m->m_len;
174 				m->m_len = 0;
175 				m = m->m_next;
176 			} else {                        /* adjust mbuf */
177 				m->m_len -= len;
178 				m->m_off += len;
179 				break;
180 			}
181 		}
182 
183 	} else {                        /* adjust from bottom of msg chain */
184 		len = -len;
185 		while (len > 0 && m->m_len != 0) {
186 			/* find end of chain */
187 			while (m != NULL && m->m_len != 0) {
188 				n = m;
189 				m = m->m_next;
190 			}
191 			if (n->m_len <= len) {          /* last mbuf */
192 				len -= n->m_len;
193 				n->m_len = 0;
194 				m = mp;
195 			} else {                        /* adjust length */
196 				n->m_len -= len;
197 				break;
198 			}
199 		}
200 	}
201 }
202 
203 /*
204  * convert mbuf virtual to physical addr for uballoc
205  */
206 mtophys(m)
207 	register struct mbuf *m;
208 {
209 	register i;
210 	register unsigned long addr;
211 	register struct pte *pte;
212 
213 COUNT(MTOPHYS);
214 	i = (((int)m & ~PGOFSET) - (int)netutl) >> PGSHIFT;
215 	pte = &Netmap[i];
216 	addr = (pte->pg_pfnum << PGSHIFT) | ((int)m & PGOFSET);
217 	return (addr);
218 }
219 
220 m_cat(m, n)
221 	register struct mbuf *m, *n;
222 {
223 
224 	while (m->m_next)
225 		m = m->m_next;
226 	while (n)
227 		if (m->m_off + m->m_len + n->m_len <= MMAXOFF) {
228 			bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, n->m_len);
229 			m->m_len += n->m_len;
230 			n = m_free(n);
231 		} else {
232 			m->m_next = n;
233 			m = n;
234 			n = m->m_next;
235 		}
236 }
237