Messages in this thread | | | Date | Sat, 14 Aug 1999 09:52:47 -0400 (EDT) | From | Benjamin LaHaise <> | Subject | Re: Problems writting a CHAR Driver with interruptible_sleep (wait_queu e) |
| |
> sometimes, after a few reads, the interrupt occurs before the proccess > complete the "interruptible_sleep_on()" call. > > Then, the interrupt handler tries to wake it up, but it has not > slept yet.
What you're looking for is a construct that's widely used in the kernel to eliminate races with interrupts f:
struct wait_queue *my_wait_queue = NULL;
foo_irq() { wake_up_interruptible(&my_wait_queue); }
foo_read() { struct wait_queue wait = { current, NULL };
current->state = TASK_INTERRUPTIBLE; add_wait_queue(&my_wait_queue, &wait);
/* now start the hardware. if the interrupt comes in before we * enter schedule, the task is set back to TASK_RUNNING and the * schedule becomes a no-op */ ...
schedule(); if (signal_pending(current)) ret = -ERESTARTSYS;
...cleanup
remove_wait_queue(&my_wait_queue, &wait); return ret; }
Basically, a task puts it self onto the list for whatever it is waiting before it starts the process that will lead to the wakeup. This solves the problem with interrupts. interruptible_sleep_on can only really be used if you're waiting on another task. For 2.3, the declaration for my_wait_queue can become a wait_queue_head_t my_wait_queue; init_wait_queue(&my_wait_queue_head_t) (there's a macro for use in variable declarations), and use DECLARE_WAITQUEUE(wait, current); instead of defining the structure. Of course, using macros and always writing the 2.3 form is easier. =) You may wish to make your driver trigger the data acquesition and buffer results rather than starting from userland each time to speed things up. Also, if latency is a concern rtlinux will be worth investigating.
-ben
- 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/
| |