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