diff options
Diffstat (limited to 'kernel/time/tick-sched.c')
-rw-r--r-- | kernel/time/tick-sched.c | 66 |
1 files changed, 36 insertions, 30 deletions
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 342fc9ccab46..1b6c05bd0d0a 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
@@ -144,7 +144,7 @@ void tick_nohz_update_jiffies(void) | |||
144 | if (!ts->tick_stopped) | 144 | if (!ts->tick_stopped) |
145 | return; | 145 | return; |
146 | 146 | ||
147 | cpu_clear(cpu, nohz_cpu_mask); | 147 | cpumask_clear_cpu(cpu, nohz_cpu_mask); |
148 | now = ktime_get(); | 148 | now = ktime_get(); |
149 | ts->idle_waketime = now; | 149 | ts->idle_waketime = now; |
150 | 150 | ||
@@ -247,7 +247,7 @@ void tick_nohz_stop_sched_tick(int inidle) | |||
247 | if (need_resched()) | 247 | if (need_resched()) |
248 | goto end; | 248 | goto end; |
249 | 249 | ||
250 | if (unlikely(local_softirq_pending())) { | 250 | if (unlikely(local_softirq_pending() && cpu_online(cpu))) { |
251 | static int ratelimit; | 251 | static int ratelimit; |
252 | 252 | ||
253 | if (ratelimit < 10) { | 253 | if (ratelimit < 10) { |
@@ -282,8 +282,31 @@ void tick_nohz_stop_sched_tick(int inidle) | |||
282 | /* Schedule the tick, if we are at least one jiffie off */ | 282 | /* Schedule the tick, if we are at least one jiffie off */ |
283 | if ((long)delta_jiffies >= 1) { | 283 | if ((long)delta_jiffies >= 1) { |
284 | 284 | ||
285 | /* | ||
286 | * calculate the expiry time for the next timer wheel | ||
287 | * timer | ||
288 | */ | ||
289 | expires = ktime_add_ns(last_update, tick_period.tv64 * | ||
290 | delta_jiffies); | ||
291 | |||
292 | /* | ||
293 | * If this cpu is the one which updates jiffies, then | ||
294 | * give up the assignment and let it be taken by the | ||
295 | * cpu which runs the tick timer next, which might be | ||
296 | * this cpu as well. If we don't drop this here the | ||
297 | * jiffies might be stale and do_timer() never | ||
298 | * invoked. | ||
299 | */ | ||
300 | if (cpu == tick_do_timer_cpu) | ||
301 | tick_do_timer_cpu = TICK_DO_TIMER_NONE; | ||
302 | |||
285 | if (delta_jiffies > 1) | 303 | if (delta_jiffies > 1) |
286 | cpu_set(cpu, nohz_cpu_mask); | 304 | cpumask_set_cpu(cpu, nohz_cpu_mask); |
305 | |||
306 | /* Skip reprogram of event if its not changed */ | ||
307 | if (ts->tick_stopped && ktime_equal(expires, dev->next_event)) | ||
308 | goto out; | ||
309 | |||
287 | /* | 310 | /* |
288 | * nohz_stop_sched_tick can be called several times before | 311 | * nohz_stop_sched_tick can be called several times before |
289 | * the nohz_restart_sched_tick is called. This happens when | 312 | * the nohz_restart_sched_tick is called. This happens when |
@@ -296,7 +319,7 @@ void tick_nohz_stop_sched_tick(int inidle) | |||
296 | /* | 319 | /* |
297 | * sched tick not stopped! | 320 | * sched tick not stopped! |
298 | */ | 321 | */ |
299 | cpu_clear(cpu, nohz_cpu_mask); | 322 | cpumask_clear_cpu(cpu, nohz_cpu_mask); |
300 | goto out; | 323 | goto out; |
301 | } | 324 | } |
302 | 325 | ||
@@ -306,17 +329,6 @@ void tick_nohz_stop_sched_tick(int inidle) | |||
306 | rcu_enter_nohz(); | 329 | rcu_enter_nohz(); |
307 | } | 330 | } |
308 | 331 | ||
309 | /* | ||
310 | * If this cpu is the one which updates jiffies, then | ||
311 | * give up the assignment and let it be taken by the | ||
312 | * cpu which runs the tick timer next, which might be | ||
313 | * this cpu as well. If we don't drop this here the | ||
314 | * jiffies might be stale and do_timer() never | ||
315 | * invoked. | ||
316 | */ | ||
317 | if (cpu == tick_do_timer_cpu) | ||
318 | tick_do_timer_cpu = TICK_DO_TIMER_NONE; | ||
319 | |||
320 | ts->idle_sleeps++; | 332 | ts->idle_sleeps++; |
321 | 333 | ||
322 | /* | 334 | /* |
@@ -332,12 +344,7 @@ void tick_nohz_stop_sched_tick(int inidle) | |||
332 | goto out; | 344 | goto out; |
333 | } | 345 | } |
334 | 346 | ||
335 | /* | 347 | /* Mark expiries */ |
336 | * calculate the expiry time for the next timer wheel | ||
337 | * timer | ||
338 | */ | ||
339 | expires = ktime_add_ns(last_update, tick_period.tv64 * | ||
340 | delta_jiffies); | ||
341 | ts->idle_expires = expires; | 348 | ts->idle_expires = expires; |
342 | 349 | ||
343 | if (ts->nohz_mode == NOHZ_MODE_HIGHRES) { | 350 | if (ts->nohz_mode == NOHZ_MODE_HIGHRES) { |
@@ -354,7 +361,7 @@ void tick_nohz_stop_sched_tick(int inidle) | |||
354 | * softirq. | 361 | * softirq. |
355 | */ | 362 | */ |
356 | tick_do_update_jiffies64(ktime_get()); | 363 | tick_do_update_jiffies64(ktime_get()); |
357 | cpu_clear(cpu, nohz_cpu_mask); | 364 | cpumask_clear_cpu(cpu, nohz_cpu_mask); |
358 | } | 365 | } |
359 | raise_softirq_irqoff(TIMER_SOFTIRQ); | 366 | raise_softirq_irqoff(TIMER_SOFTIRQ); |
360 | out: | 367 | out: |
@@ -412,7 +419,9 @@ void tick_nohz_restart_sched_tick(void) | |||
412 | { | 419 | { |
413 | int cpu = smp_processor_id(); | 420 | int cpu = smp_processor_id(); |
414 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); | 421 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); |
422 | #ifndef CONFIG_VIRT_CPU_ACCOUNTING | ||
415 | unsigned long ticks; | 423 | unsigned long ticks; |
424 | #endif | ||
416 | ktime_t now; | 425 | ktime_t now; |
417 | 426 | ||
418 | local_irq_disable(); | 427 | local_irq_disable(); |
@@ -432,8 +441,9 @@ void tick_nohz_restart_sched_tick(void) | |||
432 | select_nohz_load_balancer(0); | 441 | select_nohz_load_balancer(0); |
433 | now = ktime_get(); | 442 | now = ktime_get(); |
434 | tick_do_update_jiffies64(now); | 443 | tick_do_update_jiffies64(now); |
435 | cpu_clear(cpu, nohz_cpu_mask); | 444 | cpumask_clear_cpu(cpu, nohz_cpu_mask); |
436 | 445 | ||
446 | #ifndef CONFIG_VIRT_CPU_ACCOUNTING | ||
437 | /* | 447 | /* |
438 | * We stopped the tick in idle. Update process times would miss the | 448 | * We stopped the tick in idle. Update process times would miss the |
439 | * time we slept as update_process_times does only a 1 tick | 449 | * time we slept as update_process_times does only a 1 tick |
@@ -443,12 +453,9 @@ void tick_nohz_restart_sched_tick(void) | |||
443 | /* | 453 | /* |
444 | * We might be one off. Do not randomly account a huge number of ticks! | 454 | * We might be one off. Do not randomly account a huge number of ticks! |
445 | */ | 455 | */ |
446 | if (ticks && ticks < LONG_MAX) { | 456 | if (ticks && ticks < LONG_MAX) |
447 | add_preempt_count(HARDIRQ_OFFSET); | 457 | account_idle_ticks(ticks); |
448 | account_system_time(current, HARDIRQ_OFFSET, | 458 | #endif |
449 | jiffies_to_cputime(ticks)); | ||
450 | sub_preempt_count(HARDIRQ_OFFSET); | ||
451 | } | ||
452 | 459 | ||
453 | touch_softlockup_watchdog(); | 460 | touch_softlockup_watchdog(); |
454 | /* | 461 | /* |
@@ -681,7 +688,6 @@ void tick_setup_sched_timer(void) | |||
681 | */ | 688 | */ |
682 | hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); | 689 | hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); |
683 | ts->sched_timer.function = tick_sched_timer; | 690 | ts->sched_timer.function = tick_sched_timer; |
684 | ts->sched_timer.cb_mode = HRTIMER_CB_IRQSAFE_PERCPU; | ||
685 | 691 | ||
686 | /* Get the next period (per cpu) */ | 692 | /* Get the next period (per cpu) */ |
687 | hrtimer_set_expires(&ts->sched_timer, tick_init_jiffy_update()); | 693 | hrtimer_set_expires(&ts->sched_timer, tick_init_jiffy_update()); |