interruptible_sleep_on, interrupts and device drivers

From: Gabriele Brugnoni (news_at_dveprojects.com)
Date: 10/13/05

  • Next message: Gary: "Dumb question on embedded Linux - why?"
    Date: Thu, 13 Oct 2005 18:29:15 +0200
    
    

    Hello,
    First of all, this message may has already been posted on linux.kernel
    newsgroup, I'm not sure if was successfully sent or not. I apologize for
    the inconvenient.

    I'm writing a device driver for a UART to be used to drive a RS485 line.
    I would use the interruptible_sleep_on function to wait for receiver ready,
    or for the transmitter to finish.
    I've take a look at how other device driver use this function, and a big
    question is born on my mind:

    In several device driver I've seen that:

    The code check for the availability of data.
    If not available, a call the interruptible_sleep_on is made.
    In the interrupt handler, when data becomes ready, a wakeup_interruptible
    call is made.

    Often the variables that indicates if data is available or not are tested
    between spin_lock and unlock (or save_irq and restore_irq) so that the
    interrupt handler cannot change the status during check.

    But:
    If the test is made with IRQ closed, and IRQ are then enabled after the test
    but before the call to interruptible_sleep_on, what happen if the handler
    break the procedure immediately before entering the interruptible_sleep_on
    function ?
    I beleave that the interrupt handler, calling the wakeup function, will not
    wake our process, because is not in the waiting list. But at return from
    IRQ handler, the process will continue execution calling the sleep
    function, and nobody will wake it because the data is now already available.

    I try to explain better with an example:

    This may be a function that should wait that the UART send all chars.
    When the interrupt for shift empty will be serviced, the
    wakeup_interruptible function will wake all waiting processes in wait list.

    10: void waitEndTX ( void )
    11: {
    12: unsigned long flags;
    13:
    14: //....
    15:
    16: spin_lock_irqsave(&mylock, flags);
    17: if( tx_done ) {
    18: spin_lock_irqrestore(&mylock, flags);
    19: return;
    20: }
    21: spin_lock_irqrestore(&mylock, flags);
    22: interruptible_sleep_on ( &uartwait );
    23:}

    This type of code is very used in a lot of device drivers, in kernel 2.6.x
    (the char/specialix, for example).

    OK, Now we suppose that the UART finish to send the character exactely when
    the process has closed the IRQ and is about to the the tx_done variable.
    (At line 17 for example).
    The hardware will asserts the IRQ line, but the processor has the IRQ
    closed, so the execution will continue in our process.
    Now at line 21 our process enable the IRQ.
    The CPU will immediately jumps to irq handler, breaking the execution at
    line 22. Our handler will set the variable tx_done to one.
    When the cpu control returns to our calling process, at line 21, the tx_done
    has already tested and it's value was zero. The execution continue with the
    call to interruptible_sleep_on function, that will put our process in the
    uartwait queue, but nobody will wakeup it.

    If this is true, a lot of device driver in linux kernel may have this
    problem. This sound me very strange, so where I'm wrong ?

    Thanks in advance.
    Gabriele


  • Next message: Gary: "Dumb question on embedded Linux - why?"

    Relevant Pages

    • interruptible_sleep_on, interrupts and device drivers
      ... I'm writing a device driver for a UART to be used to drive a RS485 line. ... In the interrupt handler, when data becomes ready, a wakeup_interruptible ... If the test is made with IRQ closed, and IRQ are then enabled after the test ...
      (Linux-Kernel)
    • [RFC][PATCH] irq: remove IRQF_DISABLED
      ... Subject: irq: remove IRQF_DISABLED ... all reported to the kernel as machine checks, so the handler ... static struct irqaction aaec2000_timer_irq = { ... goto err_request_irq; ...
      (Linux-Kernel)
    • Re: [RFC][PATCH] Cascaded interrupts: a simple solution
      ... IRQ layer and thus make the generic IRQ layer truly generic. ... information is permanently lost and we end up losing interrupts. ... clean way to handle this type of cascading via the 'return irq' method.) ... demultiplexing into the _demultiplexing handler_, ...
      (Linux-Kernel)
    • Please pull git390 for-linus branch
      ... determine the device driver owning the device that raised the interrupt. ... -Linux/390 preserves the IRQ concept and semantically maps the ESA/390 ... --ENODEV - cdev invalid. ... This call enables a device driver to get information about supported commands ...
      (Linux-Kernel)
    • Re: [patch 2/9] LTTng instrumentation - irq
      ... interrupts and to detect interrupts with max/min/avg duration. ... Those tracepoints are used by LTTng. ... The IRQ instrumentation instruments the IRQ handler entry and exit. ...
      (Linux-Kernel)