X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=kernel%2Fsoftirq.c;h=582a1e8091bc651fcf714b3a6aeb7732ce9244f5;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=4a3da9be9f260474d744ad938c5ec07f9b687413;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/kernel/softirq.c b/kernel/softirq.c index 4a3da9be9..582a1e809 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -137,15 +137,39 @@ EXPORT_SYMBOL(do_softirq); void local_bh_enable(void) { - __local_bh_enable(); WARN_ON(irqs_disabled()); - if (unlikely(!in_interrupt() && - local_softirq_pending())) - invoke_softirq(); + /* + * Keep preemption disabled until we are done with + * softirq processing: + */ + sub_preempt_count(SOFTIRQ_OFFSET - 1); + + if (unlikely(!in_interrupt() && local_softirq_pending())) + do_softirq(); + + dec_preempt_count(); preempt_check_resched(); } EXPORT_SYMBOL(local_bh_enable); +#ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED +# define invoke_softirq() __do_softirq() +#else +# define invoke_softirq() do_softirq() +#endif + +/* + * Exit an interrupt context. Process softirqs if needed and possible: + */ +void irq_exit(void) +{ + account_system_vtime(current); + sub_preempt_count(IRQ_EXIT_OFFSET); + if (!in_interrupt() && local_softirq_pending()) + invoke_softirq(); + preempt_enable_no_resched(); +} + /* * This function must run with irqs disabled! */ @@ -177,8 +201,6 @@ void fastcall raise_softirq(unsigned int nr) local_irq_restore(flags); } -EXPORT_SYMBOL(raise_softirq); - void open_softirq(int nr, void (*action)(struct softirq_action*), void *data) { softirq_vec[nr].data = data;