diff options
Diffstat (limited to 'kernel/time/tick-sched.c')
-rw-r--r-- | kernel/time/tick-sched.c | 61 |
1 files changed, 28 insertions, 33 deletions
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index ea20f7d1ac2c..9f8af69c67ec 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
@@ -86,6 +86,7 @@ static void tick_do_update_jiffies64(ktime_t now) | |||
86 | tick_next_period = ktime_add(last_jiffies_update, tick_period); | 86 | tick_next_period = ktime_add(last_jiffies_update, tick_period); |
87 | } | 87 | } |
88 | write_sequnlock(&jiffies_lock); | 88 | write_sequnlock(&jiffies_lock); |
89 | update_wall_time(); | ||
89 | } | 90 | } |
90 | 91 | ||
91 | /* | 92 | /* |
@@ -177,7 +178,7 @@ static bool can_stop_full_tick(void) | |||
177 | * TODO: kick full dynticks CPUs when | 178 | * TODO: kick full dynticks CPUs when |
178 | * sched_clock_stable is set. | 179 | * sched_clock_stable is set. |
179 | */ | 180 | */ |
180 | if (!sched_clock_stable) { | 181 | if (!sched_clock_stable()) { |
181 | trace_tick_stop(0, "unstable sched clock\n"); | 182 | trace_tick_stop(0, "unstable sched clock\n"); |
182 | /* | 183 | /* |
183 | * Don't allow the user to think they can get | 184 | * Don't allow the user to think they can get |
@@ -391,11 +392,9 @@ __setup("nohz=", setup_tick_nohz); | |||
391 | */ | 392 | */ |
392 | static void tick_nohz_update_jiffies(ktime_t now) | 393 | static void tick_nohz_update_jiffies(ktime_t now) |
393 | { | 394 | { |
394 | int cpu = smp_processor_id(); | ||
395 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); | ||
396 | unsigned long flags; | 395 | unsigned long flags; |
397 | 396 | ||
398 | ts->idle_waketime = now; | 397 | __this_cpu_write(tick_cpu_sched.idle_waketime, now); |
399 | 398 | ||
400 | local_irq_save(flags); | 399 | local_irq_save(flags); |
401 | tick_do_update_jiffies64(now); | 400 | tick_do_update_jiffies64(now); |
@@ -426,17 +425,15 @@ update_ts_time_stats(int cpu, struct tick_sched *ts, ktime_t now, u64 *last_upda | |||
426 | 425 | ||
427 | } | 426 | } |
428 | 427 | ||
429 | static void tick_nohz_stop_idle(int cpu, ktime_t now) | 428 | static void tick_nohz_stop_idle(struct tick_sched *ts, ktime_t now) |
430 | { | 429 | { |
431 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); | 430 | update_ts_time_stats(smp_processor_id(), ts, now, NULL); |
432 | |||
433 | update_ts_time_stats(cpu, ts, now, NULL); | ||
434 | ts->idle_active = 0; | 431 | ts->idle_active = 0; |
435 | 432 | ||
436 | sched_clock_idle_wakeup_event(0); | 433 | sched_clock_idle_wakeup_event(0); |
437 | } | 434 | } |
438 | 435 | ||
439 | static ktime_t tick_nohz_start_idle(int cpu, struct tick_sched *ts) | 436 | static ktime_t tick_nohz_start_idle(struct tick_sched *ts) |
440 | { | 437 | { |
441 | ktime_t now = ktime_get(); | 438 | ktime_t now = ktime_get(); |
442 | 439 | ||
@@ -536,12 +533,13 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts, | |||
536 | struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev; | 533 | struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev; |
537 | u64 time_delta; | 534 | u64 time_delta; |
538 | 535 | ||
536 | time_delta = timekeeping_max_deferment(); | ||
537 | |||
539 | /* Read jiffies and the time when jiffies were updated last */ | 538 | /* Read jiffies and the time when jiffies were updated last */ |
540 | do { | 539 | do { |
541 | seq = read_seqbegin(&jiffies_lock); | 540 | seq = read_seqbegin(&jiffies_lock); |
542 | last_update = last_jiffies_update; | 541 | last_update = last_jiffies_update; |
543 | last_jiffies = jiffies; | 542 | last_jiffies = jiffies; |
544 | time_delta = timekeeping_max_deferment(); | ||
545 | } while (read_seqretry(&jiffies_lock, seq)); | 543 | } while (read_seqretry(&jiffies_lock, seq)); |
546 | 544 | ||
547 | if (rcu_needs_cpu(cpu, &rcu_delta_jiffies) || | 545 | if (rcu_needs_cpu(cpu, &rcu_delta_jiffies) || |
@@ -681,18 +679,18 @@ out: | |||
681 | static void tick_nohz_full_stop_tick(struct tick_sched *ts) | 679 | static void tick_nohz_full_stop_tick(struct tick_sched *ts) |
682 | { | 680 | { |
683 | #ifdef CONFIG_NO_HZ_FULL | 681 | #ifdef CONFIG_NO_HZ_FULL |
684 | int cpu = smp_processor_id(); | 682 | int cpu = smp_processor_id(); |
685 | 683 | ||
686 | if (!tick_nohz_full_cpu(cpu) || is_idle_task(current)) | 684 | if (!tick_nohz_full_cpu(cpu) || is_idle_task(current)) |
687 | return; | 685 | return; |
688 | 686 | ||
689 | if (!ts->tick_stopped && ts->nohz_mode == NOHZ_MODE_INACTIVE) | 687 | if (!ts->tick_stopped && ts->nohz_mode == NOHZ_MODE_INACTIVE) |
690 | return; | 688 | return; |
691 | 689 | ||
692 | if (!can_stop_full_tick()) | 690 | if (!can_stop_full_tick()) |
693 | return; | 691 | return; |
694 | 692 | ||
695 | tick_nohz_stop_sched_tick(ts, ktime_get(), cpu); | 693 | tick_nohz_stop_sched_tick(ts, ktime_get(), cpu); |
696 | #endif | 694 | #endif |
697 | } | 695 | } |
698 | 696 | ||
@@ -754,7 +752,7 @@ static void __tick_nohz_idle_enter(struct tick_sched *ts) | |||
754 | ktime_t now, expires; | 752 | ktime_t now, expires; |
755 | int cpu = smp_processor_id(); | 753 | int cpu = smp_processor_id(); |
756 | 754 | ||
757 | now = tick_nohz_start_idle(cpu, ts); | 755 | now = tick_nohz_start_idle(ts); |
758 | 756 | ||
759 | if (can_stop_idle_tick(cpu, ts)) { | 757 | if (can_stop_idle_tick(cpu, ts)) { |
760 | int was_stopped = ts->tick_stopped; | 758 | int was_stopped = ts->tick_stopped; |
@@ -911,8 +909,7 @@ static void tick_nohz_account_idle_ticks(struct tick_sched *ts) | |||
911 | */ | 909 | */ |
912 | void tick_nohz_idle_exit(void) | 910 | void tick_nohz_idle_exit(void) |
913 | { | 911 | { |
914 | int cpu = smp_processor_id(); | 912 | struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched); |
915 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); | ||
916 | ktime_t now; | 913 | ktime_t now; |
917 | 914 | ||
918 | local_irq_disable(); | 915 | local_irq_disable(); |
@@ -925,7 +922,7 @@ void tick_nohz_idle_exit(void) | |||
925 | now = ktime_get(); | 922 | now = ktime_get(); |
926 | 923 | ||
927 | if (ts->idle_active) | 924 | if (ts->idle_active) |
928 | tick_nohz_stop_idle(cpu, now); | 925 | tick_nohz_stop_idle(ts, now); |
929 | 926 | ||
930 | if (ts->tick_stopped) { | 927 | if (ts->tick_stopped) { |
931 | tick_nohz_restart_sched_tick(ts, now); | 928 | tick_nohz_restart_sched_tick(ts, now); |
@@ -1009,12 +1006,10 @@ static void tick_nohz_switch_to_nohz(void) | |||
1009 | * timer and do not touch the other magic bits which need to be done | 1006 | * timer and do not touch the other magic bits which need to be done |
1010 | * when idle is left. | 1007 | * when idle is left. |
1011 | */ | 1008 | */ |
1012 | static void tick_nohz_kick_tick(int cpu, ktime_t now) | 1009 | static void tick_nohz_kick_tick(struct tick_sched *ts, ktime_t now) |
1013 | { | 1010 | { |
1014 | #if 0 | 1011 | #if 0 |
1015 | /* Switch back to 2.6.27 behaviour */ | 1012 | /* Switch back to 2.6.27 behaviour */ |
1016 | |||
1017 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); | ||
1018 | ktime_t delta; | 1013 | ktime_t delta; |
1019 | 1014 | ||
1020 | /* | 1015 | /* |
@@ -1029,36 +1024,36 @@ static void tick_nohz_kick_tick(int cpu, ktime_t now) | |||
1029 | #endif | 1024 | #endif |
1030 | } | 1025 | } |
1031 | 1026 | ||
1032 | static inline void tick_check_nohz(int cpu) | 1027 | static inline void tick_nohz_irq_enter(void) |
1033 | { | 1028 | { |
1034 | struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); | 1029 | struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched); |
1035 | ktime_t now; | 1030 | ktime_t now; |
1036 | 1031 | ||
1037 | if (!ts->idle_active && !ts->tick_stopped) | 1032 | if (!ts->idle_active && !ts->tick_stopped) |
1038 | return; | 1033 | return; |
1039 | now = ktime_get(); | 1034 | now = ktime_get(); |
1040 | if (ts->idle_active) | 1035 | if (ts->idle_active) |
1041 | tick_nohz_stop_idle(cpu, now); | 1036 | tick_nohz_stop_idle(ts, now); |
1042 | if (ts->tick_stopped) { | 1037 | if (ts->tick_stopped) { |
1043 | tick_nohz_update_jiffies(now); | 1038 | tick_nohz_update_jiffies(now); |
1044 | tick_nohz_kick_tick(cpu, now); | 1039 | tick_nohz_kick_tick(ts, now); |
1045 | } | 1040 | } |
1046 | } | 1041 | } |
1047 | 1042 | ||
1048 | #else | 1043 | #else |
1049 | 1044 | ||
1050 | static inline void tick_nohz_switch_to_nohz(void) { } | 1045 | static inline void tick_nohz_switch_to_nohz(void) { } |
1051 | static inline void tick_check_nohz(int cpu) { } | 1046 | static inline void tick_nohz_irq_enter(void) { } |
1052 | 1047 | ||
1053 | #endif /* CONFIG_NO_HZ_COMMON */ | 1048 | #endif /* CONFIG_NO_HZ_COMMON */ |
1054 | 1049 | ||
1055 | /* | 1050 | /* |
1056 | * Called from irq_enter to notify about the possible interruption of idle() | 1051 | * Called from irq_enter to notify about the possible interruption of idle() |
1057 | */ | 1052 | */ |
1058 | void tick_check_idle(int cpu) | 1053 | void tick_irq_enter(void) |
1059 | { | 1054 | { |
1060 | tick_check_oneshot_broadcast(cpu); | 1055 | tick_check_oneshot_broadcast_this_cpu(); |
1061 | tick_check_nohz(cpu); | 1056 | tick_nohz_irq_enter(); |
1062 | } | 1057 | } |
1063 | 1058 | ||
1064 | /* | 1059 | /* |