From a5c4836d399dbb00ba605ca5fd75caac0582ffc5 Mon Sep 17 00:00:00 2001 From: David Malone Date: Sat, 19 Aug 2000 08:32:59 +0000 Subject: 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 Reviewed by: alfred (glanced at by others on -net) --- sys/dev/en/midway.c | 2 +- sys/dev/sk/if_sk.c | 83 ++++++++------------------------------------------- sys/dev/sk/if_skreg.h | 1 - sys/dev/ti/if_ti.c | 83 ++++++++------------------------------------------- sys/dev/ti/if_tireg.h | 1 - 5 files changed, 27 insertions(+), 143 deletions(-) (limited to 'sys/dev') diff --git a/sys/dev/en/midway.c b/sys/dev/en/midway.c index 410d2f3fa32fb..f397065ab72c0 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 b74f3f1542dc4..d45ac2634748a 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 af17c1c165cee..24cce27c9537a 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 7e1b6f7606078..56847f4c8f3e7 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 471227223f77d..6346c67e33809 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; }; /* -- cgit v1.3