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