尽管软中断处理可以在中断之后进行,内核设计者也实现了软中断在内核线程上下文运行。即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();
}