I have a driver that wants to send notification to the user about a status change. In the current implementation it uses the proc filesystem to do so. The read process loops around a read() to the proc filesystem. The read() blocks with wait_event_interruptible() until the kernel gets an interrupt which causes the write_new_data() function to call wake_up_interruptible(). Here’s the basic code (removed all unneeded clutter):
static int flag=0;
DECLARE_WAIT_QUEUE_HEAD(info_wq);
//user process call read() on /proc/myfile to get to this function
int my_proc_read (struct file *filp, char *buf, size_t count, loff_t *pos)
{
wait_event_interruptible(info_wq, flag != 0);
flag = 0;
//copy buffers to user
return 0;
}
//when an interrupt comes it schedules this function on the systems' work queue
void write_new_data ()
{
//fill buffer with data
flag = 1;
wake_up_interruptible(&info_wq);
}
Now consider the following flow:
- User process calls
read(), then waits. - interrupt occurs ->
write_new_data()is called. writes data and callswake_up_interruptible(). read()is awaken, reads data but process has not rerun read (wasn’t scheduled
to run, didn’t get to it because of the next interrupt…).- interrupt occurs ->
write_new_data()is triggered again, callswake_up_interruptible()but no waiting thread is waiting… - process calls read and blocks.
Note: this all happens on a uni-processor system. Also there is only one thread reading and one thread writing new data.
How can I avoid missing the second interrupt? (One solution is to use netlink sockets but I was wondering if there is a way to do it in /proc land)
Since the interrupt can occur between the call to
wait_event_interruptibleandflag = 0, it would affect theflagvariable in an unwanted way.Note that even on a UP machine, the kernel could be preemptive depending on the configuration, and that code would be affected as a result.
Also, I advice to not use a simple ‘int’ flag. Instead, you should use
atomic_tandatomic_dec/inc_*operations. See the implementation of completions inside the kernel, it does something similar to what you are doing here.About the question itself:
If you’ll look in the code of
wait_event_interruptibleyou’ll see that the sleep doesn’t take place if the condition is true – so your problem is a non-problem.