Re: Problems writting a CHAR Driver with interruptible_sleep (wait_queu e)

Andreas Bombe (andreas.bombe@munich.netsurf.de)
Fri, 13 Aug 1999 16:35:16 +0200


On Thu, Aug 12, 1999 at 02:51:33PM -0300, Raul Dias wrote:
>
> Here is how it should work:
>
> When a user tries to read the device (/dev/chaos0),
> the chaos_read() function (responsable for file reading in the module)
> have to do an "outb(board)" to "ask" the board to acquire data.
>
> then it goes to sleep with an interruptible_sleep_on();
>
> When the DATA is ready, it does an interrupt.
> The interrupt handler uses a wake_up_interruptible() to wake the
> process on chaos_read() that will actually read the data (inb) and
> output it.
>
>
> Everything is fine, except that:
>
> sometimes, after a few reads, the interrupt occurs before the proccess
> complete the "interruptible_sleep_on()" call.

There is an easy, but probably not so obvious fix: do the things in
(interruptible_)sleep_on yourself in the right order. There is no
prepackaged function doing that for you.

Take a look at these function's implementation to understand the
following example better.

#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)
DECLARE_WAITQUEUE(wait, current);
#else
struct wait_queue wait;
wait.task = current;
#endif

add_wait_queue(&wait_queue, &wait);
current->state = TASK_INTERRUPTIBLE;
/* or TASK_UNINTERRUPTIBLE */

outb(ioport, 0xFF); /* Ask for data */

schedule(); /* Go to sleep (or not) */
remove_wait_queue(&wait_queue, &wait);
/* Have a nice oops if you forget to remove */

data = inb(ioport); /* There you go */

This solves the problem by setting the state to sleep and only after
that to trigger the interrupt. If the interrupt happens and
wake_up_interruptible() is called before the schedule() then
current->state will be TASK_RUNNING again and make schedule() return
immediately (or not, if it finds a better task to run).

-- 
    Andreas E. Bombe <andreas.bombe@munich.netsurf.de>
    http://home.pages.de/~andreas.bombe/
RSA 0x886663c9  30 EC 09 73 84 7B 55 83  C4 7A 91 D9 9D C5 4B B0
DSA 0x04880A44 72E5 7031 4414 2EB6 F6B4  4CBD 1181 7032 0488 0A44

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