尽管软中断处理可以在中断之后进行,内核设计者也实现了软中断在内核线程上下文运行。即softirqdX类。
定义每CPU线程:
DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
static struct smp_hotplug_thread softirq_threads = { .store = &ksoftirqd, .thread_should_run = ksoftirqd_should_run, .thread_fn = run_ksoftirqd, .thread_comm = "ksoftirqd/%u", };
static __init int spawn_ksoftirqd(void) { cpuhp_setup_state_nocalls(CPUHP_SOFTIRQ_DEAD, "softirq:dead", NULL, takeover_tasklets); BUG_ON(smpboot_register_percpu_thread(&softirq_threads));
return 0; } early_initcall(spawn_ksoftirqd);
需要注意ksoftirqd的定义和其对softirq_threads的store的赋值。这样后面wakeup_softirqd()就可以对softirqd进行唤醒了。
static void wakeup_softirqd(void) { /* Interrupts are disabled: no need to stop preemption */ struct task_struct *tsk = __this_cpu_read(ksoftirqd);
if (tsk && tsk->state != TASK_RUNNING) wake_up_process(tsk); }
kthread--> smpboot_thread_fn --> run_ksoftirqd:
static void run_ksoftirqd(unsigned int cpu) { local_irq_disable(); if (local_softirq_pending()) { /* * We can safely run softirq on inline stack, as we are not deep * in the task stack here. */ __do_softirq(); local_irq_enable(); cond_resched_rcu_qs(); return; } local_irq_enable(); }