softirq 真正干活的函数是__do_softirq。 linuxv3.11内核里能够执行__do_softirq,有如下调用, 这里指真正执行softirq的地方,不是触发(设置)softirq标志 !!!
每个硬中断退出的时。 当bh使能的时。 发送回环报文时。NOTE: 使能bh的时候,刚开始抢占还是禁止的。只有软中断处理完了后,抢占才使能的。 顺便说一下,使能bh时,有可能发生进程切换(见preempt_check_resched).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 157 static inline void _local_bh_enable_ip(unsigned long ip) 158 { 159 WARN_ON_ONCE(in_irq() || irqs_disabled()); 160 #ifdef CONFIG_TRACE_IRQFLAGS 161 local_irq_disable(); 162 #endif 163 /* 164 * Are softirqs going to be turned on now: 165 */ 166 if (softirq_count() == SOFTIRQ_DISABLE_OFFSET) 167 trace_softirqs_on(ip); 168 /* 169 * Keep preemption disabled until we are done with 170 * softirq processing: 171 */ 172 sub_preempt_count(SOFTIRQ_DISABLE_OFFSET - 1); 173 174 if (unlikely(!in_interrupt() && local_softirq_pending())) 175 do_softirq(); 176 177 dec_preempt_count(); 178 #ifdef CONFIG_TRACE_IRQFLAGS 179 local_irq_enable(); 180 #endif 181 preempt_check_resched(); 182 }当对应的硬件体系里没有定义do_softirq时,使用 kernel/softirq.c中通用的do_softirq`.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 286 #ifndef __ARCH_HAS_DO_SOFTIRQ 287 288 asmlinkage void do_softirq(void) 289 { 290 __u32 pending; 291 unsigned long flags; 292 293 if (in_interrupt()) 294 return; 295 296 local_irq_save(flags); 297 298 pending = local_softirq_pending(); 299 300 if (pending) 301 __do_softirq(); 302 303 local_irq_restore(flags); 304 } 305 306 #endif而对于X86_64,有其自己的定义。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 92 extern void call_softirq(void); 93 94 asmlinkage void do_softirq(void) 95 { 96 __u32 pending; 97 unsigned long flags; 98 99 if (in_interrupt()) 100 return; 101 102 local_irq_save(flags); 103 pending = local_softirq_pending(); 104 /* Switch to interrupt stack */ 105 if (pending) { 106 call_softirq(); 107 WARN_ON_ONCE(softirq_count()); 108 } 109 local_irq_restore(flags); 110 }其中call_softirq是个用汇编语言写的一个函数定义在 arch/x86/kernel/entry_64.S
这一块的理解不是很透,仅以一个具体的例子来说明。发送回环报文.
loopback 报文会通过netif_rx函数,被重新放回到 per_cpu变量softnet_data下的队列input_pkt_queue里, 同时激发napi调用,进而激发软中断调用(只是设置标志位,不是真正调用)
另外,注意netif_rx_ni里没有禁止bh调度,而是只是禁止了抢占(preempt_disable).
Posted by Martin Sep 23rd, 2013 10:36 am irqs
http://martinbj2008.github.io/blog/2013/09/23/where-softirq-is-invoked/