I write a kernel module that uses kernel threads and semaphores.
I call up(...)
function for semaphore from interrupt handler and then my kthread starts to execute.
static int interrupt_handler_thread(void *data)
{
/* duty cycle */
while (!kthread_should_stop()) {
/*
* If semaphore has been uped in the interrupt, we will
* acquire it here, else thread will go to sleep.
*/
if (!down_interruptible(mysem)) {
/* proccess gpio interrupt */
dev_info(dev, "gpio interrupt detected\n");
}
}
do_exit(0);
return 0;
}
The semaphore and thread are initializated into module_init function. Error checking was omitted.
...
sema_init(mysem, 0);
thread = kthread_create(interrupt_handler_thread,client,"my_int_handler");
wake_up_process(thread);
...
And during unloading a module the semaphore and the thread are removed:
/*
* After this call kthread_should_stop() in the thread will return TRUE.
* See https://lwn.net/Articles/118935/
*/
kthread_stop(thread);
/*
* Release the semaphore to return
* from down_interruptible() function
*/
up(mysem);
When I try to unload my module the one frozes into thread in down_interruptible()
function, because it waits while the semaphore ups in interrupt handler. And my code never returns from kthread_stop()
.
It seems, I need to disable the interrupt from my gpio, up the semaphore by hand and call kthread_stop()
function. But it is a potential bug, because after the semaphore is uped by hand, the thread starts executing and the one can again down_interruptible()
after its duty cycle.
Could anyone help me, please?
PS: I know about this question, but, it seems, this is not my case.