diff options
-rw-r--r-- | include/linux/tick.h | 2 | ||||
-rw-r--r-- | kernel/sched/idle.c | 9 | ||||
-rw-r--r-- | kernel/time/tick-sched.c | 26 |
3 files changed, 26 insertions, 11 deletions
diff --git a/include/linux/tick.h b/include/linux/tick.h index 1d253df9ea3c..fccebfba167e 100644 --- a/include/linux/tick.h +++ b/include/linux/tick.h | |||
@@ -116,6 +116,7 @@ extern bool tick_nohz_enabled; | |||
116 | extern bool tick_nohz_tick_stopped(void); | 116 | extern bool tick_nohz_tick_stopped(void); |
117 | extern bool tick_nohz_tick_stopped_cpu(int cpu); | 117 | extern bool tick_nohz_tick_stopped_cpu(int cpu); |
118 | extern void tick_nohz_idle_stop_tick(void); | 118 | extern void tick_nohz_idle_stop_tick(void); |
119 | extern void tick_nohz_idle_restart_tick(void); | ||
119 | extern void tick_nohz_idle_enter(void); | 120 | extern void tick_nohz_idle_enter(void); |
120 | extern void tick_nohz_idle_exit(void); | 121 | extern void tick_nohz_idle_exit(void); |
121 | extern void tick_nohz_irq_exit(void); | 122 | extern void tick_nohz_irq_exit(void); |
@@ -137,6 +138,7 @@ static inline void tick_nohz_idle_stop_tick_protected(void) | |||
137 | static inline int tick_nohz_tick_stopped(void) { return 0; } | 138 | static inline int tick_nohz_tick_stopped(void) { return 0; } |
138 | static inline int tick_nohz_tick_stopped_cpu(int cpu) { return 0; } | 139 | static inline int tick_nohz_tick_stopped_cpu(int cpu) { return 0; } |
139 | static inline void tick_nohz_idle_stop_tick(void) { } | 140 | static inline void tick_nohz_idle_stop_tick(void) { } |
141 | static inline void tick_nohz_idle_restart_tick(void) { } | ||
140 | static inline void tick_nohz_idle_enter(void) { } | 142 | static inline void tick_nohz_idle_enter(void) { } |
141 | static inline void tick_nohz_idle_exit(void) { } | 143 | static inline void tick_nohz_idle_exit(void) { } |
142 | 144 | ||
diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c index c0bc111878e6..3777e83c0b5a 100644 --- a/kernel/sched/idle.c +++ b/kernel/sched/idle.c | |||
@@ -216,13 +216,13 @@ static void do_idle(void) | |||
216 | 216 | ||
217 | __current_set_polling(); | 217 | __current_set_polling(); |
218 | tick_nohz_idle_enter(); | 218 | tick_nohz_idle_enter(); |
219 | tick_nohz_idle_stop_tick_protected(); | ||
220 | 219 | ||
221 | while (!need_resched()) { | 220 | while (!need_resched()) { |
222 | check_pgt_cache(); | 221 | check_pgt_cache(); |
223 | rmb(); | 222 | rmb(); |
224 | 223 | ||
225 | if (cpu_is_offline(cpu)) { | 224 | if (cpu_is_offline(cpu)) { |
225 | tick_nohz_idle_stop_tick_protected(); | ||
226 | cpuhp_report_idle_dead(); | 226 | cpuhp_report_idle_dead(); |
227 | arch_cpu_idle_dead(); | 227 | arch_cpu_idle_dead(); |
228 | } | 228 | } |
@@ -236,10 +236,13 @@ static void do_idle(void) | |||
236 | * broadcast device expired for us, we don't want to go deep | 236 | * broadcast device expired for us, we don't want to go deep |
237 | * idle as we know that the IPI is going to arrive right away. | 237 | * idle as we know that the IPI is going to arrive right away. |
238 | */ | 238 | */ |
239 | if (cpu_idle_force_poll || tick_check_broadcast_expired()) | 239 | if (cpu_idle_force_poll || tick_check_broadcast_expired()) { |
240 | tick_nohz_idle_restart_tick(); | ||
240 | cpu_idle_poll(); | 241 | cpu_idle_poll(); |
241 | else | 242 | } else { |
243 | tick_nohz_idle_stop_tick(); | ||
242 | cpuidle_idle_call(); | 244 | cpuidle_idle_call(); |
245 | } | ||
243 | arch_cpu_idle_exit(); | 246 | arch_cpu_idle_exit(); |
244 | } | 247 | } |
245 | 248 | ||
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 678349aec483..f5d37788ea85 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
@@ -960,12 +960,10 @@ void tick_nohz_irq_exit(void) | |||
960 | { | 960 | { |
961 | struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched); | 961 | struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched); |
962 | 962 | ||
963 | if (ts->inidle) { | 963 | if (ts->inidle) |
964 | tick_nohz_start_idle(ts); | 964 | tick_nohz_start_idle(ts); |
965 | __tick_nohz_idle_stop_tick(ts); | 965 | else |
966 | } else { | ||
967 | tick_nohz_full_update_tick(ts); | 966 | tick_nohz_full_update_tick(ts); |
968 | } | ||
969 | } | 967 | } |
970 | 968 | ||
971 | /** | 969 | /** |
@@ -1026,6 +1024,20 @@ static void tick_nohz_account_idle_ticks(struct tick_sched *ts) | |||
1026 | #endif | 1024 | #endif |
1027 | } | 1025 | } |
1028 | 1026 | ||
1027 | static void __tick_nohz_idle_restart_tick(struct tick_sched *ts, ktime_t now) | ||
1028 | { | ||
1029 | tick_nohz_restart_sched_tick(ts, now); | ||
1030 | tick_nohz_account_idle_ticks(ts); | ||
1031 | } | ||
1032 | |||
1033 | void tick_nohz_idle_restart_tick(void) | ||
1034 | { | ||
1035 | struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched); | ||
1036 | |||
1037 | if (ts->tick_stopped) | ||
1038 | __tick_nohz_idle_restart_tick(ts, ktime_get()); | ||
1039 | } | ||
1040 | |||
1029 | /** | 1041 | /** |
1030 | * tick_nohz_idle_exit - restart the idle tick from the idle task | 1042 | * tick_nohz_idle_exit - restart the idle tick from the idle task |
1031 | * | 1043 | * |
@@ -1050,10 +1062,8 @@ void tick_nohz_idle_exit(void) | |||
1050 | if (ts->idle_active) | 1062 | if (ts->idle_active) |
1051 | tick_nohz_stop_idle(ts, now); | 1063 | tick_nohz_stop_idle(ts, now); |
1052 | 1064 | ||
1053 | if (ts->tick_stopped) { | 1065 | if (ts->tick_stopped) |
1054 | tick_nohz_restart_sched_tick(ts, now); | 1066 | __tick_nohz_idle_restart_tick(ts, now); |
1055 | tick_nohz_account_idle_ticks(ts); | ||
1056 | } | ||
1057 | 1067 | ||
1058 | local_irq_enable(); | 1068 | local_irq_enable(); |
1059 | } | 1069 | } |