diff options
Diffstat (limited to 'kernel/time')
| -rw-r--r-- | kernel/time/tick-sched.c | 25 |
1 files changed, 13 insertions, 12 deletions
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 266c242dc354..c76aefe764b0 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
| @@ -453,18 +453,22 @@ out: | |||
| 453 | * | 453 | * |
| 454 | * When the next event is more than a tick into the future, stop the idle tick | 454 | * When the next event is more than a tick into the future, stop the idle tick |
| 455 | * Called when we start the idle loop. | 455 | * Called when we start the idle loop. |
| 456 | * This also enters into RCU extended quiescent state so that this CPU doesn't | 456 | * |
| 457 | * need anymore to be part of any global grace period completion. This way | 457 | * If no use of RCU is made in the idle loop between |
| 458 | * the tick can be stopped safely as we don't need to report quiescent states. | 458 | * tick_nohz_idle_enter() and tick_nohz_idle_exit() calls, then |
| 459 | * tick_nohz_idle_enter_norcu() should be called instead and the arch | ||
| 460 | * doesn't need to call rcu_idle_enter() and rcu_idle_exit() explicitly. | ||
| 461 | * | ||
| 462 | * Otherwise the arch is responsible of calling: | ||
| 463 | * | ||
| 464 | * - rcu_idle_enter() after its last use of RCU before the CPU is put | ||
| 465 | * to sleep. | ||
| 466 | * - rcu_idle_exit() before the first use of RCU after the CPU is woken up. | ||
| 459 | */ | 467 | */ |
| 460 | void tick_nohz_idle_enter(void) | 468 | void __tick_nohz_idle_enter(void) |
| 461 | { | 469 | { |
| 462 | struct tick_sched *ts; | 470 | struct tick_sched *ts; |
| 463 | 471 | ||
| 464 | WARN_ON_ONCE(irqs_disabled()); | ||
| 465 | |||
| 466 | local_irq_disable(); | ||
| 467 | |||
| 468 | ts = &__get_cpu_var(tick_cpu_sched); | 472 | ts = &__get_cpu_var(tick_cpu_sched); |
| 469 | /* | 473 | /* |
| 470 | * set ts->inidle unconditionally. even if the system did not | 474 | * set ts->inidle unconditionally. even if the system did not |
| @@ -473,9 +477,6 @@ void tick_nohz_idle_enter(void) | |||
| 473 | */ | 477 | */ |
| 474 | ts->inidle = 1; | 478 | ts->inidle = 1; |
| 475 | tick_nohz_stop_sched_tick(ts); | 479 | tick_nohz_stop_sched_tick(ts); |
| 476 | rcu_idle_enter(); | ||
| 477 | |||
| 478 | local_irq_enable(); | ||
| 479 | } | 480 | } |
| 480 | 481 | ||
| 481 | /** | 482 | /** |
| @@ -551,7 +552,7 @@ void tick_nohz_idle_exit(void) | |||
| 551 | ktime_t now; | 552 | ktime_t now; |
| 552 | 553 | ||
| 553 | local_irq_disable(); | 554 | local_irq_disable(); |
| 554 | rcu_idle_exit(); | 555 | |
| 555 | if (ts->idle_active || (ts->inidle && ts->tick_stopped)) | 556 | if (ts->idle_active || (ts->inidle && ts->tick_stopped)) |
| 556 | now = ktime_get(); | 557 | now = ktime_get(); |
| 557 | 558 | ||
