📄 uipc_mbuf.c
字号:
/* * Copyright (c) 1982, 1986, 1988, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 * $Id: uipc_mbuf.c,v 1.7 2003/02/06 17:14:29 joel Exp $ */#include <sys/param.h>#include <sys/systm.h>#include <sys/proc.h>#include <sys/malloc.h>#define MBTYPES#include <sys/mbuf.h>#include <sys/kernel.h>#include <sys/syslog.h>#include <sys/domain.h>#include <sys/protosw.h>#include <vm/vm.h>#include <vm/vm_param.h>#include <vm/vm_kern.h>#include <vm/vm_extern.h>#if !defined(__rtems__)static void mbinit __P((void *)) __attribute__ ((unused));SYSINIT(mbuf, SI_SUB_MBUF, SI_ORDER_FIRST, mbinit, NULL)#endifstruct mbuf *mbutl;char *mclrefcnt;struct mbstat mbstat;struct mbuf *mmbfree;union mcluster *mclfree;int max_linkhdr;int max_protohdr;int max_hdr;int max_datalen;/* "number of clusters of pages" */#define NCL_INIT 1#define NMB_INIT 16/* * When MGET failes, ask protocols to free space when short of memory, * then re-attempt to allocate an mbuf. */struct mbuf *m_retry(i, t) int i, t;{ register struct mbuf *m; m_reclaim();#define m_retry(i, t) (struct mbuf *)0 MGET(m, i, t);#undef m_retry if (m != NULL) mbstat.m_wait++; else mbstat.m_drops++; return (m);}/* * As above; retry an MGETHDR. */struct mbuf *m_retryhdr(i, t) int i, t;{ register struct mbuf *m; m_reclaim();#define m_retryhdr(i, t) (struct mbuf *)0 MGETHDR(m, i, t);#undef m_retryhdr if (m != NULL) mbstat.m_wait++; else mbstat.m_drops++; return (m);}voidm_reclaim(void){ register struct domain *dp; register struct protosw *pr; int s = splimp(); for (dp = domains; dp; dp = dp->dom_next) for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_drain) (*pr->pr_drain)(); splx(s); mbstat.m_drain++;}/* * Space allocation routines. * These are also available as macros * for critical paths. */struct mbuf *m_get(nowait, type) int nowait, type;{ register struct mbuf *m; MGET(m, nowait, type); return (m);}struct mbuf *m_gethdr(nowait, type) int nowait, type;{ register struct mbuf *m; MGETHDR(m, nowait, type); return (m);}struct mbuf *m_getclr(nowait, type) int nowait, type;{ register struct mbuf *m; MGET(m, nowait, type); if (m == 0) return (0); bzero(mtod(m, caddr_t), MLEN); return (m);}struct mbuf *m_free(m) struct mbuf *m;{ register struct mbuf *n; MFREE(m, n); return (n);}voidm_freem(m) register struct mbuf *m;{ register struct mbuf *n; if (m == NULL) return; do { MFREE(m, n); m = n; } while (m);}/* * Mbuffer utility routines. *//* * Lesser-used path for M_PREPEND: * allocate new mbuf to prepend to chain, * copy junk along. */struct mbuf *m_prepend(m, len, how) register struct mbuf *m; int len, how;{ struct mbuf *mn; MGET(mn, how, m->m_type); if (mn == (struct mbuf *)NULL) { m_freem(m); return ((struct mbuf *)NULL); } if (m->m_flags & M_PKTHDR) { M_COPY_PKTHDR(mn, m); m->m_flags &= ~M_PKTHDR; } mn->m_next = m; m = mn; if (len < MHLEN) MH_ALIGN(m, len); m->m_len = len; return (m);}/* * Make a copy of an mbuf chain starting "off0" bytes from the beginning, * continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf. * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller. */static int MCFail;struct mbuf *m_copym(m, off0, len, wait) register struct mbuf *m; int off0, wait; register int len;{ register struct mbuf *n, **np; register int off = off0; struct mbuf *top; int copyhdr = 0; if (off < 0 || len < 0) panic("m_copym"); if (off == 0 && m->m_flags & M_PKTHDR) copyhdr = 1; while (off > 0) { if (m == 0) panic("m_copym"); if (off < m->m_len) break; off -= m->m_len; m = m->m_next; } np = ⊤ top = 0; while (len > 0) { if (m == 0) { if (len != M_COPYALL) panic("m_copym"); break; } MGET(n, wait, m->m_type); *np = n; if (n == 0) goto nospace; if (copyhdr) { M_COPY_PKTHDR(n, m); if (len == M_COPYALL) n->m_pkthdr.len -= off0; else n->m_pkthdr.len = len; copyhdr = 0; } n->m_len = min(len, m->m_len - off); if (m->m_flags & M_EXT) { n->m_data = m->m_data + off; if(!m->m_ext.ext_ref) mclrefcnt[mtocl(m->m_ext.ext_buf)]++; else (*(m->m_ext.ext_ref))(m->m_ext.ext_buf, m->m_ext.ext_size); n->m_ext = m->m_ext; n->m_flags |= M_EXT; } 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; } if (top == 0) MCFail++; return (top);nospace: m_freem(top); MCFail++; return (0);}/* * Copy an entire packet, including header (which must be present). * An optimization of the common case `m_copym(m, 0, M_COPYALL, how)'. */struct mbuf *m_copypacket(m, how) struct mbuf *m; int how;{ struct mbuf *top, *n, *o; MGET(n, how, m->m_type); top = n; if (!n) goto nospace; M_COPY_PKTHDR(n, m); n->m_len = m->m_len; if (m->m_flags & M_EXT) { n->m_data = m->m_data; mclrefcnt[mtocl(m->m_ext.ext_buf)]++; n->m_ext = m->m_ext; n->m_flags |= M_EXT; } else { bcopy(mtod(m, char *), mtod(n, char *), n->m_len); } m = m->m_next; while (m) { MGET(o, how, m->m_type); if (!o) goto nospace; n->m_next = o; n = n->m_next; n->m_len = m->m_len; if (m->m_flags & M_EXT) { n->m_data = m->m_data; mclrefcnt[mtocl(m->m_ext.ext_buf)]++; n->m_ext = m->m_ext; n->m_flags |= M_EXT; } else { bcopy(mtod(m, char *), mtod(n, char *), n->m_len); } m = m->m_next; } return top;nospace: m_freem(top); MCFail++; return 0;}/* * Copy data from an mbuf chain starting "off" bytes from the beginning, * continuing for "len" bytes, into the indicated buffer. Return -1 if requested * size is bigger than available */intm_copydata(m, off, len, cp) register struct mbuf *m; register int off; register int len; caddr_t cp;{ register unsigned count;/* struct mbuf *m0 = m; */ if (off < 0 || len < 0) panic("m_copydata"); while (off > 0) { if (m == 0) { /*printf("m_copydata: offset > mbuf length ("); while(m0) { printf("[%d] ",m0->m_len); m0 = m0->m_next; } printf(")\n");*/ return -1; } if (off < m->m_len) break; off -= m->m_len; m = m->m_next; } while (len > 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -