summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordwmalone <dwmalone@FreeBSD.org>2000-08-19 08:32:59 +0000
committerdwmalone <dwmalone@FreeBSD.org>2000-08-19 08:32:59 +0000
commitdf0e25bf6c3619217f1f2c8b5a35a6e706f2a0b4 (patch)
tree47f526cc36bae230ba5426a392413b1b46c0d678
parent2f92e39a0fe52366609e44e5a1978feb243c8755 (diff)
downloadFreeBSD-src-df0e25bf6c3619217f1f2c8b5a35a6e706f2a0b4.zip
FreeBSD-src-df0e25bf6c3619217f1f2c8b5a35a6e706f2a0b4.tar.gz
Replace the mbuf external reference counting code with something
that should be better. The old code counted references to mbuf clusters by using the offset of the cluster from the start of memory allocated for mbufs and clusters as an index into an array of chars, which did the reference counting. If the external storage was not a cluster then reference counting had to be done by the code using that external storage. NetBSD's system of linked lists of mbufs was cosidered, but Alfred felt it would have locking issues when the kernel was made more SMP friendly. The system implimented uses a pool of unions to track external storage. The union contains an int for counting the references and a pointer for forming a free list. The reference counts are incremented and decremented atomically and so should be SMP friendly. This system can track reference counts for any sort of external storage. Access to the reference counting stuff is now through macros defined in mbuf.h, so it should be easier to make changes to the system in the future. The possibility of storing the reference count in one of the referencing mbufs was considered, but was rejected 'cos it would often leave extra mbufs allocated. Storing the reference count in the cluster was also considered, but because the external storage may not be a cluster this isn't an option. The size of the pool of reference counters is available in the stats provided by "netstat -m". PR: 19866 Submitted by: Bosko Milekic <bmilekic@dsuper.net> Reviewed by: alfred (glanced at by others on -net)
-rw-r--r--sys/alpha/alpha/machdep.c12
-rw-r--r--sys/amd64/amd64/machdep.c12
-rw-r--r--sys/dev/en/midway.c2
-rw-r--r--sys/dev/sk/if_sk.c83
-rw-r--r--sys/dev/sk/if_skreg.h1
-rw-r--r--sys/dev/ti/if_ti.c83
-rw-r--r--sys/dev/ti/if_tireg.h1
-rw-r--r--sys/i386/i386/machdep.c12
-rw-r--r--sys/kern/uipc_mbuf.c84
-rw-r--r--sys/kern/uipc_mbuf2.c2
-rw-r--r--sys/kern/uipc_syscalls.c68
-rw-r--r--sys/netinet6/ipsec.c2
-rw-r--r--sys/netkey/key_debug.c4
-rw-r--r--sys/pc98/i386/machdep.c12
-rw-r--r--sys/pc98/pc98/machdep.c12
-rw-r--r--sys/pci/if_sk.c83
-rw-r--r--sys/pci/if_skreg.h1
-rw-r--r--sys/pci/if_ti.c83
-rw-r--r--sys/pci/if_tireg.h1
-rw-r--r--sys/pci/if_wb.c16
-rw-r--r--sys/sys/mbuf.h177
-rw-r--r--sys/sys/socketvar.h1
-rw-r--r--usr.bin/netstat/mbuf.c8
23 files changed, 292 insertions, 468 deletions
diff --git a/sys/alpha/alpha/machdep.c b/sys/alpha/alpha/machdep.c
index 02643ae..e5124d4 100644
--- a/sys/alpha/alpha/machdep.c
+++ b/sys/alpha/alpha/machdep.c
@@ -370,18 +370,16 @@ again:
(16*(ARG_MAX+(PAGE_SIZE*3))));
/*
- * Finally, allocate mbuf pool. Since mclrefcnt is an off-size
- * we use the more space efficient malloc in place of kmem_alloc.
+ * Finally, allocate mbuf pool.
*/
{
vm_offset_t mb_map_size;
- mb_map_size = nmbufs * MSIZE + nmbclusters * MCLBYTES;
+ mb_map_size = nmbufs * MSIZE + nmbclusters * MCLBYTES +
+ (nmbclusters + nmbufs / 4) * sizeof(union mext_refcnt);
mb_map_size = roundup2(mb_map_size, max(MCLBYTES, PAGE_SIZE));
- mclrefcnt = malloc(mb_map_size / MCLBYTES, M_MBUF, M_NOWAIT);
- bzero(mclrefcnt, mb_map_size / MCLBYTES);
- mb_map = kmem_suballoc(kmem_map, (vm_offset_t *)&mbutl, &maxaddr,
- mb_map_size);
+ mb_map = kmem_suballoc(kmem_map, (vm_offset_t *)&mbutl,
+ &maxaddr, mb_map_size);
mb_map->system_map = 1;
}
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 7647877..5e0dcba 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -386,18 +386,16 @@ again:
(16*(ARG_MAX+(PAGE_SIZE*3))));
/*
- * Finally, allocate mbuf pool. Since mclrefcnt is an off-size
- * we use the more space efficient malloc in place of kmem_alloc.
+ * Finally, allocate mbuf pool.
*/
{
vm_offset_t mb_map_size;
- mb_map_size = nmbufs * MSIZE + nmbclusters * MCLBYTES;
+ mb_map_size = nmbufs * MSIZE + nmbclusters * MCLBYTES +
+ (nmbclusters + nmbufs / 4) * sizeof(union mext_refcnt);
mb_map_size = roundup2(mb_map_size, max(MCLBYTES, PAGE_SIZE));
- mclrefcnt = malloc(mb_map_size / MCLBYTES, M_MBUF, M_NOWAIT);
- bzero(mclrefcnt, mb_map_size / MCLBYTES);
- mb_map = kmem_suballoc(kmem_map, (vm_offset_t *)&mbutl, &maxaddr,
- mb_map_size);
+ mb_map = kmem_suballoc(kmem_map, (vm_offset_t *)&mbutl,
+ &maxaddr, mb_map_size);
mb_map->system_map = 1;
}
diff --git a/sys/dev/en/midway.c b/sys/dev/en/midway.c
index 410d2f3..f397065 100644
--- a/sys/dev/en/midway.c
+++ b/sys/dev/en/midway.c
@@ -1833,7 +1833,7 @@ STATIC int en_makeexclusive(sc, mm, prev)
return (0);
}
- if (mclrefcnt[mtocl(m->m_ext.ext_buf)] > 1) {
+ if (MEXT_IS_REF(m)) {
/* make a real copy of the M_EXT mbuf since it is shared */
MGET(new, M_DONTWAIT, MT_DATA);
if (!new) {
diff --git a/sys/dev/sk/if_sk.c b/sys/dev/sk/if_sk.c
index b74f3f1..d45ac26 100644
--- a/sys/dev/sk/if_sk.c
+++ b/sys/dev/sk/if_sk.c
@@ -148,8 +148,7 @@ static int sk_newbuf __P((struct sk_if_softc *,
struct sk_chain *, struct mbuf *));
static int sk_alloc_jumbo_mem __P((struct sk_if_softc *));
static void *sk_jalloc __P((struct sk_if_softc *));
-static void sk_jfree __P((caddr_t, u_int));
-static void sk_jref __P((caddr_t, u_int));
+static void sk_jfree __P((caddr_t, void *));
static int sk_init_rx_ring __P((struct sk_if_softc *));
static void sk_init_tx_ring __P((struct sk_if_softc *));
static u_int32_t sk_win_read_4 __P((struct sk_softc *, int));
@@ -690,12 +689,9 @@ static int sk_newbuf(sc_if, c, m)
}
/* Attach the buffer to the mbuf */
- m_new->m_data = m_new->m_ext.ext_buf = (void *)buf;
- m_new->m_flags |= M_EXT;
- m_new->m_ext.ext_size = m_new->m_pkthdr.len =
- m_new->m_len = SK_MCLBYTES;
- m_new->m_ext.ext_free = sk_jfree;
- m_new->m_ext.ext_ref = sk_jref;
+ MEXTADD(m_new, buf, SK_MCLBYTES, sk_jfree, NULL);
+ m_new->m_data = (void *)buf;
+ m_new->m_pkthdr.len = m_new->m_len = SK_MCLBYTES;
} else {
/*
* We're re-using a previously allocated mbuf;
@@ -765,7 +761,6 @@ static int sk_alloc_jumbo_mem(sc_if)
aptr[0] = (u_int64_t *)sc_if;
ptr += sizeof(u_int64_t);
sc_if->sk_cdata.sk_jslots[i].sk_buf = ptr;
- sc_if->sk_cdata.sk_jslots[i].sk_inuse = 0;
ptr += SK_MCLBYTES;
entry = malloc(sizeof(struct sk_jpool_entry),
M_DEVBUF, M_NOWAIT);
@@ -803,55 +798,15 @@ static void *sk_jalloc(sc_if)
SLIST_REMOVE_HEAD(&sc_if->sk_jfree_listhead, jpool_entries);
SLIST_INSERT_HEAD(&sc_if->sk_jinuse_listhead, entry, jpool_entries);
- sc_if->sk_cdata.sk_jslots[entry->slot].sk_inuse = 1;
return(sc_if->sk_cdata.sk_jslots[entry->slot].sk_buf);
}
/*
- * Adjust usage count on a jumbo buffer. In general this doesn't
- * get used much because our jumbo buffers don't get passed around
- * a lot, but it's implemented for correctness.
- */
-static void sk_jref(buf, size)
- caddr_t buf;
- u_int size;
-{
- struct sk_if_softc *sc_if;
- u_int64_t **aptr;
- register int i;
-
- /* Extract the softc struct pointer. */
- aptr = (u_int64_t **)(buf - sizeof(u_int64_t));
- sc_if = (struct sk_if_softc *)(aptr[0]);
-
- if (sc_if == NULL)
- panic("sk_jref: can't find softc pointer!");
-
- if (size != SK_MCLBYTES)
- panic("sk_jref: adjusting refcount of buf of wrong size!");
-
- /* calculate the slot this buffer belongs to */
-
- i = ((vm_offset_t)aptr
- - (vm_offset_t)sc_if->sk_cdata.sk_jumbo_buf) / SK_JLEN;
-
- if ((i < 0) || (i >= SK_JSLOTS))
- panic("sk_jref: asked to reference buffer "
- "that we don't manage!");
- else if (sc_if->sk_cdata.sk_jslots[i].sk_inuse == 0)
- panic("sk_jref: buffer already free!");
- else
- sc_if->sk_cdata.sk_jslots[i].sk_inuse++;
-
- return;
-}
-
-/*
* Release a jumbo buffer.
*/
-static void sk_jfree(buf, size)
+static void sk_jfree(buf, args)
caddr_t buf;
- u_int size;
+ void *args;
{
struct sk_if_softc *sc_if;
u_int64_t **aptr;
@@ -865,31 +820,19 @@ static void sk_jfree(buf, size)
if (sc_if == NULL)
panic("sk_jfree: can't find softc pointer!");
- if (size != SK_MCLBYTES)
- panic("sk_jfree: freeing buffer of wrong size!");
-
/* calculate the slot this buffer belongs to */
-
i = ((vm_offset_t)aptr
- (vm_offset_t)sc_if->sk_cdata.sk_jumbo_buf) / SK_JLEN;
if ((i < 0) || (i >= SK_JSLOTS))
panic("sk_jfree: asked to free buffer that we don't manage!");
- else if (sc_if->sk_cdata.sk_jslots[i].sk_inuse == 0)
- panic("sk_jfree: buffer already free!");
- else {
- sc_if->sk_cdata.sk_jslots[i].sk_inuse--;
- if(sc_if->sk_cdata.sk_jslots[i].sk_inuse == 0) {
- entry = SLIST_FIRST(&sc_if->sk_jinuse_listhead);
- if (entry == NULL)
- panic("sk_jfree: buffer not in use!");
- entry->slot = i;
- SLIST_REMOVE_HEAD(&sc_if->sk_jinuse_listhead,
- jpool_entries);
- SLIST_INSERT_HEAD(&sc_if->sk_jfree_listhead,
- entry, jpool_entries);
- }
- }
+
+ entry = SLIST_FIRST(&sc_if->sk_jinuse_listhead);
+ if (entry == NULL)
+ panic("sk_jfree: buffer not in use!");
+ entry->slot = i;
+ SLIST_REMOVE_HEAD(&sc_if->sk_jinuse_listhead, jpool_entries);
+ SLIST_INSERT_HEAD(&sc_if->sk_jfree_listhead, entry, jpool_entries);
return;
}
diff --git a/sys/dev/sk/if_skreg.h b/sys/dev/sk/if_skreg.h
index af17c1c..24cce27 100644
--- a/sys/dev/sk/if_skreg.h
+++ b/sys/dev/sk/if_skreg.h
@@ -1124,7 +1124,6 @@ struct sk_tx_desc {
struct sk_jslot {
caddr_t sk_buf;
- int sk_inuse;
};
struct sk_jpool_entry {
diff --git a/sys/dev/ti/if_ti.c b/sys/dev/ti/if_ti.c
index 7e1b6f7..56847f4 100644
--- a/sys/dev/ti/if_ti.c
+++ b/sys/dev/ti/if_ti.c
@@ -190,8 +190,7 @@ static void ti_cmd_ext __P((struct ti_softc *, struct ti_cmd_desc *,
static void ti_handle_events __P((struct ti_softc *));
static int ti_alloc_jumbo_mem __P((struct ti_softc *));
static void *ti_jalloc __P((struct ti_softc *));
-static void ti_jfree __P((caddr_t, u_int));
-static void ti_jref __P((caddr_t, u_int));
+static void ti_jfree __P((caddr_t, void *));
static int ti_newbuf_std __P((struct ti_softc *, int, struct mbuf *));
static int ti_newbuf_mini __P((struct ti_softc *, int, struct mbuf *));
static int ti_newbuf_jumbo __P((struct ti_softc *, int, struct mbuf *));
@@ -629,7 +628,6 @@ static int ti_alloc_jumbo_mem(sc)
aptr[0] = (u_int64_t *)sc;
ptr += sizeof(u_int64_t);
sc->ti_cdata.ti_jslots[i].ti_buf = ptr;
- sc->ti_cdata.ti_jslots[i].ti_inuse = 0;
ptr += (TI_JLEN - sizeof(u_int64_t));
entry = malloc(sizeof(struct ti_jpool_entry),
M_DEVBUF, M_NOWAIT);
@@ -665,55 +663,15 @@ static void *ti_jalloc(sc)
SLIST_REMOVE_HEAD(&sc->ti_jfree_listhead, jpool_entries);
SLIST_INSERT_HEAD(&sc->ti_jinuse_listhead, entry, jpool_entries);
- sc->ti_cdata.ti_jslots[entry->slot].ti_inuse = 1;
return(sc->ti_cdata.ti_jslots[entry->slot].ti_buf);
}
/*
- * Adjust usage count on a jumbo buffer. In general this doesn't
- * get used much because our jumbo buffers don't get passed around
- * too much, but it's implemented for correctness.
- */
-static void ti_jref(buf, size)
- caddr_t buf;
- u_int size;
-{
- struct ti_softc *sc;
- u_int64_t **aptr;
- register int i;
-
- /* Extract the softc struct pointer. */
- aptr = (u_int64_t **)(buf - sizeof(u_int64_t));
- sc = (struct ti_softc *)(aptr[0]);
-
- if (sc == NULL)
- panic("ti_jref: can't find softc pointer!");
-
- if (size != TI_JUMBO_FRAMELEN)
- panic("ti_jref: adjusting refcount of buf of wrong size!");
-
- /* calculate the slot this buffer belongs to */
-
- i = ((vm_offset_t)aptr
- - (vm_offset_t)sc->ti_cdata.ti_jumbo_buf) / TI_JLEN;
-
- if ((i < 0) || (i >= TI_JSLOTS))
- panic("ti_jref: asked to reference buffer "
- "that we don't manage!");
- else if (sc->ti_cdata.ti_jslots[i].ti_inuse == 0)
- panic("ti_jref: buffer already free!");
- else
- sc->ti_cdata.ti_jslots[i].ti_inuse++;
-
- return;
-}
-
-/*
* Release a jumbo buffer.
*/
-static void ti_jfree(buf, size)
+static void ti_jfree(buf, args)
caddr_t buf;
- u_int size;
+ void *args;
{
struct ti_softc *sc;
u_int64_t **aptr;
@@ -727,31 +685,19 @@ static void ti_jfree(buf, size)
if (sc == NULL)
panic("ti_jfree: can't find softc pointer!");
- if (size != TI_JUMBO_FRAMELEN)
- panic("ti_jfree: freeing buffer of wrong size!");
-
/* calculate the slot this buffer belongs to */
-
i = ((vm_offset_t)aptr
- (vm_offset_t)sc->ti_cdata.ti_jumbo_buf) / TI_JLEN;
if ((i < 0) || (i >= TI_JSLOTS))
panic("ti_jfree: asked to free buffer that we don't manage!");
- else if (sc->ti_cdata.ti_jslots[i].ti_inuse == 0)
- panic("ti_jfree: buffer already free!");
- else {
- sc->ti_cdata.ti_jslots[i].ti_inuse--;
- if(sc->ti_cdata.ti_jslots[i].ti_inuse == 0) {
- entry = SLIST_FIRST(&sc->ti_jinuse_listhead);
- if (entry == NULL)
- panic("ti_jfree: buffer not in use!");
- entry->slot = i;
- SLIST_REMOVE_HEAD(&sc->ti_jinuse_listhead,
- jpool_entries);
- SLIST_INSERT_HEAD(&sc->ti_jfree_listhead,
- entry, jpool_entries);
- }
- }
+
+ entry = SLIST_FIRST(&sc->ti_jinuse_listhead);
+ if (entry == NULL)
+ panic("ti_jfree: buffer not in use!");
+ entry->slot = i;
+ SLIST_REMOVE_HEAD(&sc->ti_jinuse_listhead, jpool_entries);
+ SLIST_INSERT_HEAD(&sc->ti_jfree_listhead, entry, jpool_entries);
return;
}
@@ -877,12 +823,9 @@ static int ti_newbuf_jumbo(sc, i, m)
}
/* Attach the buffer to the mbuf. */
- m_new->m_data = m_new->m_ext.ext_buf = (void *)buf;
- m_new->m_flags |= M_EXT;
- m_new->m_len = m_new->m_pkthdr.len =
- m_new->m_ext.ext_size = TI_JUMBO_FRAMELEN;
- m_new->m_ext.ext_free = ti_jfree;
- m_new->m_ext.ext_ref = ti_jref;
+ m_new->m_data = (void *) buf;
+ m_new->m_len = m_new->m_pkthdr.len = TI_JUMBO_FRAMELEN;
+ MEXTADD(m_new, buf, TI_JUMBO_FRAMELEN, ti_jfree, NULL);
} else {
m_new = m;
m_new->m_data = m_new->m_ext.ext_buf;
diff --git a/sys/dev/ti/if_tireg.h b/sys/dev/ti/if_tireg.h
index 4712272..6346c67 100644
--- a/sys/dev/ti/if_tireg.h
+++ b/sys/dev/ti/if_tireg.h
@@ -1046,7 +1046,6 @@ struct ti_event_desc {
struct ti_jslot {
caddr_t ti_buf;
- int ti_inuse;
};
/*
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index 7647877..5e0dcba 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -386,18 +386,16 @@ again:
(16*(ARG_MAX+(PAGE_SIZE*3))));
/*
- * Finally, allocate mbuf pool. Since mclrefcnt is an off-size
- * we use the more space efficient malloc in place of kmem_alloc.
+ * Finally, allocate mbuf pool.
*/
{
vm_offset_t mb_map_size;
- mb_map_size = nmbufs * MSIZE + nmbclusters * MCLBYTES;
+ mb_map_size = nmbufs * MSIZE + nmbclusters * MCLBYTES +
+ (nmbclusters + nmbufs / 4) * sizeof(union mext_refcnt);
mb_map_size = roundup2(mb_map_size, max(MCLBYTES, PAGE_SIZE));
- mclrefcnt = malloc(mb_map_size / MCLBYTES, M_MBUF, M_NOWAIT);
- bzero(mclrefcnt, mb_map_size / MCLBYTES);
- mb_map = kmem_suballoc(kmem_map, (vm_offset_t *)&mbutl, &maxaddr,
- mb_map_size);
+ mb_map = kmem_suballoc(kmem_map, (vm_offset_t *)&mbutl,
+ &maxaddr, mb_map_size);
mb_map->system_map = 1;
}
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index 89ec747..ee0b58c 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -56,11 +56,11 @@ static void mbinit __P((void *));
SYSINIT(mbuf, SI_SUB_MBUF, SI_ORDER_FIRST, mbinit, NULL)
struct mbuf *mbutl;
-char *mclrefcnt;
struct mbstat mbstat;
u_long mbtypes[MT_NTYPES];
struct mbuf *mmbfree;
union mcluster *mclfree;
+union mext_refcnt *mext_refcnt_free;
int max_linkhdr;
int max_protohdr;
int max_hdr;
@@ -95,10 +95,9 @@ TUNABLE_INT_DECL("kern.ipc.nmbufs", NMBCLUSTERS * 4, nmbufs);
static void m_reclaim __P((void));
-/* "number of clusters of pages" */
-#define NCL_INIT 1
-
+#define NCL_INIT 2
#define NMB_INIT 16
+#define REF_INIT (NMBCLUSTERS * 2)
/* ARGSUSED*/
static void
@@ -107,7 +106,10 @@ mbinit(dummy)
{
int s;
- mmbfree = NULL; mclfree = NULL;
+ mmbfree = NULL;
+ mclfree = NULL;
+ mext_refcnt_free = NULL;
+
mbstat.m_msize = MSIZE;
mbstat.m_mclbytes = MCLBYTES;
mbstat.m_minclsize = MINCLSIZE;
@@ -115,6 +117,8 @@ mbinit(dummy)
mbstat.m_mhlen = MHLEN;
s = splimp();
+ if (m_alloc_ref(REF_INIT) == 0)
+ goto bad;
if (m_mballoc(NMB_INIT, M_DONTWAIT) == 0)
goto bad;
#if MCLBYTES <= PAGE_SIZE
@@ -128,7 +132,49 @@ mbinit(dummy)
splx(s);
return;
bad:
- panic("mbinit");
+ panic("mbinit: failed to initialize mbuf subsystem!");
+}
+
+/*
+ * Allocate at least nmb reference count structs and place them
+ * on the ref cnt free list.
+ * Must be called at splimp.
+ */
+int
+m_alloc_ref(nmb)
+ u_int nmb;
+{
+ caddr_t p;
+ u_int nbytes;
+ int i;
+
+ /*
+ * XXX:
+ * We don't cap the amount of memory that can be used
+ * by the reference counters, like we do for mbufs and
+ * mbuf clusters. The reason is that we don't really expect
+ * to have to be allocating too many of these guys with m_alloc_ref(),
+ * and if we are, we're probably not out of the woods anyway,
+ * so leave this way for now.
+ */
+
+ if (mb_map_full)
+ return (0);
+
+ nbytes = round_page(nmb * sizeof(union mext_refcnt));
+ if ((p = (caddr_t)kmem_malloc(mb_map, nbytes, M_NOWAIT)) == NULL)
+ return (0);
+ nmb = nbytes / sizeof(union mext_refcnt);
+
+ for (i = 0; i < nmb; i++) {
+ ((union mext_refcnt *)p)->next_ref = mext_refcnt_free;
+ mext_refcnt_free = (union mext_refcnt *)p;
+ p += sizeof(union mext_refcnt);
+ mbstat.m_refree++;
+ }
+ mbstat.m_refcnt += nmb;
+
+ return (1);
}
/*
@@ -363,7 +409,7 @@ m_clalloc_wait(void)
* MGET, but avoid getting into another instance of m_clalloc_wait()
*/
p = NULL;
- MCLALLOC(p, M_DONTWAIT);
+ _MCLALLOC(p, M_DONTWAIT);
s = splimp();
if (p != NULL) { /* We waited and got something... */
@@ -624,13 +670,9 @@ m_copym(m, off0, len, wait)
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;
+ MEXT_ADD_REF(m);
} else
bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
(unsigned)n->m_len);
@@ -671,13 +713,9 @@ m_copypacket(m, how)
n->m_len = m->m_len;
if (m->m_flags & M_EXT) {
n->m_data = m->m_data;
- 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;
+ MEXT_ADD_REF(m);
} else {
bcopy(mtod(m, char *), mtod(n, char *), n->m_len);
}
@@ -694,13 +732,9 @@ m_copypacket(m, how)
n->m_len = m->m_len;
if (m->m_flags & M_EXT) {
n->m_data = m->m_data;
- 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;
+ MEXT_ADD_REF(m);
} else {
bcopy(mtod(m, char *), mtod(n, char *), n->m_len);
}
@@ -1042,11 +1076,7 @@ extpacket:
if (m->m_flags & M_EXT) {
n->m_flags |= M_EXT;
n->m_ext = m->m_ext;
- 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);
+ MEXT_ADD_REF(m);
m->m_ext.ext_size = 0; /* For Accounting XXXXXX danger */
n->m_data = m->m_data + len;
} else {
diff --git a/sys/kern/uipc_mbuf2.c b/sys/kern/uipc_mbuf2.c
index b39c002..2e6aa1e 100644
--- a/sys/kern/uipc_mbuf2.c
+++ b/sys/kern/uipc_mbuf2.c
@@ -182,7 +182,7 @@ m_pulldown(m, off, len, offp)
else {
if (n->m_ext.ext_free)
sharedcluster = 1;
- else if (mclrefcnt[mtocl(n->m_ext.ext_buf)] > 1)
+ else if (MEXT_IS_REF(n))
sharedcluster = 1;
else
sharedcluster = 0;
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index 5ba2a24..ed9d691 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -72,8 +72,7 @@
static void sf_buf_init(void *arg);
SYSINIT(sock_sf, SI_SUB_MBUF, SI_ORDER_ANY, sf_buf_init, NULL)
static struct sf_buf *sf_buf_alloc(void);
-static void sf_buf_ref(caddr_t addr, u_int size);
-static void sf_buf_free(caddr_t addr, u_int size);
+static void sf_buf_free(caddr_t addr, void *args);
static int sendit __P((struct proc *p, int s, struct msghdr *mp, int flags));
static int recvit __P((struct proc *p, int s, struct msghdr *mp,
@@ -1354,58 +1353,42 @@ sf_buf_alloc()
}
SLIST_REMOVE_HEAD(&sf_freelist, free_list);
splx(s);
- sf->refcnt = 1;
return (sf);
}
#define dtosf(x) (&sf_bufs[((uintptr_t)(x) - (uintptr_t)sf_base) >> PAGE_SHIFT])
-static void
-sf_buf_ref(caddr_t addr, u_int size)
-{
- struct sf_buf *sf;
-
- sf = dtosf(addr);
- if (sf->refcnt == 0)
- panic("sf_buf_ref: referencing a free sf_buf");
- sf->refcnt++;
-}
/*
- * Lose a reference to an sf_buf. When none left, detach mapped page
- * and release resources back to the system.
+ *
+ * Detatch mapped page and release resources back to the system.
*
* Must be called at splimp.
*/
static void
-sf_buf_free(caddr_t addr, u_int size)
+sf_buf_free(caddr_t addr, void *args)
{
struct sf_buf *sf;
struct vm_page *m;
int s;
sf = dtosf(addr);
- if (sf->refcnt == 0)
- panic("sf_buf_free: freeing free sf_buf");
- sf->refcnt--;
- if (sf->refcnt == 0) {
- pmap_qremove((vm_offset_t)addr, 1);
- m = sf->m;
- s = splvm();
- vm_page_unwire(m, 0);
- /*
- * Check for the object going away on us. This can
- * happen since we don't hold a reference to it.
- * If so, we're responsible for freeing the page.
- */
- if (m->wire_count == 0 && m->object == NULL)
- vm_page_free(m);
- splx(s);
- sf->m = NULL;
- SLIST_INSERT_HEAD(&sf_freelist, sf, free_list);
- if (sf_buf_alloc_want) {
- sf_buf_alloc_want = 0;
- wakeup(&sf_freelist);
- }
+ pmap_qremove((vm_offset_t)addr, 1);
+ m = sf->m;
+ s = splvm();
+ vm_page_unwire(m, 0);
+ /*
+ * Check for the object going away on us. This can
+ * happen since we don't hold a reference to it.
+ * If so, we're responsible for freeing the page.
+ */
+ if (m->wire_count == 0 && m->object == NULL)
+ vm_page_free(m);
+ splx(s);
+ sf->m = NULL;
+ SLIST_INSERT_HEAD(&sf_freelist, sf, free_list);
+ if (sf_buf_alloc_want) {
+ sf_buf_alloc_want = 0;
+ wakeup(&sf_freelist);
}
}
@@ -1630,12 +1613,11 @@ retry_lookup:
error = ENOBUFS;
goto done;
}
- m->m_ext.ext_free = sf_buf_free;
- m->m_ext.ext_ref = sf_buf_ref;
- m->m_ext.ext_buf = (void *)sf->kva;
- m->m_ext.ext_size = PAGE_SIZE;
+ /*
+ * Setup external storage for mbuf.
+ */
+ MEXTADD(m, sf->kva, PAGE_SIZE, sf_buf_free, NULL);
m->m_data = (char *) sf->kva + pgoff;
- m->m_flags |= M_EXT;
m->m_pkthdr.len = m->m_len = xfsize;
/*
* Add the buffer to the socket buffer chain.
diff --git a/sys/netinet6/ipsec.c b/sys/netinet6/ipsec.c
index 2e8a67e..87e771f 100644
--- a/sys/netinet6/ipsec.c
+++ b/sys/netinet6/ipsec.c
@@ -3225,7 +3225,7 @@ ipsec_copypkt(m)
*/
if (
n->m_ext.ext_free ||
- mclrefcnt[mtocl(n->m_ext.ext_buf)] > 1
+ MEXT_IS_REF(n)
)
{
int remain, copied;
diff --git a/sys/netkey/key_debug.c b/sys/netkey/key_debug.c
index ebd06c3..3e8b12b 100644
--- a/sys/netkey/key_debug.c
+++ b/sys/netkey/key_debug.c
@@ -646,9 +646,9 @@ kdebug_mbufhdr(m)
if (m->m_flags & M_EXT) {
printf(" m_ext{ ext_buf:%p ext_free:%p "
- "ext_size:%u ext_ref:%p }\n",
+ "ext_size:%u ref_cnt:%p }\n",
m->m_ext.ext_buf, m->m_ext.ext_free,
- m->m_ext.ext_size, m->m_ext.ext_ref);
+ m->m_ext.ext_size, m->m_ext.ref_cnt);
}
return;
diff --git a/sys/pc98/i386/machdep.c b/sys/pc98/i386/machdep.c
index f63a452..5d6472b 100644
--- a/sys/pc98/i386/machdep.c
+++ b/sys/pc98/i386/machdep.c
@@ -399,18 +399,16 @@ again:
(16*(ARG_MAX+(PAGE_SIZE*3))));
/*
- * Finally, allocate mbuf pool. Since mclrefcnt is an off-size
- * we use the more space efficient malloc in place of kmem_alloc.
+ * Finally, allocate mbuf pool.
*/
{
vm_offset_t mb_map_size;
- mb_map_size = nmbufs * MSIZE + nmbclusters * MCLBYTES;
+ mb_map_size = nmbufs * MSIZE + nmbclusters * MCLBYTES +
+ (nmbclusters + nmbufs / 4) * sizeof(union mext_refcnt);
mb_map_size = roundup2(mb_map_size, max(MCLBYTES, PAGE_SIZE));
- mclrefcnt = malloc(mb_map_size / MCLBYTES, M_MBUF, M_NOWAIT);
- bzero(mclrefcnt, mb_map_size / MCLBYTES);
- mb_map = kmem_suballoc(kmem_map, (vm_offset_t *)&mbutl, &maxaddr,
- mb_map_size);
+ mb_map = kmem_suballoc(kmem_map, (vm_offset_t *)&mbutl,
+ &maxaddr, mb_map_size);
mb_map->system_map = 1;
}
diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c
index f63a452..5d6472b 100644
--- a/sys/pc98/pc98/machdep.c
+++ b/sys/pc98/pc98/machdep.c
@@ -399,18 +399,16 @@ again:
(16*(ARG_MAX+(PAGE_SIZE*3))));
/*
- * Finally, allocate mbuf pool. Since mclrefcnt is an off-size
- * we use the more space efficient malloc in place of kmem_alloc.
+ * Finally, allocate mbuf pool.
*/
{
vm_offset_t mb_map_size;
- mb_map_size = nmbufs * MSIZE + nmbclusters * MCLBYTES;
+ mb_map_size = nmbufs * MSIZE + nmbclusters * MCLBYTES +
+ (nmbclusters + nmbufs / 4) * sizeof(union mext_refcnt);
mb_map_size = roundup2(mb_map_size, max(MCLBYTES, PAGE_SIZE));
- mclrefcnt = malloc(mb_map_size / MCLBYTES, M_MBUF, M_NOWAIT);
- bzero(mclrefcnt, mb_map_size / MCLBYTES);
- mb_map = kmem_suballoc(kmem_map, (vm_offset_t *)&mbutl, &maxaddr,
- mb_map_size);
+ mb_map = kmem_suballoc(kmem_map, (vm_offset_t *)&mbutl,
+ &maxaddr, mb_map_size);
mb_map->system_map = 1;
}
diff --git a/sys/pci/if_sk.c b/sys/pci/if_sk.c
index b74f3f1..d45ac26 100644
--- a/sys/pci/if_sk.c
+++ b/sys/pci/if_sk.c
@@ -148,8 +148,7 @@ static int sk_newbuf __P((struct sk_if_softc *,
struct sk_chain *, struct mbuf *));
static int sk_alloc_jumbo_mem __P((struct sk_if_softc *));
static void *sk_jalloc __P((struct sk_if_softc *));
-static void sk_jfree __P((caddr_t, u_int));
-static void sk_jref __P((caddr_t, u_int));
+static void sk_jfree __P((caddr_t, void *));
static int sk_init_rx_ring __P((struct sk_if_softc *));
static void sk_init_tx_ring __P((struct sk_if_softc *));
static u_int32_t sk_win_read_4 __P((struct sk_softc *, int));
@@ -690,12 +689,9 @@ static int sk_newbuf(sc_if, c, m)
}
/* Attach the buffer to the mbuf */
- m_new->m_data = m_new->m_ext.ext_buf = (void *)buf;
- m_new->m_flags |= M_EXT;
- m_new->m_ext.ext_size = m_new->m_pkthdr.len =
- m_new->m_len = SK_MCLBYTES;
- m_new->m_ext.ext_free = sk_jfree;
- m_new->m_ext.ext_ref = sk_jref;
+ MEXTADD(m_new, buf, SK_MCLBYTES, sk_jfree, NULL);
+ m_new->m_data = (void *)buf;
+ m_new->m_pkthdr.len = m_new->m_len = SK_MCLBYTES;
} else {
/*
* We're re-using a previously allocated mbuf;
@@ -765,7 +761,6 @@ static int sk_alloc_jumbo_mem(sc_if)
aptr[0] = (u_int64_t *)sc_if;
ptr += sizeof(u_int64_t);
sc_if->sk_cdata.sk_jslots[i].sk_buf = ptr;
- sc_if->sk_cdata.sk_jslots[i].sk_inuse = 0;
ptr += SK_MCLBYTES;
entry = malloc(sizeof(struct sk_jpool_entry),
M_DEVBUF, M_NOWAIT);
@@ -803,55 +798,15 @@ static void *sk_jalloc(sc_if)
SLIST_REMOVE_HEAD(&sc_if->sk_jfree_listhead, jpool_entries);
SLIST_INSERT_HEAD(&sc_if->sk_jinuse_listhead, entry, jpool_entries);
- sc_if->sk_cdata.sk_jslots[entry->slot].sk_inuse = 1;
return(sc_if->sk_cdata.sk_jslots[entry->slot].sk_buf);
}
/*
- * Adjust usage count on a jumbo buffer. In general this doesn't
- * get used much because our jumbo buffers don't get passed around
- * a lot, but it's implemented for correctness.
- */
-static void sk_jref(buf, size)
- caddr_t buf;
- u_int size;
-{
- struct sk_if_softc *sc_if;
- u_int64_t **aptr;
- register int i;
-
- /* Extract the softc struct pointer. */
- aptr = (u_int64_t **)(buf - sizeof(u_int64_t));
- sc_if = (struct sk_if_softc *)(aptr[0]);
-
- if (sc_if == NULL)
- panic("sk_jref: can't find softc pointer!");
-
- if (size != SK_MCLBYTES)
- panic("sk_jref: adjusting refcount of buf of wrong size!");
-
- /* calculate the slot this buffer belongs to */
-
- i = ((vm_offset_t)aptr
- - (vm_offset_t)sc_if->sk_cdata.sk_jumbo_buf) / SK_JLEN;
-
- if ((i < 0) || (i >= SK_JSLOTS))
- panic("sk_jref: asked to reference buffer "
- "that we don't manage!");
- else if (sc_if->sk_cdata.sk_jslots[i].sk_inuse == 0)
- panic("sk_jref: buffer already free!");
- else
- sc_if->sk_cdata.sk_jslots[i].sk_inuse++;
-
- return;
-}
-
-/*
* Release a jumbo buffer.
*/
-static void sk_jfree(buf, size)
+static void sk_jfree(buf, args)
caddr_t buf;
- u_int size;
+ void *args;
{
struct sk_if_softc *sc_if;
u_int64_t **aptr;
@@ -865,31 +820,19 @@ static void sk_jfree(buf, size)
if (sc_if == NULL)
panic("sk_jfree: can't find softc pointer!");
- if (size != SK_MCLBYTES)
- panic("sk_jfree: freeing buffer of wrong size!");
-
/* calculate the slot this buffer belongs to */
-
i = ((vm_offset_t)aptr
- (vm_offset_t)sc_if->sk_cdata.sk_jumbo_buf) / SK_JLEN;
if ((i < 0) || (i >= SK_JSLOTS))
panic("sk_jfree: asked to free buffer that we don't manage!");
- else if (sc_if->sk_cdata.sk_jslots[i].sk_inuse == 0)
- panic("sk_jfree: buffer already free!");
- else {
- sc_if->sk_cdata.sk_jslots[i].sk_inuse--;
- if(sc_if->sk_cdata.sk_jslots[i].sk_inuse == 0) {
- entry = SLIST_FIRST(&sc_if->sk_jinuse_listhead);
- if (entry == NULL)
- panic("sk_jfree: buffer not in use!");
- entry->slot = i;
- SLIST_REMOVE_HEAD(&sc_if->sk_jinuse_listhead,
- jpool_entries);
- SLIST_INSERT_HEAD(&sc_if->sk_jfree_listhead,
- entry, jpool_entries);
- }
- }
+
+ entry = SLIST_FIRST(&sc_if->sk_jinuse_listhead);
+ if (entry == NULL)
+ panic("sk_jfree: buffer not in use!");
+ entry->slot = i;
+ SLIST_REMOVE_HEAD(&sc_if->sk_jinuse_listhead, jpool_entries);
+ SLIST_INSERT_HEAD(&sc_if->sk_jfree_listhead, entry, jpool_entries);
return;
}
diff --git a/sys/pci/if_skreg.h b/sys/pci/if_skreg.h
index af17c1c..24cce27 100644
--- a/sys/pci/if_skreg.h
+++ b/sys/pci/if_skreg.h
@@ -1124,7 +1124,6 @@ struct sk_tx_desc {
struct sk_jslot {
caddr_t sk_buf;
- int sk_inuse;
};
struct sk_jpool_entry {
diff --git a/sys/pci/if_ti.c b/sys/pci/if_ti.c
index 7e1b6f7..56847f4 100644
--- a/sys/pci/if_ti.c
+++ b/sys/pci/if_ti.c
@@ -190,8 +190,7 @@ static void ti_cmd_ext __P((struct ti_softc *, struct ti_cmd_desc *,
static void ti_handle_events __P((struct ti_softc *));
static int ti_alloc_jumbo_mem __P((struct ti_softc *));
static void *ti_jalloc __P((struct ti_softc *));
-static void ti_jfree __P((caddr_t, u_int));
-static void ti_jref __P((caddr_t, u_int));
+static void ti_jfree __P((caddr_t, void *));
static int ti_newbuf_std __P((struct ti_softc *, int, struct mbuf *));
static int ti_newbuf_mini __P((struct ti_softc *, int, struct mbuf *));
static int ti_newbuf_jumbo __P((struct ti_softc *, int, struct mbuf *));
@@ -629,7 +628,6 @@ static int ti_alloc_jumbo_mem(sc)
aptr[0] = (u_int64_t *)sc;
ptr += sizeof(u_int64_t);
sc->ti_cdata.ti_jslots[i].ti_buf = ptr;
- sc->ti_cdata.ti_jslots[i].ti_inuse = 0;
ptr += (TI_JLEN - sizeof(u_int64_t));
entry = malloc(sizeof(struct ti_jpool_entry),
M_DEVBUF, M_NOWAIT);
@@ -665,55 +663,15 @@ static void *ti_jalloc(sc)
SLIST_REMOVE_HEAD(&sc->ti_jfree_listhead, jpool_entries);
SLIST_INSERT_HEAD(&sc->ti_jinuse_listhead, entry, jpool_entries);
- sc->ti_cdata.ti_jslots[entry->slot].ti_inuse = 1;
return(sc->ti_cdata.ti_jslots[entry->slot].ti_buf);
}
/*
- * Adjust usage count on a jumbo buffer. In general this doesn't
- * get used much because our jumbo buffers don't get passed around
- * too much, but it's implemented for correctness.
- */
-static void ti_jref(buf, size)
- caddr_t buf;
- u_int size;
-{
- struct ti_softc *sc;
- u_int64_t **aptr;
- register int i;
-
- /* Extract the softc struct pointer. */
- aptr = (u_int64_t **)(buf - sizeof(u_int64_t));
- sc = (struct ti_softc *)(aptr[0]);
-
- if (sc == NULL)
- panic("ti_jref: can't find softc pointer!");
-
- if (size != TI_JUMBO_FRAMELEN)
- panic("ti_jref: adjusting refcount of buf of wrong size!");
-
- /* calculate the slot this buffer belongs to */
-
- i = ((vm_offset_t)aptr
- - (vm_offset_t)sc->ti_cdata.ti_jumbo_buf) / TI_JLEN;
-
- if ((i < 0) || (i >= TI_JSLOTS))
- panic("ti_jref: asked to reference buffer "
- "that we don't manage!");
- else if (sc->ti_cdata.ti_jslots[i].ti_inuse == 0)
- panic("ti_jref: buffer already free!");
- else
- sc->ti_cdata.ti_jslots[i].ti_inuse++;
-
- return;
-}
-
-/*
* Release a jumbo buffer.
*/
-static void ti_jfree(buf, size)
+static void ti_jfree(buf, args)
caddr_t buf;
- u_int size;
+ void *args;
{
struct ti_softc *sc;
u_int64_t **aptr;
@@ -727,31 +685,19 @@ static void ti_jfree(buf, size)
if (sc == NULL)
panic("ti_jfree: can't find softc pointer!");
- if (size != TI_JUMBO_FRAMELEN)
- panic("ti_jfree: freeing buffer of wrong size!");
-
/* calculate the slot this buffer belongs to */
-
i = ((vm_offset_t)aptr
- (vm_offset_t)sc->ti_cdata.ti_jumbo_buf) / TI_JLEN;
if ((i < 0) || (i >= TI_JSLOTS))
panic("ti_jfree: asked to free buffer that we don't manage!");
- else if (sc->ti_cdata.ti_jslots[i].ti_inuse == 0)
- panic("ti_jfree: buffer already free!");
- else {
- sc->ti_cdata.ti_jslots[i].ti_inuse--;
- if(sc->ti_cdata.ti_jslots[i].ti_inuse == 0) {
- entry = SLIST_FIRST(&sc->ti_jinuse_listhead);
- if (entry == NULL)
- panic("ti_jfree: buffer not in use!");
- entry->slot = i;
- SLIST_REMOVE_HEAD(&sc->ti_jinuse_listhead,
- jpool_entries);
- SLIST_INSERT_HEAD(&sc->ti_jfree_listhead,
- entry, jpool_entries);
- }
- }
+
+ entry = SLIST_FIRST(&sc->ti_jinuse_listhead);
+ if (entry == NULL)
+ panic("ti_jfree: buffer not in use!");
+ entry->slot = i;
+ SLIST_REMOVE_HEAD(&sc->ti_jinuse_listhead, jpool_entries);
+ SLIST_INSERT_HEAD(&sc->ti_jfree_listhead, entry, jpool_entries);
return;
}
@@ -877,12 +823,9 @@ static int ti_newbuf_jumbo(sc, i, m)
}
/* Attach the buffer to the mbuf. */
- m_new->m_data = m_new->m_ext.ext_buf = (void *)buf;
- m_new->m_flags |= M_EXT;
- m_new->m_len = m_new->m_pkthdr.len =
- m_new->m_ext.ext_size = TI_JUMBO_FRAMELEN;
- m_new->m_ext.ext_free = ti_jfree;
- m_new->m_ext.ext_ref = ti_jref;
+ m_new->m_data = (void *) buf;
+ m_new->m_len = m_new->m_pkthdr.len = TI_JUMBO_FRAMELEN;
+ MEXTADD(m_new, buf, TI_JUMBO_FRAMELEN, ti_jfree, NULL);
} else {
m_new = m;
m_new->m_data = m_new->m_ext.ext_buf;
diff --git a/sys/pci/if_tireg.h b/sys/pci/if_tireg.h
index 4712272..6346c67 100644
--- a/sys/pci/if_tireg.h
+++ b/sys/pci/if_tireg.h
@@ -1046,7 +1046,6 @@ struct ti_event_desc {
struct ti_jslot {
caddr_t ti_buf;
- int ti_inuse;
};
/*
diff --git a/sys/pci/if_wb.c b/sys/pci/if_wb.c
index 397ca20..b33c542 100644
--- a/sys/pci/if_wb.c
+++ b/sys/pci/if_wb.c
@@ -147,7 +147,7 @@ static int wb_probe __P((device_t));
static int wb_attach __P((device_t));
static int wb_detach __P((device_t));
-static void wb_bfree __P((caddr_t, u_int));
+static void wb_bfree __P((caddr_t, void *args));
static int wb_newbuf __P((struct wb_softc *,
struct wb_chain_onefrag *,
struct mbuf *));
@@ -1078,9 +1078,9 @@ static int wb_list_rx_init(sc)
return(0);
}
-static void wb_bfree(buf, size)
+static void wb_bfree(buf, args)
caddr_t buf;
- u_int size;
+ void *args;
{
return;
}
@@ -1102,13 +1102,9 @@ static int wb_newbuf(sc, c, m)
"list -- packet dropped!\n", sc->wb_unit);
return(ENOBUFS);
}
-
- m_new->m_data = m_new->m_ext.ext_buf = c->wb_buf;
- m_new->m_flags |= M_EXT;
- m_new->m_ext.ext_size = m_new->m_pkthdr.len =
- m_new->m_len = WB_BUFBYTES;
- m_new->m_ext.ext_free = wb_bfree;
- m_new->m_ext.ext_ref = wb_bfree;
+ m_new->m_data = c->wb_buf;
+ m_new->m_pkthdr.len = m_new->m_len = WB_BUFBYTES;
+ MEXTADD(m_new, c->wb_buf, WB_BUFBYTES, wb_bfree, NULL);
} else {
m_new = m;
m_new->m_len = m_new->m_pkthdr.len = WB_BUFBYTES;
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index 155e681..033fd7b 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -55,14 +55,9 @@
* Macros for type conversion
* mtod(m, t) - convert mbuf pointer to data pointer of correct type
* dtom(x) - convert data pointer within mbuf to mbuf pointer (XXX)
- * mtocl(x) - convert pointer within cluster to cluster index #
- * cltom(x) - convert cluster # to ptr to beginning of cluster
*/
#define mtod(m, t) ((t)((m)->m_data))
#define dtom(x) ((struct mbuf *)((intptr_t)(x) & ~(MSIZE-1)))
-#define mtocl(x) (((uintptr_t)(x) - (uintptr_t)mbutl) >> MCLSHIFT)
-#define cltom(x) ((caddr_t)((uintptr_t)mbutl + \
- ((uintptr_t)(x) << MCLSHIFT)))
/* header at beginning of each mbuf: */
struct m_hdr {
@@ -90,10 +85,10 @@ struct pkthdr {
struct m_ext {
caddr_t ext_buf; /* start of buffer */
void (*ext_free) /* free routine if not the usual */
- __P((caddr_t, u_int));
+ __P((caddr_t, void *));
+ void *ext_args; /* optional argument pointer */
u_int ext_size; /* size of buffer, for ext_free */
- void (*ext_ref) /* add a reference to the ext object */
- __P((caddr_t, u_int));
+ union mext_refcnt *ref_cnt; /* pointer to ref count info */
};
struct mbuf {
@@ -188,8 +183,10 @@ struct mbuf {
struct mbstat {
u_long m_mbufs; /* mbufs obtained from page pool */
u_long m_clusters; /* clusters obtained from page pool */
- u_long m_spare; /* spare field */
u_long m_clfree; /* free clusters */
+ u_long m_refcnt; /* refcnt structs obtained from page pool */
+ u_long m_refree; /* free refcnt structs */
+ u_long m_spare; /* spare field */
u_long m_drops; /* times failed to find space */
u_long m_wait; /* times waited for space */
u_long m_drain; /* times drained protocols for space */
@@ -227,6 +224,14 @@ union mcluster {
#define MGET_C 2
/*
+ * The m_ext object reference counter structure.
+ */
+union mext_refcnt {
+ union mext_refcnt *next_ref;
+ u_long refcnt;
+};
+
+/*
* Wake up the next instance (if any) of m_mballoc_wait() which is
* waiting for an mbuf to be freed. This should be called at splimp().
*
@@ -265,6 +270,50 @@ union mcluster {
} while (0)
/*
+ * mbuf external reference count management macros:
+ *
+ * MEXT_IS_REF(m): true if (m) is not the only mbuf referencing
+ * the external buffer ext_buf
+ * MEXT_REM_REF(m): remove reference to m_ext object
+ * MEXT_ADD_REF(m): add reference to m_ext object already
+ * referred to by (m)
+ * MEXT_INIT_REF(m): allocate and initialize an external
+ * object reference counter for (m)
+ */
+#define MEXT_IS_REF(m) ((m)->m_ext.ref_cnt->refcnt > 1)
+
+#define MEXT_REM_REF(m) atomic_subtract_long(&((m)->m_ext.ref_cnt->refcnt), 1)
+
+#define MEXT_ADD_REF(m) atomic_add_long(&((m)->m_ext.ref_cnt->refcnt), 1)
+
+#define _MEXT_ALLOC_CNT(m_cnt) MBUFLOCK( \
+ union mext_refcnt *__mcnt; \
+ \
+ __mcnt = mext_refcnt_free; \
+ if ((__mcnt == NULL) && (m_alloc_ref(1) == 0)) \
+ panic("mbuf subsystem: out of ref counts!"); \
+ mext_refcnt_free = __mcnt->next_ref; \
+ __mcnt->next_ref = NULL; \
+ (m_cnt) = __mcnt; \
+ mbstat.m_refree--; \
+)
+
+#define _MEXT_DEALLOC_CNT(m_cnt) do { \
+ union mext_refcnt *__mcnt = (m_cnt); \
+ \
+ __mcnt->next_ref = mext_refcnt_free; \
+ mext_refcnt_free = __mcnt; \
+ mbstat.m_refree++; \
+} while (0)
+
+#define MEXT_INIT_REF(m) do { \
+ struct mbuf *__mmm = (m); \
+ \
+ _MEXT_ALLOC_CNT(__mmm->m_ext.ref_cnt); \
+ atomic_set_long(&(__mmm->m_ext.ref_cnt->refcnt), 1); \
+} while (0)
+
+/*
* mbuf allocation/deallocation macros:
*
* MGET(struct mbuf *m, int how, int type)
@@ -286,22 +335,20 @@ union mcluster {
if (_mm != NULL) { \
mmbfree = _mm->m_next; \
mbtypes[MT_FREE]--; \
- _mm->m_type = _mtype; \
mbtypes[_mtype]++; \
+ splx(_ms); \
+ _mm->m_type = _mtype; \
_mm->m_next = NULL; \
_mm->m_nextpkt = NULL; \
_mm->m_data = _mm->m_dat; \
_mm->m_flags = 0; \
- (m) = _mm; \
- splx(_ms); \
} else { \
splx(_ms); \
_mm = m_retry(_mhow, _mtype); \
if (_mm == NULL && _mhow == M_WAIT) \
- (m) = m_mballoc_wait(MGET_C, _mtype); \
- else \
- (m) = _mm; \
+ _mm = m_mballoc_wait(MGET_C, _mtype); \
} \
+ (m) = _mm; \
} while (0)
#define MGETHDR(m, how, type) do { \
@@ -316,36 +363,34 @@ union mcluster {
if (_mm != NULL) { \
mmbfree = _mm->m_next; \
mbtypes[MT_FREE]--; \
- _mm->m_type = _mtype; \
mbtypes[_mtype]++; \
+ splx(_ms); \
+ _mm->m_type = _mtype; \
_mm->m_next = NULL; \
_mm->m_nextpkt = NULL; \
_mm->m_data = _mm->m_pktdat; \
_mm->m_flags = M_PKTHDR; \
_mm->m_pkthdr.rcvif = NULL; \
_mm->m_pkthdr.csum_flags = 0; \
- _mm->m_pkthdr.aux = (struct mbuf *)NULL; \
- (m) = _mm; \
- splx(_ms); \
+ _mm->m_pkthdr.aux = NULL; \
} else { \
splx(_ms); \
_mm = m_retryhdr(_mhow, _mtype); \
if (_mm == NULL && _mhow == M_WAIT) \
- (m) = m_mballoc_wait(MGETHDR_C, _mtype); \
- else \
- (m) = _mm; \
+ _mm = m_mballoc_wait(MGETHDR_C, _mtype); \
} \
+ (m) = _mm; \
} while (0)
/*
- * Mbuf cluster macros.
- * MCLALLOC(caddr_t p, int how) allocates an mbuf cluster.
- * MCLGET adds such clusters to a normal mbuf;
- * the flag M_EXT is set upon success.
- * MCLFREE releases a reference to a cluster allocated by MCLALLOC,
- * freeing the cluster if the reference count has reached 0.
+ * mbuf external storage macros:
+ *
+ * MCLGET allocates and refers an mcluster to an mbuf
+ * MEXTADD sets up pre-allocated external storage and refers to mbuf
+ * MEXTFREE removes reference to external object and frees it if
+ * necessary
*/
-#define MCLALLOC(p, how) do { \
+#define _MCLALLOC(p, how) do { \
caddr_t _mp; \
int _mhow = (how); \
int _ms = splimp(); \
@@ -354,61 +399,70 @@ union mcluster {
(void)m_clalloc(1, _mhow); \
_mp = (caddr_t)mclfree; \
if (_mp != NULL) { \
- mclrefcnt[mtocl(_mp)]++; \
mbstat.m_clfree--; \
mclfree = ((union mcluster *)_mp)->mcl_next; \
- (p) = _mp; \
splx(_ms); \
} else { \
splx(_ms); \
if (_mhow == M_WAIT) \
- (p) = m_clalloc_wait(); \
- else \
- (p) = NULL; \
+ _mp = m_clalloc_wait(); \
} \
-} while (0)
+ (p) = _mp; \
+} while (0)
#define MCLGET(m, how) do { \
struct mbuf *_mm = (m); \
\
- MCLALLOC(_mm->m_ext.ext_buf, (how)); \
+ _MCLALLOC(_mm->m_ext.ext_buf, (how)); \
if (_mm->m_ext.ext_buf != NULL) { \
_mm->m_data = _mm->m_ext.ext_buf; \
_mm->m_flags |= M_EXT; \
_mm->m_ext.ext_free = NULL; \
- _mm->m_ext.ext_ref = NULL; \
+ _mm->m_ext.ext_args = NULL; \
_mm->m_ext.ext_size = MCLBYTES; \
+ MEXT_INIT_REF(_mm); \
} \
} while (0)
-#define MCLFREE1(p) do { \
- union mcluster *_mp = (union mcluster *)(p); \
+#define MEXTADD(m, buf, size, free, args) do { \
+ struct mbuf *_mm = (m); \
\
- KASSERT(mclrefcnt[mtocl(_mp)] > 0, ("freeing free cluster")); \
- if (--mclrefcnt[mtocl(_mp)] == 0) { \
- _mp->mcl_next = mclfree; \
- mclfree = _mp; \
- mbstat.m_clfree++; \
- MCLWAKEUP(); \
- } \
+ _mm->m_flags |= M_EXT; \
+ _mm->m_ext.ext_buf = (caddr_t)(buf); \
+ _mm->m_data = _mm->m_ext.ext_buf; \
+ _mm->m_ext.ext_size = (size); \
+ _mm->m_ext.ext_free = (free); \
+ _mm->m_ext.ext_args = (args); \
+ MEXT_INIT_REF(_mm); \
} while (0)
-#define MCLFREE(p) MBUFLOCK( \
- MCLFREE1(p); \
+#define _MCLFREE(p) MBUFLOCK( \
+ union mcluster *_mp = (union mcluster *)(p); \
+ \
+ _mp->mcl_next = mclfree; \
+ mclfree = _mp; \
+ mbstat.m_clfree++; \
+ MCLWAKEUP(); \
)
-#define MEXTFREE1(m) do { \
- struct mbuf *_mm = (m); \
+#define _MEXTFREE(m) do { \
+ struct mbuf *_mmm = (m); \
\
- if (_mm->m_ext.ext_free != NULL) \
- (*_mm->m_ext.ext_free)(_mm->m_ext.ext_buf, \
- _mm->m_ext.ext_size); \
- else \
- MCLFREE1(_mm->m_ext.ext_buf); \
+ if (MEXT_IS_REF(_mmm)) \
+ MEXT_REM_REF(_mmm); \
+ else if (_mmm->m_ext.ext_free != NULL) { \
+ (*(_mmm->m_ext.ext_free))(_mmm->m_ext.ext_buf, \
+ _mmm->m_ext.ext_args); \
+ _MEXT_DEALLOC_CNT(_mmm->m_ext.ref_cnt); \
+ } else { \
+ _MCLFREE(_mmm->m_ext.ext_buf); \
+ _MEXT_DEALLOC_CNT(_mmm->m_ext.ref_cnt); \
+ } \
+ _mmm->m_flags &= ~M_EXT; \
} while (0)
-#define MEXTFREE(m) MBUFLOCK( \
- MEXTFREE1(m); \
+#define MEXTFREE(m) MBUFLOCK( \
+ _MEXTFREE(m); \
)
/*
@@ -420,12 +474,12 @@ union mcluster {
struct mbuf *_mm = (m); \
\
KASSERT(_mm->m_type != MT_FREE, ("freeing free mbuf")); \
- mbtypes[_mm->m_type]--; \
if (_mm->m_flags & M_EXT) \
- MEXTFREE1(m); \
- (n) = _mm->m_next; \
+ _MEXTFREE(_mm); \
+ mbtypes[_mm->m_type]--; \
_mm->m_type = MT_FREE; \
mbtypes[MT_FREE]++; \
+ (n) = _mm->m_next; \
_mm->m_next = mmbfree; \
mmbfree = _mm; \
MMBWAKEUP(); \
@@ -540,14 +594,15 @@ extern struct mbstat mbstat;
extern u_long mbtypes[MT_NTYPES]; /* per-type mbuf allocations */
extern int mbuf_wait; /* mbuf sleep time */
extern struct mbuf *mbutl; /* virtual address of mclusters */
-extern char *mclrefcnt; /* cluster reference counts */
extern union mcluster *mclfree;
extern struct mbuf *mmbfree;
+extern union mext_refcnt *mext_refcnt_free;
extern int nmbclusters;
extern int nmbufs;
extern int nsfbufs;
void m_adj __P((struct mbuf *, int));
+int m_alloc_ref __P((u_int));
void m_cat __P((struct mbuf *,struct mbuf *));
int m_clalloc __P((int, int));
caddr_t m_clalloc_wait __P((void));
diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h
index f1134b7..aee3191 100644
--- a/sys/sys/socketvar.h
+++ b/sys/sys/socketvar.h
@@ -272,7 +272,6 @@ struct sockopt {
struct sf_buf {
SLIST_ENTRY(sf_buf) free_list; /* list of free buffer slots */
- int refcnt; /* reference count */
struct vm_page *m; /* currently mapped page */
vm_offset_t kva; /* va of mapping */
};
diff --git a/usr.bin/netstat/mbuf.c b/usr.bin/netstat/mbuf.c
index 6ad3fdb..32c0751 100644
--- a/usr.bin/netstat/mbuf.c
+++ b/usr.bin/netstat/mbuf.c
@@ -176,9 +176,13 @@ mbpr()
printf("%lu/%lu/%u mbuf clusters in use (current/peak/max)\n",
mbstat.m_clusters - mbstat.m_clfree, mbstat.m_clusters,
nmbclusters);
- totmem = mbstat.m_mbufs * MSIZE + mbstat.m_clusters * MCLBYTES;
+ printf("%lu/%lu m_ext reference counters (in use/allocated)\n",
+ mbstat.m_refcnt - mbstat.m_refree, mbstat.m_refcnt);
+ totmem = mbstat.m_mbufs * MSIZE + mbstat.m_clusters * MCLBYTES +
+ mbstat.m_refcnt * sizeof(union mext_refcnt);
totfree = mbstat.m_clfree * MCLBYTES +
- MSIZE * (mbstat.m_mbufs - totmbufs);
+ MSIZE * (mbstat.m_mbufs - totmbufs) + mbstat.m_refree *
+ sizeof(union mext_refcnt);
printf("%u Kbytes allocated to network (%d%% in use)\n",
totmem / 1024, (unsigned) (totmem - totfree) * 100 / totmem);
printf("%lu requests for memory denied\n", mbstat.m_drops);
OpenPOWER on IntegriCloud