Subject: Re: USB stack needs early review (Re: Someone should fix our USB stack...)
To: der Mouse <mouse@Rodents.Montreal.QC.CA>
From: Andrew Doran <ad@netbsd.org>
List: tech-kern
Date: 05/29/2007 10:48:55
On Tue, May 29, 2007 at 09:02:07AM +0200, Reinoud Zandijk wrote:

> On Sat, Apr 28, 2007 at 04:37:31PM +0100, Andrew Doran wrote:
> > > > That code is simply bogus; it needs to look more like this:
> > > >
> > > > s = splfoo()
> > > >   while (! (sc->flags & SCF_INTERRUPTED)) {
> > > >         tsleep();
> > > >   }
> > > > splx(s);
> 
> yes, i think the author meant:
> 
> s = splfoo();
> while (!(sc->flags & SCF_INTERURUPTED)) {
> 	splx(s);

<- there is a race here. Interrupts are no longer blocked, an interrupt can
fire and the interrupt handler can set SCF_INTERRUPTED. It then issues a
wakeup(), but the thread has not yet completed tsleep(), and so is not
asleep. So the thread misses the wakeup, and sleeps forever instead..

> 	tsleep(...);
> 	s = splfoo();
> }
> splx(s);
> 
> How would otherwise the interrupt handler be able to enter the spl 
> level/interrupt level needed to modify the value's :-) Or am i wrong in 
> this and is tsleep() taking care of that in this situation?

The call to tsleep needs to be made with the interrupt blocked. tsleep
saves and restores the SPL automatically.

> > If you are targeting -current:
> > 
> > 	mutex_enter(&foo_lock);
> > 	while ((sc->flags & SCF_INTERRUPTED) == 0)
> > 		cv_wait(&foo_cv, &foo_lock);
> > 	mutex_exit(&foo_lock);
> > 
> > :-)
> 
> Thats a lot better indeed! A lot cleaner too....

Essentially the same thing, but using locks. cv_wait has no knowledge
of the lock you want to drop, so you have to tell it.

Cheers,
Andrew