Subject: Re: Synchronization with locks in kernel
To: Ben Harris <bjh21@netbsd.org>
From: Ian Zagorskih <ianzag@megasignal.com>
List: tech-kern
Date: 06/22/2003 22:34:20
On Sunday 22 June 2003 14:01, Ben Harris wrote:
> In article <200306222007.38719.ianzag@megasignal.com> you write:
> >So i want to block inside client's code waiting for some external
> >asynchronous event [hardware interrupt in my case].
> >
> >I have tried to do this with tsleep()/wakeup() synchronization calls l=
ike
> >this:
> >
> >--------
> >void dev_interrupt_handler(void *aux) {
> > struct dev_softc *sc =3D3D aux;
> >
> > wakeup(sc);
> >}
> >
> >dev_do_something() {
> > struct dev_softc *sc =3D device_lookup().
> >
> > dev_request_interrupt(sc); /* 1 */
> > print("tralala\n"); /* 2 */
> > tsleep(sc); /* 3 */
> >}
> >--------
> >
> >...but [obviously] i do loose interrupts when interrupt is occured fas=
t
> >enough i.e. between points 1 and 3 so tsleep(sc) is blocked too late a=
nd
> >for nothing.
>
> The usual way around this is to block interrupts in that period, so you=
'd
> do something like:
>
> dev_do_something() {
> struct dev_softc *sc =3D device_lookup();
> int s;
>
> s =3D spldev();
> dev_request_interrupt(sc);
> printf("tralala\n");
> tsleep(sc);
> splx(s);
> }
>
> where spldev() is whatever spl*() function is correct for your device,
> which depends on the level at which you established your interrupt hand=
ler.
> tsleep() handles saving and restoring the interrupt level in a way that
> won't lose wakeup()s.
>
Thanks Ben, now it works well with tsleep()/wakeup() calls :)
But how does it actually work ? What means "blocking interrupt at some le=
vel"=20
? I'm attaching ISA interrupt handler at IPL_SERIAL level so i call=20
splserial() to "block" interrupts of my level and after tsleep() returns =
i=20
unblock them. Ok, seems to work. But "man spl" says that:
------
splserial() blocks hard interrupts from serial interfaces (IPL_SERI-
AL). Code running at this level may not access the=
tty
subsystem. Generally, all code run at this level m=
ust
schedule additional processing to run in a software=
in-
terrupt. Note that code running at this priority i=
s not
blocked by splvm() (described below), and is theref=
ore
prohibited from using the kernel memory allocators.
------
i.e. as i understand, *all* interrupts of this level including RS232 port=
s etc=20
are blocked.
------
/* save old mask, block serial */
s =3D splserial();
/* request interrupt */
dev_request_interrupt(sc);
/* ---> IRQ line is active, atcuall interrupt is armed */
/* What happens here ? */
print("tralala\n");
tsleep(sc);
/* restpre old mask */
splx(s);
------
Anyway, for now this work around seems to work fine so thanks again :)
// wbr