- 论坛徽章:
- 0
|
yandongxiao 发表于 2014-02-18 21:00 ![]()
那么接下来,执行软中断A还是软中断B呢? 是软中断A运行完以后,立即运行B,还是会放入队列当中啊?
如果你这里的软中断时指softirq的话,那么:
查看了一下代码,流程应该是这样:
1. 当某CPU正在run softirq A,这时来了一个硬件中断,硬件中断打断软件中断;
2. 硬件中断在上半部raise了软中断B的pending标志;
3. 硬件中断运行完毕,call irq_exit :- void irq_exit(void)
- {
- account_system_vtime(current);
- trace_hardirq_exit();
- sub_preempt_count(IRQ_EXIT_OFFSET);
- if (!in_interrupt() && local_softirq_pending())
- invoke_softirq();
- rcu_irq_exit();
- #ifdef CONFIG_NO_HZ
- /* Make sure that timer wheel updates are propagated */
- if (idle_cpu(smp_processor_id()) && !in_interrupt() && !need_resched())
- tick_nohz_stop_sched_tick(0);
- #endif
- preempt_enable_no_resched();
- }
复制代码 4. 注意这里的代码:
if (!in_interrupt() && local_softirq_pending())
invoke_softirq();
是说如果现在的环境本身就是在中断中(软中断也是在中断环境中),那么!in_interrupt()就会返回false,那么就不会运行invoke_softirq()
5. 硬件中断继续返回到被打断的地方(即先前的softirq A的处理中),kernel继续运行softirq A。
请注意在step 2中kernel已经raise了softirq B的pending位,所以在函数__do_softirq中,会重新check到softirq B的bit,从而运行softirq B的action- restart:
- /* Reset the pending bitmask before enabling irqs */
- set_softirq_pending(0);
- local_irq_enable();
- h = softirq_vec;
- do {
- if (pending & 1) {
- int prev_count = preempt_count();
- kstat_incr_softirqs_this_cpu(h - softirq_vec);
- trace_softirq_entry(h, softirq_vec);
- h->action(h);
- trace_softirq_exit(h, softirq_vec);
- if (unlikely(prev_count != preempt_count())) {
- printk(KERN_ERR "huh, entered softirq %td %s %p"
- "with preempt_count %08x,"
- " exited with %08x?\n", h - softirq_vec,
- softirq_to_name[h - softirq_vec],
- h->action, prev_count, preempt_count());
- preempt_count() = prev_count;
- }
- rcu_bh_qs(cpu);
- }
- h++;
- pending >>= 1;
- } while (pending);
- local_irq_disable();
- pending = local_softirq_pending();
- if (pending && --max_restart)
- goto restart;
复制代码 |
|