Почему запланированный тасклет из обработчика прерываний не будет запущен
У меня есть обработчик прерываний, который планирует тасклет следующим образом (псевдокод) -
struct tasklet_struct mytasklet;
void my_tasklet_function(unsigned long arg1) {
...
pr_alert("Inside tasklet function\n");
...
}
int my_probe() {
....
....
tasklet_init(&mytasklet, my_tasklet_function, arg1);
....
/* Register interrupt handler my_irq_handler*/
....
}
irqreturn_t my_irq_handler(int irq, void *data) {
...
status = read_reg(base_addr, intr_status_reg_offset)
write_reg(base_addr, intr_status_reg_offset, status);
if (status & INTR_MASK_1) {
....
pr_alert("intr 1 came\n");
}
...
...
pr_alert("Schedule tasklet\n");
tasklet_schedule(&mytasklet);
pr_alert("Exit irq\n");
return IRQ_HANDLED;
}
Замечено, что ядро зависает после следующих распечаток
intr 1 came
Schedule tasklet
Печать "Выход из IRQ" никогда не появляется. Отпечатки в функции тасклета не печатаются.
Что может быть причиной того, что этот тасклет не был запланирован?
Что может вызвать зависание ядра?
1 ответ
Планирование тасклетов НЕ должно выполняться в обработчике IRQ. Вы можете проверить код schedule_tasklet() в lxr. В обработчике IRQ вызов schedule_tasklet() только устанавливает бит для softirq и связывает ваш тасклет.
Когда вызывается irq_exit(), он проверяет, находится ли он все еще в контексте прерывания (вложенное прерывание). Если нет, и есть какой-либо активированный тасклет, он вызовет обработчики softirq, которые, в свою очередь, вызовут тасклет.