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