cvs commit: src/sys/dev/fxp if_fxp.c if_fxpvar.h

Andrew Gallatin gallatin at cs.duke.edu
Tue Apr 29 14:23:39 PDT 2003


John Baldwin writes:

 > test for the special case in foo_intr().  Hmmmm.  You almost want a way
 > to turn off the interrupt handler as the very first thing (maybe just mark
 > it as dead if it is still running, but not block) while holding the driver
 > lock, then turn off the ability to generate interrupts, then sit and wait
 > for the interrupt handler to remove itself.  Maybe:
 > 
 > 
 >         mtx_lock(&sc->sc_mtx);
 >         /* handler no longer executes */
 >         bus_disable_intr(inthand_cookie, &sc->sc_mtx);
 >         /* dink with device */
 >         mtx_unlock(&sc->sc_mtx);
 >         bus_teardown_intr(inthande_cookie);
 > 
 > With bus_disable_intr() calling a function like this:
 > 
 > void
 > ithread_disable_handler(void *cookie, struct mtx *m)
 > {
 >         struct intrhand *ih;
 >         struct ithread *it;
 > 
 >         ih = (struct intrhand *)cookie;
 >         it = ih->ih_it;
 >         mtx_lock(&it->it_lock);
 >         if (ithread_is_running) {
 >                 it->it_need = 1;
 >                 ih->ih_flags |= IH_DISABLING;
 >                 ih->ih_mutex = m;
 >                 mtx_unlock(&it->it_lock);
 >                 msleep(ih, m, ...);
 >         } else {
 >                 ih->ih_flags |= IH_DISABLED;
 >                 mtx_unlock(&it->it_lock);
 >         }
 > }
 > 
 > and some changes to ithread_loop() along the lines of:
 > 
 >                         CTR6(... /* existing */)
 >                         if (ih->ih_flags & IH_DISABLED)
 >                                 continue;
 >                         if (ih->ih_flags & IH_DISABLING) {
 >                                 struct mtx *m;
 > 
 >                                 m = ih->ih_mutex;
 >                                 ih->ih_flags |= IH_DISABLED;
 >                                 ih->ih_flags &= ~IH_DISABLING;
 >                                 mtx_unlock(&it->it_lock);
 >                                 mtx_lock(&m);
 >                                 wakeup(ih);
 >                                 mtx_unlock(&m);
 >                                 goto restart;
 >                         }
 >                         if (ih->ih_flags & IH_DEAD) {
 >                                 TAILQ_REMOVE(...);
 >                                 wakeup(ih);
 >                                 continue;
 >                         }
 > 
 > I would need to hold the ithread lock around the TAILQ_FOREACH()
 > bit and drop it around the execution of the handlers, but I probably
 > need that anyways.  Of course, all this really does, is take your
 > gone test and move it up in the stack.  You are still checking a flag
 > on every interrupt handler invocation.

Since you we already need to check for IH_DEAD, you could avoid extra
compares by doing

if (ih->ih_flags & (IH_DISABLED | IH_DISABLING | IH_DEAD)) {
   /* sort out rare cases outside the critical path */
}

Now we're doing only one check in the common case on something that
you apparently need to check anyway.  I'd be all for something like
this.

 > > No, in theory increased performance should come from increased
 > > parallelism with no increased overhead.  Any increased overhead is a
 > > bug.  Linux 2.4 runs a thread safe kernel with less overhead than we
 > > have in 4.x.  Its possible.
 > 
 > How are we going to achieve increased paralellism w/o increased overhead?
 > Discounting redesigning algo's which would have been a win in the
 > non-parallel kernel as well.  A mutex is far more expensive than an spl.
 > You have to protect against more things.  Of course overhead is going to
 > go up.

I have no idea really.  All I know is that linux 2.4 is more parallel
than 5.x is today, yet it outperforms 4.x for things like system call
latency and networking packets/sec through a single interface.
Therefore it must be possible.

Drew


More information about the cvs-src mailing list