diff options
Diffstat (limited to 'kernel/softirq.c')
| -rw-r--r-- | kernel/softirq.c | 13 | 
1 files changed, 10 insertions, 3 deletions
diff --git a/kernel/softirq.c b/kernel/softirq.c index b5197dcb0da..3d6833f125d 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -195,8 +195,12 @@ void local_bh_enable_ip(unsigned long ip)  EXPORT_SYMBOL(local_bh_enable_ip);  /* - * We restart softirq processing for at most 2 ms, - * and if need_resched() is not set. + * We restart softirq processing for at most MAX_SOFTIRQ_RESTART times, + * but break the loop if need_resched() is set or after 2 ms. + * The MAX_SOFTIRQ_TIME provides a nice upper bound in most cases, but in + * certain cases, such as stop_machine(), jiffies may cease to + * increment and so we need the MAX_SOFTIRQ_RESTART limit as + * well to make sure we eventually return from this method.   *   * These limits have been established via experimentation.   * The two things to balance is latency against fairness - @@ -204,6 +208,7 @@ EXPORT_SYMBOL(local_bh_enable_ip);   * should not be able to lock up the box.   */  #define MAX_SOFTIRQ_TIME  msecs_to_jiffies(2) +#define MAX_SOFTIRQ_RESTART 10  asmlinkage void __do_softirq(void)  { @@ -212,6 +217,7 @@ asmlinkage void __do_softirq(void)  	unsigned long end = jiffies + MAX_SOFTIRQ_TIME;  	int cpu;  	unsigned long old_flags = current->flags; +	int max_restart = MAX_SOFTIRQ_RESTART;  	/*  	 * Mask out PF_MEMALLOC s current task context is borrowed for the @@ -265,7 +271,8 @@ restart:  	pending = local_softirq_pending();  	if (pending) { -		if (time_before(jiffies, end) && !need_resched()) +		if (time_before(jiffies, end) && !need_resched() && +		    --max_restart)  			goto restart;  		wakeup_softirqd();  |