/* uipc_mbuf.c 1.6 81/10/30 */ #include "../h/param.h" #include "../h/dir.h" #include "../h/user.h" #include "../h/proc.h" #include "../h/pte.h" #include "../h/cmap.h" #include "../h/map.h" #include "../h/mbuf.h" #include "../inet/inet.h" #include "../inet/inet_systm.h" #include "../inet/ip.h" #include "../inet/tcp.h" #include "../h/vm.h" struct mbuf * m_get(canwait) int canwait; { register struct mbuf *m; COUNT(M_GET); MGET(m, canwait); return (m); } struct mbuf * m_free(m) struct mbuf *m; { register struct mbuf *n; COUNT(M_FREE); MFREE(m, n); return (n); } struct mbuf * m_more(type) int type; { int s; register struct mbuf *m; COUNT(M_MORE); if (!m_expand()) { netstat.m_drops++; return (NULL); } #define m_more(x) ((struct mbuf *)panic("m_more")) MGET(m, 0); return (m); } m_freem(m) register struct mbuf *m; { register struct mbuf *n; register int s, cnt; COUNT(M_FREEM); if (m == NULL) return (0); cnt = 0; s = splimp(); do { if (m->m_off > MMAXOFF) cnt += NMBPG; cnt++; MFREE(m, n); } while (m = n); splx(s); return (cnt); } mbufinit() { register struct mbuf *m; register i; COUNT(MBUFINIT); m = (struct mbuf *)&netutl[0]; /* ->start of buffer virt mem */ vmemall(&Netmap[0], 2, proc, CSYS); vmaccess(&Netmap[0], m, 2); for (i=0; i < NMBPG; i++) { m->m_off = 0; m_free(m); m++; } pg_alloc(3); mbstat.m_pages = 4; mbstat.m_bufs = 32; mbstat.m_lowat = 16; mbstat.m_hiwat = 32; { int i,j,k,n; n = 32; k = n << 1; if ((i = rmalloc(netmap, n)) == 0) return (0); j = i<<1; m = pftom(i); /* should use vmemall sometimes */ if (memall(&Netmap[j], k, proc, CSYS) == 0) { printf("botch\n"); return; } vmaccess(&Netmap[j], (caddr_t)m, k); for (j=0; j < n; j++) { m->m_off = 0; m->m_next = mpfree; mpfree = m; m += NMBPG; nmpfree++; } } } pg_alloc(n) register int n; { register i, j, k; register struct mbuf *m; int bufs, s; COUNT(PG_ALLOC); k = n << 1; if ((i = rmalloc(netmap, n)) == 0) return (0); j = i<<1; m = pftom(i); /* should use vmemall sometimes */ if (memall(&Netmap[j], k, proc, CSYS) == 0) return (0); vmaccess(&Netmap[j], (caddr_t)m, k); bufs = n << 3; s = splimp(); for (j=0; j < bufs; j++) { m->m_off = 0; m_free(m); m++; } splx(s); mbstat.m_pages += n; return (1); } m_expand() { register i; register struct mbuf *m, *n; int need, needp, needs; COUNT(M_EXPAND); needs = need = mbstat.m_hiwat - mbstat.m_bufs; needp = need >> 3; if (pg_alloc(needp)) return (1); for (i=0; i < needp; i++, need -= NMBPG) if (pg_alloc(1) == 0) goto steal; return (need < needs); steal: /* while (not enough) ask protocols to free code */ ; } #ifdef notdef m_relse() { COUNT(M_RELSE); } #endif m_cat(m, n) register struct mbuf *m, *n; { while (m->m_next) m = m->m_next; while (n) if (m->m_off + m->m_len + n->m_len <= MMAXOFF) { bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, n->m_len); m->m_len += n->m_len; n = m_free(n); } else { m->m_next = n; m = n; n = m->m_next; } } m_adj(mp, len) struct mbuf *mp; register len; { register struct mbuf *m, *n; /* for (m = mp; m; m = m->m_next) { printf("a %x %d\n", m, m->m_len); } */ COUNT(M_ADJ); if ((m = mp) == NULL) return; if (len >= 0) { /* adjust from top of msg chain */ while (m != NULL && len > 0) { if (m->m_len <= len) { /* free this mbuf */ len -= m->m_len; m->m_len = 0; m = m->m_next; } else { /* adjust mbuf */ m->m_len -= len; m->m_off += len; break; } } } else { /* adjust from bottom of msg chain */ len = -len; while (len > 0 && m->m_len != 0) { /* find end of chain */ while (m != NULL && m->m_len != 0) { n = m; m = m->m_next; } if (n->m_len <= len) { /* last mbuf */ len -= n->m_len; n->m_len = 0; m = mp; } else { /* adjust length */ n->m_len -= len; break; } } } } /* * convert mbuf virtual to physical addr for uballoc */ mtophys(m) register struct mbuf *m; { register i; register unsigned long addr; register struct pte *pte; COUNT(MTOPHYS); i = (((int)m & ~PGOFSET) - (int)netutl) >> PGSHIFT; pte = &Netmap[i]; addr = (pte->pg_pfnum << PGSHIFT) | ((int)m & PGOFSET); return (addr); }