Subject: Re: Mutex question
To: Eric Haszlakiewicz <firstname.lastname@example.org>
From: Steven M. Bellovin <email@example.com>
Date: 03/16/2006 18:16:15
On Thu, 16 Mar 2006 11:28:04 -0600, Eric Haszlakiewicz
> On Thu, Mar 16, 2006 at 11:49:47AM -0500, Steven M. Bellovin wrote:
> > On Thu, 16 Mar 2006 09:16:57 -0500 (EST), Matthew Orgass
> > <firstname.lastname@example.org> wrote:
> > > On 2006-03-16 email@example.com wrote:
> > >
> > > > If I want to aquire a mutex from:
> > > >
> > > > 1) Interrupt handler
> > > > 2) Callout (timeout)
> > > >
> > > > How do I do that? Do I have to use a soft interrupt handler?
> > >
> > > No, you just need to use the right spl calls to block the hard interrupt
> > > in the callout (placed outside the lock).
> > >
> > The question is this: what do you do in the interrupt handler or
> > timeout if you can't get the mutex? You can't sleep; there's no
> > process context.
> I think you have to spin. Since the splfoo() in non-interrupt code
> ensures that the current processor can't have been in the middle of the
> mutex protected code, you know that it must be some other processor that
> holds the lock. Eventually, that processor will release the mutex and
> the interrupt handler will get it. Of course, if the non-interrupt code
> holds that mutex for long the interrupt latency will suck.
It's more complex than that; the single- and multi-processor situations
If the spin lock is grabbed by mainline code, an interrupt routine
*can't* spin on it, because there's no way it will ever be released on
a uniprocessor. On a multiprocessor, spl() doesn't do the trick,
because another CPU may get in there. You need both.
In the mainline code, you do spl() to exclude local interrupt routines,
followed by a spinlock to exclude other processors; you release them in
the opposite order. In the interrupt routine, you may already have
interrupts masked, so you just do the spinlock. You'll always succeed
there on single CPUs, but putting the code in keeps you MP-safe.
If you really need to contend for a lock at interrupt level, you need
to schedule a kernel thread instead, since it can sleep.
--Steven M. Bellovin, http://www.cs.columbia.edu/~smb