wLiu2007 发表于 2014-08-12 20:33

软中断被打断,硬中断中触发新的更高优先级软中断时怎么处理

本帖最后由 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);
}


Tinnal 发表于 2014-08-12 21:21

回复 1# wLiu2007

新一批的软中断,无论优先级多高,也得等到前一批的软中断被处理完成之后才能得到处理。而优先级只能帮助软中断在对应的批次中优先得到处理。
   

wLiu2007 发表于 2014-08-13 12:41

这么看来 softirq的优先级是有场景限制的,跟进程的优先级还不太一样;

humjb_1983 发表于 2014-08-13 12:48

Linux中,中断没有优先级,而且中断执行过程中默认是关中断的,不会嵌套,而是串行执行。。。。

oscarvei 发表于 2014-08-13 16:23

本帖最后由 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();

Tinnal 发表于 2014-08-13 21:37

回复 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]
查看完整版本: 软中断被打断,硬中断中触发新的更高优先级软中断时怎么处理