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/