Re: Interrupt/Sleep deadlock

From: Matthew Dharm (mdharm-kernel@one-eyed-alien.net)
Date: Thu Sep 28 2000 - 20:32:43 EST


Heh.. I needed to figure this out about 6 months ago. Here's the "right
answer"

Before sending the command to the board, call
set_current_state(TASK_UNINTERRUPTIBLE). This will prevent the scheduler
from interrupting your task, but more importantly it will prevent your task
from being re-scheduled (once you give up control) until the task is woken
up (which sets the state to TASK_RUNNING).

Then, send the command to the board. Then call schedule() or
schedule_timeout() -- that won't return until your task is at TASK_RUNNING.
Now, if the interrupt fires before you call schedule, then schedule will
simply reschedule. But, the wakeup re-set the state to TASK_RUNNING for
you, so your task _will_ get rescheduled (avoiding the deadlock).

See linux/drivers/usb/storage/transport.c usb_stor_bulk_msg() for the code
I wrote that uses this. The key is in setting TASK_UNINTERRUPTABLE
_before_ you send the command, so that it doesn't race with the interrupt.

Matt

On Thu, Sep 28, 2000 at 06:26:17PM -0700, Ivan Passos wrote:
>
> Hello,
>
> In order to get the configuration of a board, I have to send, from
> userspace, an ioctl to the driver and wait for the board to complete its
> action. The way this is implemented is as follows:
> - In the ioctl, the driver sends a command to the board and then goes to
> sleep (interruptible_sleep_on(&info->config_wait));
> - The board receives the command, handles it and answers back with an
> interrupt;
> - The driver's interrupt handler schedules a bottom-half action.
> - The bottom-half calls wake_up_interuptible(&info->config_wait).
> - The ioctl returns and the userspace application has the board
> configuration.
>
> Now, the problem: the board is so fast that it interrupts back _before_
> the driver goes to sleep, i.e.:
> - Driver sends command to board;
> - Driver goes to sl... interrupt back from board!!
> - Interrupt handler schedules bottom-half.
> - Bottom-half calls wake_up.
> - Ioctl continues, and _then_ goes to sleep. System locked.
>
> I can't disable interrupts before going to sleep, because the event that
> wakes me up is an interrupt. However, if I don't protect it from the
> interrupts, the system locks ...
>
> Is there any other way in Linux to implement this?!?!?!
>
> Thanks in advance for any help.
>
> Later,
> Ivan
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> Please read the FAQ at http://www.tux.org/lkml/

-- 
Matthew Dharm                              Home: mdharm-usb@one-eyed-alien.net 
Maintainer, Linux USB Mass Storage Driver

C: They kicked your ass, didn't they? S: They were cheating! -- The Chief and Stef User Friendly, 11/19/1997


- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sat Sep 30 2000 - 21:00:23 EST