How to run longer code in an ISR - kthread isn't working
Hi,
hopefully I found the right forum to post my question. The basic setting is that I'm developing a device driver as Linux Kernel Module which listens on an interrupt of an external device. Using request_irq(ird_id, (irq_handler_t) handler, IRQF_DISABLED, "yyy", NULL); I can successfully register my callback for the interrupt. The interrupt is also fired at the right moment. So my final source code - which I need to run after the interrupt was triggered - will take between 500 µs and 10 ms. It works just fine placing the code inside the ISR, but I learned that such "fragile" functions should be as short as possible. I thought that a kthread would be ideal: it contains the source code to be executed and in the ISR a call to kthread_run() is short and enough to start it. Therefore my ISR looks like: Code:
struct task_struct *task; Beneath some mistakes in my code (which I'll check a second time for tomorrow): is there any reason why this didn't work? How to fix it? Or is there an even better way to perform my task? Regards, maduino |
A typical reason would be getting another interrupt before finishing processing on the first one.
|
Quote:
Is it save to block an ISR for 250 µs? Where is the border? |
250,000 nsec is a long time. The normal scheme is to do the minimum processing in the ISR, put the work on a queue, and poke the kthread. The kthread wakes up, checks the queue, and runs til its empty. If the queue is full, the ISR starts dropping work and logs an error to avoid hanging the rest of the system. The network stack doesn't even log an error, it's such a common occurrence that it just counts dropped packets and lets the TCP protocol sort it out.
|
Quote:
|
The key idea here is that it "pokes" the thread, in order to be certain that the thread is not asleep, after first putting a new unit-of-work onto the queue (if it can). Every (productive) interrupt "wakes up the sleepyhead." It does not create the thread, nor start it: the thread is always out there.
The thread, since it does operate asynchronously, can take as long as it needs to, to complete any request. (Of course, it must be mindful that it must not monopolize kernel time, since it can't be pre-empted.) Another strategy that is sometimes used is a "virtual device driver," which actually exposes a /dev entry (or somesuch ...) that a suitably privileged user-land daemon can use. The kernel thread hands-off the work to user-land, using ordinary and easy-to-use filesystem semantics. As always, look through the kernel source tree (and GitHub) for "prior art." :) "Somebody out there has already done this ... I don't need to write this from scratch. I just need to steal 'borrow it,' then whack on it until it becomes what I need." (And then, like a good netizen, contribute it back to GitHub ...) |
All times are GMT -5. The time now is 10:39 AM. |