diff options
| -rw-r--r-- | kernel/time/tick-common.c | 8 | ||||
| -rw-r--r-- | kernel/time/tick-internal.h | 1 | ||||
| -rw-r--r-- | kernel/time/tick-sched.c | 42 |
3 files changed, 48 insertions, 3 deletions
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index bfda3f7f0716..a96ec9ab3454 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c | |||
| @@ -31,7 +31,7 @@ DEFINE_PER_CPU(struct tick_device, tick_cpu_device); | |||
| 31 | */ | 31 | */ |
| 32 | ktime_t tick_next_period; | 32 | ktime_t tick_next_period; |
| 33 | ktime_t tick_period; | 33 | ktime_t tick_period; |
| 34 | static int tick_do_timer_cpu = -1; | 34 | int tick_do_timer_cpu __read_mostly = -1; |
| 35 | DEFINE_SPINLOCK(tick_device_lock); | 35 | DEFINE_SPINLOCK(tick_device_lock); |
| 36 | 36 | ||
| 37 | /* | 37 | /* |
| @@ -295,6 +295,12 @@ static void tick_shutdown(unsigned int *cpup) | |||
| 295 | clockevents_exchange_device(dev, NULL); | 295 | clockevents_exchange_device(dev, NULL); |
| 296 | td->evtdev = NULL; | 296 | td->evtdev = NULL; |
| 297 | } | 297 | } |
| 298 | /* Transfer the do_timer job away from this cpu */ | ||
| 299 | if (*cpup == tick_do_timer_cpu) { | ||
| 300 | int cpu = first_cpu(cpu_online_map); | ||
| 301 | |||
| 302 | tick_do_timer_cpu = (cpu != NR_CPUS) ? cpu : -1; | ||
| 303 | } | ||
| 298 | spin_unlock_irqrestore(&tick_device_lock, flags); | 304 | spin_unlock_irqrestore(&tick_device_lock, flags); |
| 299 | } | 305 | } |
| 300 | 306 | ||
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h index c9d203bde518..bb13f2724905 100644 --- a/kernel/time/tick-internal.h +++ b/kernel/time/tick-internal.h | |||
| @@ -5,6 +5,7 @@ DECLARE_PER_CPU(struct tick_device, tick_cpu_device); | |||
| 5 | extern spinlock_t tick_device_lock; | 5 | extern spinlock_t tick_device_lock; |
| 6 | extern ktime_t tick_next_period; | 6 | extern ktime_t tick_next_period; |
| 7 | extern ktime_t tick_period; | 7 | extern ktime_t tick_period; |
| 8 | extern int tick_do_timer_cpu __read_mostly; | ||
| 8 | 9 | ||
| 9 | extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast); | 10 | extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast); |
| 10 | extern void tick_handle_periodic(struct clock_event_device *dev); | 11 | extern void tick_handle_periodic(struct clock_event_device *dev); |
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 51556b95f60f..f4fc867f467d 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
| @@ -221,6 +221,18 @@ void tick_nohz_stop_sched_tick(void) | |||
| 221 | ts->tick_stopped = 1; | 221 | ts->tick_stopped = 1; |
| 222 | ts->idle_jiffies = last_jiffies; | 222 | ts->idle_jiffies = last_jiffies; |
| 223 | } | 223 | } |
| 224 | |||
| 225 | /* | ||
| 226 | * If this cpu is the one which updates jiffies, then | ||
| 227 | * give up the assignment and let it be taken by the | ||
| 228 | * cpu which runs the tick timer next, which might be | ||
| 229 | * this cpu as well. If we don't drop this here the | ||
| 230 | * jiffies might be stale and do_timer() never | ||
| 231 | * invoked. | ||
| 232 | */ | ||
| 233 | if (cpu == tick_do_timer_cpu) | ||
| 234 | tick_do_timer_cpu = -1; | ||
| 235 | |||
| 224 | /* | 236 | /* |
| 225 | * calculate the expiry time for the next timer wheel | 237 | * calculate the expiry time for the next timer wheel |
| 226 | * timer | 238 | * timer |
| @@ -338,12 +350,24 @@ static void tick_nohz_handler(struct clock_event_device *dev) | |||
| 338 | { | 350 | { |
| 339 | struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched); | 351 | struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched); |
| 340 | struct pt_regs *regs = get_irq_regs(); | 352 | struct pt_regs *regs = get_irq_regs(); |
| 353 | int cpu = smp_processor_id(); | ||
| 341 | ktime_t now = ktime_get(); | 354 | ktime_t now = ktime_get(); |
| 342 | 355 | ||
| 343 | dev->next_event.tv64 = KTIME_MAX; | 356 | dev->next_event.tv64 = KTIME_MAX; |
| 344 | 357 | ||
| 358 | /* | ||
| 359 | * Check if the do_timer duty was dropped. We don't care about | ||
| 360 | * concurrency: This happens only when the cpu in charge went | ||
| 361 | * into a long sleep. If two cpus happen to assign themself to | ||
| 362 | * this duty, then the jiffies update is still serialized by | ||
| 363 | * xtime_lock. | ||
| 364 | */ | ||
| 365 | if (unlikely(tick_do_timer_cpu == -1)) | ||
| 366 | tick_do_timer_cpu = cpu; | ||
| 367 | |||
| 345 | /* Check, if the jiffies need an update */ | 368 | /* Check, if the jiffies need an update */ |
| 346 | tick_do_update_jiffies64(now); | 369 | if (tick_do_timer_cpu == cpu) |
| 370 | tick_do_update_jiffies64(now); | ||
| 347 | 371 | ||
| 348 | /* | 372 | /* |
| 349 | * When we are idle and the tick is stopped, we have to touch | 373 | * When we are idle and the tick is stopped, we have to touch |
| @@ -431,9 +455,23 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer) | |||
| 431 | struct hrtimer_cpu_base *base = timer->base->cpu_base; | 455 | struct hrtimer_cpu_base *base = timer->base->cpu_base; |
| 432 | struct pt_regs *regs = get_irq_regs(); | 456 | struct pt_regs *regs = get_irq_regs(); |
| 433 | ktime_t now = ktime_get(); | 457 | ktime_t now = ktime_get(); |
| 458 | int cpu = smp_processor_id(); | ||
| 459 | |||
| 460 | #ifdef CONFIG_NO_HZ | ||
| 461 | /* | ||
| 462 | * Check if the do_timer duty was dropped. We don't care about | ||
| 463 | * concurrency: This happens only when the cpu in charge went | ||
| 464 | * into a long sleep. If two cpus happen to assign themself to | ||
| 465 | * this duty, then the jiffies update is still serialized by | ||
| 466 | * xtime_lock. | ||
| 467 | */ | ||
| 468 | if (unlikely(tick_do_timer_cpu == -1)) | ||
| 469 | tick_do_timer_cpu = cpu; | ||
| 470 | #endif | ||
| 434 | 471 | ||
| 435 | /* Check, if the jiffies need an update */ | 472 | /* Check, if the jiffies need an update */ |
| 436 | tick_do_update_jiffies64(now); | 473 | if (tick_do_timer_cpu == cpu) |
| 474 | tick_do_update_jiffies64(now); | ||
| 437 | 475 | ||
| 438 | /* | 476 | /* |
| 439 | * Do not call, when we are not in irq context and have | 477 | * Do not call, when we are not in irq context and have |
