软中断被打断,硬中断中触发新的更高优先级软中断时怎么处理
本帖最后由 wLiu2007 于 2014-08-12 20:56 编辑假设当前有3个softirq处于pending状态,然后__do_softirq正在处理第1个软中断,这个时候硬中断发生了,硬中断里面trigger了1个新的更高优先级的softirq,当中断返回的时候,检查in_interrupt不为0,所以不会重新调用do_softirq,而是返回中断前的__do_softirq中,
被中断的地方如果是在do_while这个循环中的话,只有等将pending标记的那些softirq都处理完了,才会处理新触发的softirq, 即这个时候需要将前3个softirq都处理完了才会处理这个新的softirq,尽管新触发的softirq优先级更高一些,不知道理解是否正确?
asmlinkage void __do_softirq(void)
{
struct softirq_action *h;
__u32 pending;
int max_restart = MAX_SOFTIRQ_RESTART;
int cpu;
unsigned long old_flags = current->flags;
/*
* Mask out PF_MEMALLOC s current task context is borrowed for the
* softirq. A softirq handled such as network RX might set PF_MEMALLOC
* again if the socket is related to swap
*/
current->flags &= ~PF_MEMALLOC;
pending = local_softirq_pending();
account_system_vtime(current);
__local_bh_disable((unsigned long)__builtin_return_address(0),
SOFTIRQ_OFFSET);
lockdep_softirq_enter();
cpu = smp_processor_id();
restart:
/* Reset the pending bitmask before enabling irqs */
set_softirq_pending(0);
local_irq_enable();
h = softirq_vec;
do {
if (pending & 1) {
unsigned int vec_nr = h - softirq_vec;
int prev_count = preempt_count();
kstat_incr_softirqs_this_cpu(vec_nr);
trace_softirq_entry(vec_nr);
h->action(h);
trace_softirq_exit(vec_nr);
if (unlikely(prev_count != preempt_count())) {
printk(KERN_ERR "huh, entered softirq %u %s %p"
"with preempt_count %08x,"
" exited with %08x?\n", vec_nr,
softirq_to_name, h->action,
prev_count, preempt_count());
preempt_count() = prev_count;
}
rcu_bh_qs(cpu);
}
h++;
pending >>= 1;
}while (pending); ///////////////////////////////////////////////////////////////////////////////////////while
local_irq_disable();
pending = local_softirq_pending();
if (pending && --max_restart)
goto restart;
if (pending)
wakeup_softirqd();
lockdep_softirq_exit();
account_system_vtime(current);
__local_bh_enable(SOFTIRQ_OFFSET);
tsk_restore_flags(current, old_flags, PF_MEMALLOC);
}
回复 1# wLiu2007
新一批的软中断,无论优先级多高,也得等到前一批的软中断被处理完成之后才能得到处理。而优先级只能帮助软中断在对应的批次中优先得到处理。
这么看来 softirq的优先级是有场景限制的,跟进程的优先级还不太一样; Linux中,中断没有优先级,而且中断执行过程中默认是关中断的,不会嵌套,而是串行执行。。。。 本帖最后由 oscarvei 于 2014-08-13 16:29 编辑
回复 1# wLiu2007
假设当前有3个softirq处于pending状态,然后__do_softirq正在处理第1个软中断,这个时候硬中断发生了,硬中断里面trigger了1个<====楼主,硬中断可以被响应
我的理解,激发软中断,但是 irq还是disable的状态。应该无法响应新的硬中断。
373 /*
374* Exit an interrupt context. Process softirqs if needed and possible:
375*/
376 void irq_exit(void)
377 {
378 #ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED
379 local_irq_disable();
380 #else
381 WARN_ON_ONCE(!irqs_disabled());
382 #endif
383
384 account_irq_exit_time(current);
385 preempt_count_sub(HARDIRQ_OFFSET);
386 if (!in_interrupt() && local_softirq_pending())
387 invoke_softirq(); 回复 5# oscarvei
呵呵,虽然在此处关闭的中断,但在__do_softirq(void)里还是会打开中断的。软中断的Linux的概念里就是开中断运行的,如果它也是关中断的,那上下半的优点就全部丧失了。下面的代码来自 3.16内核,因为在早期的内核,如我手上的2.6.24内核,irq_exit是没有关中断的代码的。
226 asmlinkage __visible void __do_softirq(void)
227 {
228 unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
229 unsigned long old_flags = current->flags;
230 int max_restart = MAX_SOFTIRQ_RESTART;
231 struct softirq_action *h;
232 bool in_hardirq;
233 __u32 pending;
234 int softirq_bit;
235
236 /*
237 * Mask out PF_MEMALLOC s current task context is borrowed for the
238 * softirq. A softirq handled such as network RX might set PF_MEMALLOC
239 * again if the socket is related to swap
240 */
241 current->flags &= ~PF_MEMALLOC;
242
243 pending = local_softirq_pending();
244 account_irq_enter_time(current);
245
246 __local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET);
247 in_hardirq = lockdep_softirq_start();
248
249 restart:
250 /* Reset the pending bitmask before enabling irqs */
251 set_softirq_pending(0);
252
253 local_irq_enable();
254
255 h = softirq_vec;
256
257 while ((softirq_bit = ffs(pending))) {
258 unsigned int vec_nr;
259 int prev_count;
页:
[1]