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