Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 8 Nov 2000 13:13:43 -0600
From:      Jonathan Lemon <jlemon@flugsvamp.com>
To:        smp@freebsd.org
Subject:   SMP safe interface queues
Message-ID:  <20001108131343.A72943@prism.flugsvamp.com>

index | next in thread | raw e-mail


I've converted the ifqueue structure and the IF* macros to be SMP
safe.  The conversion was done with an eye towards modifying the
ethernet drivers as little as possible.  An explanation of the 
changes is below, and at the end is a design question of what to
do with "misbehaved" drivers.

Borrowing from the mbuf model, the existing IF_DEQUEUE, IF_ENQUEUE
and IF_PREPEND macros are prepended with an underscore, and new
macros are defined that obtain and release the lock around the 
call.  E.g.:

#define IF_DEQUEUE(ifq, m) do {                                 \
        IF_LOCK(ifq);                                           \
        _IF_DEQUEUE(ifq, m);                                    \
        IF_UNLOCK(ifq);                                         \
} while (0)

#define IF_PREPEND(ifq, m) do {                                 \
        IF_LOCK(ifq);                                           \
        _IF_PREPEND(ifq, m);                                    \
        IF_UNLOCK(ifq);                                         \
} while (0)

With this approach, no change at all is required for most drivers.
Mutex initialization/destruction is done by if_attach/if_detach().


Most of the upper layer uses a variant of the following model:

	s = splnet();
        if (IF_QFULL(ifq)) {
                IF_DROP(ifq);
                m_freem(m);
                return;
        }
        ifp->if_obytes += m->m_pkthdr.len;
        if (m->m_flags & M_MCAST)
                ifp->if_omcasts++;
        IF_ENQUEUE(ifq, m);
        if ((ifp->if_flags & IFF_OACTIVE) == 0)
                (*ifp->if_start)(ifp);
	splx(s);

When converting this to use mutexes, the lock has to be dropped before
calling the start routine, otherwise we can deadlock.  This opens up 
a possible race where the driver can turn off the OACTIVE flag after 
a packet is queued.  So to make things simpler, the entire block of 
code above is moved into a new "IF_HANDOFF" macro which takes care of 
all the details for the caller.  The upper layer code simplifies to:

	if (! IF_HANDOFF(ifq, m, ifp))
		ifp->if_oerrors++;

For full details, refer to the current patchset against -current which 
is at: http://www.flugsvamp.com/~jlemon/fbsd/ifq_v3.patch


The only warts in this particular model are certain drivers which
abuse the ifqueue structure as a convenient way of retaining mbufs
that the chip is transmitting.  In this case, the ifq is completely
private to one driver, and thus does not need to be locked, as it 
is not an interface queue at all.  The question then is should the
driver be converted to use the "mutex-free" versions of the macros
above, or should it be forced to perform locking/unlocking even though
it is unncessary?

   Some example drivers doing this are midway, de, awi, hea, lmc.

Personally, I'd prefer to have these use the 'mutex-free' version of 
the macro to make it clear that no locks are being used, but this may
be a problem for maintainability, especially considering that most 
(if not all) of the above drivers are from NetBSD.

Feedback welcome.
--
Jonathan


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-smp" in the body of the message



help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20001108131343.A72943>