diff options
Diffstat (limited to 'kernel/softirq.c')
-rw-r--r-- | kernel/softirq.c | 38 |
1 files changed, 18 insertions, 20 deletions
diff --git a/kernel/softirq.c b/kernel/softirq.c index f5cc25f147a6..14d7758074aa 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c | |||
@@ -195,21 +195,21 @@ void local_bh_enable_ip(unsigned long ip) | |||
195 | EXPORT_SYMBOL(local_bh_enable_ip); | 195 | EXPORT_SYMBOL(local_bh_enable_ip); |
196 | 196 | ||
197 | /* | 197 | /* |
198 | * We restart softirq processing MAX_SOFTIRQ_RESTART times, | 198 | * We restart softirq processing for at most 2 ms, |
199 | * and we fall back to softirqd after that. | 199 | * and if need_resched() is not set. |
200 | * | 200 | * |
201 | * This number has been established via experimentation. | 201 | * These limits have been established via experimentation. |
202 | * The two things to balance is latency against fairness - | 202 | * The two things to balance is latency against fairness - |
203 | * we want to handle softirqs as soon as possible, but they | 203 | * we want to handle softirqs as soon as possible, but they |
204 | * should not be able to lock up the box. | 204 | * should not be able to lock up the box. |
205 | */ | 205 | */ |
206 | #define MAX_SOFTIRQ_RESTART 10 | 206 | #define MAX_SOFTIRQ_TIME msecs_to_jiffies(2) |
207 | 207 | ||
208 | asmlinkage void __do_softirq(void) | 208 | asmlinkage void __do_softirq(void) |
209 | { | 209 | { |
210 | struct softirq_action *h; | 210 | struct softirq_action *h; |
211 | __u32 pending; | 211 | __u32 pending; |
212 | int max_restart = MAX_SOFTIRQ_RESTART; | 212 | unsigned long end = jiffies + MAX_SOFTIRQ_TIME; |
213 | int cpu; | 213 | int cpu; |
214 | unsigned long old_flags = current->flags; | 214 | unsigned long old_flags = current->flags; |
215 | 215 | ||
@@ -264,11 +264,12 @@ restart: | |||
264 | local_irq_disable(); | 264 | local_irq_disable(); |
265 | 265 | ||
266 | pending = local_softirq_pending(); | 266 | pending = local_softirq_pending(); |
267 | if (pending && --max_restart) | 267 | if (pending) { |
268 | goto restart; | 268 | if (time_before(jiffies, end) && !need_resched()) |
269 | goto restart; | ||
269 | 270 | ||
270 | if (pending) | ||
271 | wakeup_softirqd(); | 271 | wakeup_softirqd(); |
272 | } | ||
272 | 273 | ||
273 | lockdep_softirq_exit(); | 274 | lockdep_softirq_exit(); |
274 | 275 | ||
@@ -322,18 +323,10 @@ void irq_enter(void) | |||
322 | 323 | ||
323 | static inline void invoke_softirq(void) | 324 | static inline void invoke_softirq(void) |
324 | { | 325 | { |
325 | if (!force_irqthreads) { | 326 | if (!force_irqthreads) |
326 | #ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED | ||
327 | __do_softirq(); | 327 | __do_softirq(); |
328 | #else | 328 | else |
329 | do_softirq(); | ||
330 | #endif | ||
331 | } else { | ||
332 | __local_bh_disable((unsigned long)__builtin_return_address(0), | ||
333 | SOFTIRQ_OFFSET); | ||
334 | wakeup_softirqd(); | 329 | wakeup_softirqd(); |
335 | __local_bh_enable(SOFTIRQ_OFFSET); | ||
336 | } | ||
337 | } | 330 | } |
338 | 331 | ||
339 | /* | 332 | /* |
@@ -341,9 +334,15 @@ static inline void invoke_softirq(void) | |||
341 | */ | 334 | */ |
342 | void irq_exit(void) | 335 | void irq_exit(void) |
343 | { | 336 | { |
337 | #ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED | ||
338 | local_irq_disable(); | ||
339 | #else | ||
340 | WARN_ON_ONCE(!irqs_disabled()); | ||
341 | #endif | ||
342 | |||
344 | account_irq_exit_time(current); | 343 | account_irq_exit_time(current); |
345 | trace_hardirq_exit(); | 344 | trace_hardirq_exit(); |
346 | sub_preempt_count(IRQ_EXIT_OFFSET); | 345 | sub_preempt_count(HARDIRQ_OFFSET); |
347 | if (!in_interrupt() && local_softirq_pending()) | 346 | if (!in_interrupt() && local_softirq_pending()) |
348 | invoke_softirq(); | 347 | invoke_softirq(); |
349 | 348 | ||
@@ -353,7 +352,6 @@ void irq_exit(void) | |||
353 | tick_nohz_irq_exit(); | 352 | tick_nohz_irq_exit(); |
354 | #endif | 353 | #endif |
355 | rcu_irq_exit(); | 354 | rcu_irq_exit(); |
356 | sched_preempt_enable_no_resched(); | ||
357 | } | 355 | } |
358 | 356 | ||
359 | /* | 357 | /* |