X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/d80cae33efe58b3a928acc416122bea6a195f607..da7c5cc62d0962b5d290c48159695646218b130b:/usr/src/sys/kern/uipc_mbuf.c?ds=inline diff --git a/usr/src/sys/kern/uipc_mbuf.c b/usr/src/sys/kern/uipc_mbuf.c index 9e52140bab..ca8d4af43c 100644 --- a/usr/src/sys/kern/uipc_mbuf.c +++ b/usr/src/sys/kern/uipc_mbuf.c @@ -1,26 +1,142 @@ -/* mbuf.c 1.6 81/10/21 */ - -#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 "../bbnnet/net.h" -#include "../bbnnet/mbuf.h" -#include "../bbnnet/tcp.h" -#include "../bbnnet/ip.h" -#include "../h/vm.h" +/* + * Copyright (c) 1982 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + * + * @(#)uipc_mbuf.c 6.5 (Berkeley) %G% + */ -struct mbuf * -m_get(canwait) +#include "../machine/pte.h" + +#include "param.h" +#include "dir.h" +#include "user.h" +#include "proc.h" +#include "cmap.h" +#include "map.h" +#include "mbuf.h" +#include "vm.h" +#include "kernel.h" + +mbinit() +{ + int s; + + s = splimp(); + if (m_clalloc(4096/CLBYTES, MPG_MBUFS, M_DONTWAIT) == 0) + goto bad; + if (m_clalloc(8*4096/CLBYTES, MPG_CLUSTERS, M_DONTWAIT) == 0) + goto bad; + splx(s); + return; +bad: + panic("mbinit"); +} + +/* + * Must be called at splimp. + */ +caddr_t +m_clalloc(ncl, how, canwait) + register int ncl; + int how; +{ + int npg, mbx; + register struct mbuf *m; + register int i; + + npg = ncl * CLSIZE; + mbx = rmalloc(mbmap, (long)npg); + if (mbx == 0) { + if (canwait == M_WAIT) + panic("out of mbuf map"); + return (0); + } + m = cltom(mbx / CLSIZE); + if (memall(&Mbmap[mbx], npg, proc, CSYS) == 0) { + rmfree(mbmap, (long)npg, (long)mbx); + return (0); + } + vmaccess(&Mbmap[mbx], (caddr_t)m, npg); + switch (how) { + + case MPG_CLUSTERS: + for (i = 0; i < ncl; i++) { + m->m_off = 0; + m->m_next = mclfree; + mclfree = m; + m += CLBYTES / sizeof (*m); + mbstat.m_clfree++; + } + mbstat.m_clusters += ncl; + break; + + case MPG_MBUFS: + for (i = ncl * CLBYTES / sizeof (*m); i > 0; i--) { + m->m_off = 0; + m->m_type = MT_DATA; + mbstat.m_mtypes[MT_DATA]++; + mbstat.m_mbufs++; + (void) m_free(m); + m++; + } + break; + } + return ((caddr_t)m); +} + +m_pgfree(addr, n) + caddr_t addr; + int n; +{ + +#ifdef lint + addr = addr; n = n; +#endif +} + +/* + * Must be called at splimp. + */ +m_expand(canwait) int canwait; { + + if (m_clalloc(1, MPG_MBUFS, canwait) == 0) + goto steal; + return (1); +steal: + /* should ask protocols to free code */ + return (0); +} + +/* NEED SOME WAY TO RELEASE SPACE */ + +/* + * Space allocation routines. + * These are also available as macros + * for critical paths. + */ +struct mbuf * +m_get(canwait, type) + int canwait, type; +{ + register struct mbuf *m; + + MGET(m, canwait, type); + return (m); +} + +struct mbuf * +m_getclr(canwait, type) + int canwait, type; +{ register struct mbuf *m; -COUNT(M_GET); - MGET(m, canwait); + MGET(m, canwait, type); + if (m == 0) + return (0); + bzero(mtod(m, caddr_t), MLEN); return (m); } @@ -30,186 +146,166 @@ m_free(m) { register struct mbuf *n; -COUNT(M_FREE); MFREE(m, n); return (n); } +/* + * Get more mbufs; called from MGET macro if mfree list is empty. + * Must be called at splimp. + */ +/*ARGSUSED*/ struct mbuf * -m_more(type) - int type; +m_more(canwait, type) + int canwait, type; { - int s; register struct mbuf *m; -COUNT(M_MORE); - if (!m_expand()) { - netstat.m_drops++; - return (NULL); + while (m_expand(canwait) == 0) { + if (canwait == M_WAIT) { + m_want++; + sleep((caddr_t)mfree, PZERO - 1); + } else { + mbstat.m_drops++; + return (NULL); + } } -#define m_more(x) ((struct mbuf *)panic("m_more")) - MGET(m, 0); +#define m_more(x,y) (panic("m_more"), (struct mbuf *)0) + MGET(m, canwait, type); +#undef m_more return (m); } -m_freem(m) /* free mbuf chain headed by m */ +m_freem(m) register struct mbuf *m; { register struct mbuf *n; - register int s, cnt; + register int s; -COUNT(M_FREEM); if (m == NULL) - return (0); - cnt = 0; - s = spl_imp(); + return; + s = splimp(); do { MFREE(m, n); - cnt++; } while (m = n); splx(s); - return (cnt); } +/* + * Mbuffer utility routines. + */ -mbufinit() /* init network buffer mgmt system */ -{ +/* + * Make a copy of an mbuf chain starting "off" bytes from the beginning, + * continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf. + * Should get M_WAIT/M_DONTWAIT from caller. + */ +struct mbuf * +m_copy(m, off, len) 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_free(m); - m++; - } - pg_alloc(3); - netcb.n_pages = 4; - netcb.n_bufs = 32; - netcb.n_lowat = 16; - netcb.n_hiwat = 32; -} - -pg_alloc(n) - register int n; + int off; + register int len; { - register i, j, k; - register struct mbuf *m; - int bufs, s; + register struct mbuf *n, **np; + struct mbuf *top, *p; -COUNT(PG_ALLOC); - k = n << 1; - if ((i = rmalloc(netmap, n)) == 0) + if (len == 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 = spl_imp(); - for (j=0; j < bufs; j++) { - m_free(m); - m++; - } - splx(s); - netcb.n_pages += n; - return (1); -} - -m_expand() -{ - register i; - register struct ipq *fp; - register struct ip *q; - register struct tcb *tp; - register struct mbuf *m, *n; - int need, needp, needs; - -COUNT(M_EXPAND); - needs = need = netcb.n_hiwat - netcb.n_bufs; /* #bufs to add */ - needp = need >> 3; /* #pages to add */ - if (pg_alloc(needp)) - return (1); - for (i=0; i < needp; i++, need-=NMBPG) - if (needp == 1 || pg_alloc(1) == 0) /* ??? */ - goto steal; - return (need < needs); -steal: - fp = netcb.n_ip_tail; /* ip reass.q */ - while (need > 0 && fp) { - q = fp->iqx.ip_next; /* free mbufs assoc. w/chain */ - while (q != (struct ip *)fp) { - need -= m_freem(dtom(q)); - q = q->ip_next; - } - ip_freef(fp); /* free header */ - fp = netcb.n_ip_tail; + if (off < 0 || len < 0) + panic("m_copy"); + while (off > 0) { + if (m == 0) + panic("m_copy"); + if (off < m->m_len) + break; + off -= m->m_len; + m = m->m_next; } - tp = netcb.n_tcb_tail; /* ->tcbs */ - while (need > 0 && tp != NULL) { - m = tp->t_rcv_unack; - while (m != NULL) { - n = m->m_act; - need -= m_freem(m); - m = n; + np = ⊤ + top = 0; + while (len > 0) { + if (m == 0) { + if (len != M_COPYALL) + panic("m_copy"); + break; } - tp->t_rcv_unack = NULL; - tp = tp->t_tcb_prev; + MGET(n, M_DONTWAIT, m->m_type); + *np = n; + if (n == 0) + goto nospace; + n->m_len = MIN(len, m->m_len - off); + if (m->m_off > MMAXOFF) { + p = mtod(m, struct mbuf *); + n->m_off = ((int)p - (int)n) + off; + mclrefcnt[mtocl(p)]++; + } else + bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t), + (unsigned)n->m_len); + if (len != M_COPYALL) + len -= n->m_len; + off = 0; + m = m->m_next; + np = &n->m_next; } - return (need < needs); + return (top); +nospace: + m_freem(top); + return (0); } -#ifdef notdef -m_relse() +m_cat(m, n) + register struct mbuf *m, *n; { - int free; - -COUNT(M_RELSE); - free = (netcb.n_bufs - netcb.n_hiwat) >> 3; /* # excess free pages */ - return; + while (m->m_next) + m = m->m_next; + while (n) { + if (m->m_off >= MMAXOFF || + m->m_off + m->m_len + n->m_len > MMAXOFF) { + /* just join the two chains */ + m->m_next = n; + return; + } + /* splat the data from one into the other */ + bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, + (u_int)n->m_len); + m->m_len += n->m_len; + n = m_free(n); + } } -#endif -struct mbuf * m_adj(mp, len) struct mbuf *mp; - register len; + register int len; { register struct mbuf *m, *n; -COUNT(M_ADJ); if ((m = mp) == NULL) return; - if (len >= 0) { /* adjust from top of msg chain */ + if (len >= 0) { while (m != NULL && len > 0) { - if (m->m_len <= len) { /* free this mbuf */ + if (m->m_len <= len) { len -= m->m_len; m->m_len = 0; m = m->m_next; - } else { /* adjust mbuf */ + } else { m->m_len -= len; m->m_off += len; break; } } - - } else { /* adjust from bottom of msg chain */ + } else { + /* a 2 pass algorithm might be better */ 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 */ + if (n->m_len <= len) { len -= n->m_len; n->m_len = 0; m = mp; - } else { /* adjust length */ + } else { n->m_len -= len; break; } @@ -217,19 +313,42 @@ COUNT(M_ADJ); } } -/* - * convert mbuf virtual to physical addr for uballoc - */ -mtophys(m) - register struct mbuf *m; +struct mbuf * +m_pullup(m0, len) + struct mbuf *m0; + int len; { - 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); + register struct mbuf *m, *n; + int count; + + n = m0; + if (len > MLEN) + goto bad; + MGET(m, M_DONTWAIT, n->m_type); + if (m == 0) + goto bad; + m->m_len = 0; + do { + count = MIN(MLEN - m->m_len, len); + if (count > n->m_len) + count = n->m_len; + bcopy(mtod(n, caddr_t), mtod(m, caddr_t)+m->m_len, + (unsigned)count); + len -= count; + m->m_len += count; + n->m_off += count; + n->m_len -= count; + if (n->m_len) + break; + n = m_free(n); + } while (n); + if (len) { + (void) m_free(m); + goto bad; + } + m->m_next = n; + return (m); +bad: + m_freem(n); + return (0); }