350/*351 * Exit an interrupt context. Process softirqs if needed and possible:352 */353voidirq_exit(void)354{355#ifndef__ARCH_IRQ_EXIT_IRQS_DISABLED356local_irq_disable();357#else358WARN_ON_ONCE(!irqs_disabled());359#endif360361account_irq_exit_time(current);362trace_hardirq_exit();363sub_preempt_count(HARDIRQ_OFFSET);364if(!in_interrupt()&&local_softirq_pending())365invoke_softirq();366367tick_irq_exit();368rcu_irq_exit();369}
157staticinlinevoid_local_bh_enable_ip(unsignedlongip)158{159WARN_ON_ONCE(in_irq()||irqs_disabled());160#ifdefCONFIG_TRACE_IRQFLAGS161local_irq_disable();162#endif163/*164 * Are softirqs going to be turned on now:165 */166if(softirq_count()==SOFTIRQ_DISABLE_OFFSET)167trace_softirqs_on(ip);168/*169 * Keep preemption disabled until we are done with170 * softirq processing:171 */172sub_preempt_count(SOFTIRQ_DISABLE_OFFSET-1);173174if(unlikely(!in_interrupt()&&local_softirq_pending()))175do_softirq();176177dec_preempt_count();178#ifdefCONFIG_TRACE_IRQFLAGS179local_irq_enable();180#endif181preempt_check_resched();182}