Event notification from kernel space to user space
Asked Answered
R

1

6

How to notify the user space application whenever an event occurs in the kernel space?

A hardware generates an interrupt when the data arrives at some GPIO. This data is copied to the kernel buffer. At this point, I want the driver to notify the application that it can call read function to copy the data form kernel buffer to user space buffer.

I thought of using epoll method, but epoll indicates whether the device is ready to be read from. What I want is that, epoll to indicate whenever kernel buffer is full.

And, is there a way to modify the behavior of poll_wait() function in the driver?

Romantic answered 27/6, 2014 at 5:40 Comment(7)
A device is read to be read from when there is some data to be read. So what exactly is the problem?Glynis
The problem is that, after the driver reads the data from the device to the kernel buffer, an interrupt is generated. In the ISR I want the poll_wait() function to wake up and set the mask to POLLIN. Is poll_wait() function in our control?Romantic
Have a look at the second parameter of poll_wait.Glynis
It's a pointer to wait_queue_head_t. Can I use wake_up() in ISR?Romantic
That's what it's for. Did you ever bother to read some documentation?Glynis
I've been reading that book. Thanks anyway.Romantic
Let us continue this discussion in chat.Romantic
F
12

(Had replied in the chat session but it seems like this should be in an answer so putting it here with more detail.)

What poll_wait does is add your driver to the list of file descriptors being waited for by the user space program. The pattern is:

  • user program calls poll/select/epoll_ctl
  • core kernel calls your driver's poll entry point
  • driver calls poll_wait to add its wait queue to the list of waitqueues (unless the GPIO data is already readable, which you indicate via return value)
  • later, when the device interrupts, you call wake_up on your wait queue, this unblocks the process if it's (still) waiting in a poll/select call
  • user-mode program wakes up, calls read to actually obtain the data

IOW, poll_wait itself doesn't sleep (or block); it just adds your device to the list of programs that might wake the process up later. The sleep is done in the core kernel (inside the select system call, for example). That way, a user program can wait on any number of devices at once using select.

If your user-space program really doesn't have anything else to do while waiting, then you can simply have the user-program call read, and have your driver set up its wait queue and call wait_event_interruptible (or one of the other wait_event_* variants). This will block the process until your interrupt handler calls wake_up; at which time you copy from kernel buffer to user buffer.

Or you could support both methods. Typically if you support the select method, you also check the O_NONBLOCK file flag in your read function so that the user code has the option to not block in the read.

Yes, ISRs can call wake_up. It's a common pattern for device I/O: wait/block in "process context", wake-up in "interrupt context", then complete the I/O after returning to process context.

BTW, from the driver point of view, using select, poll or epoll are typically the same. From the user point of view, using select or poll is somewhat easier. It's a "one shot" deal: "here are a set of file descriptors; block until one of them is ready for read (or write etc) or until a timeout".

Whereas with epoll, you first create an epoll descriptor, then add I/O file descriptors individually. But then the "wait" call just specifies the single epoll descriptor. So if you have a large number of file descriptors to wait on, you don't have to specify all of them in each system call which leads to lower system call overhead on each epoll call.

Freestanding answered 27/6, 2014 at 21:35 Comment(4)
Hi, does the handler of epoll (in userspace) is done in interrupt context ?Garnet
No. Nothing in userspace is ever done in interrupt context.Freestanding
Does latency from kernel to userspace is smaller with poll_wait or wait_event_interruptible ?Garnet
The difference is unlikely to be measurable.Freestanding

© 2022 - 2024 — McMap. All rights reserved.