diff options
Diffstat (limited to 'kernel/softirq.c')
| -rw-r--r-- | kernel/softirq.c | 23 | 
1 files changed, 12 insertions, 11 deletions
diff --git a/kernel/softirq.c b/kernel/softirq.c index ed567babe78..b4d252fd195 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -195,21 +195,21 @@ void local_bh_enable_ip(unsigned long ip)  EXPORT_SYMBOL(local_bh_enable_ip);  /* - * We restart softirq processing MAX_SOFTIRQ_RESTART times, - * and we fall back to softirqd after that. + * We restart softirq processing for at most 2 ms, + * and if need_resched() is not set.   * - * This number has been established via experimentation. + * These limits have been established via experimentation.   * The two things to balance is latency against fairness -   * we want to handle softirqs as soon as possible, but they   * should not be able to lock up the box.   */ -#define MAX_SOFTIRQ_RESTART 10 +#define MAX_SOFTIRQ_TIME  msecs_to_jiffies(2)  asmlinkage void __do_softirq(void)  {  	struct softirq_action *h;  	__u32 pending; -	int max_restart = MAX_SOFTIRQ_RESTART; +	unsigned long end = jiffies + MAX_SOFTIRQ_TIME;  	int cpu;  	unsigned long old_flags = current->flags; @@ -221,7 +221,7 @@ asmlinkage void __do_softirq(void)  	current->flags &= ~PF_MEMALLOC;  	pending = local_softirq_pending(); -	vtime_account_irq_enter(current); +	account_irq_enter_time(current);  	__local_bh_disable((unsigned long)__builtin_return_address(0),  				SOFTIRQ_OFFSET); @@ -264,15 +264,16 @@ restart:  	local_irq_disable();  	pending = local_softirq_pending(); -	if (pending && --max_restart) -		goto restart; +	if (pending) { +		if (time_before(jiffies, end) && !need_resched()) +			goto restart; -	if (pending)  		wakeup_softirqd(); +	}  	lockdep_softirq_exit(); -	vtime_account_irq_exit(current); +	account_irq_exit_time(current);  	__local_bh_enable(SOFTIRQ_OFFSET);  	tsk_restore_flags(current, old_flags, PF_MEMALLOC);  } @@ -341,7 +342,7 @@ static inline void invoke_softirq(void)   */  void irq_exit(void)  { -	vtime_account_irq_exit(current); +	account_irq_exit_time(current);  	trace_hardirq_exit();  	sub_preempt_count(IRQ_EXIT_OFFSET);  	if (!in_interrupt() && local_softirq_pending())  |