summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/tick.h2
-rw-r--r--kernel/sched/idle.c9
-rw-r--r--kernel/time/tick-sched.c26
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;
116extern bool tick_nohz_tick_stopped(void); 116extern bool tick_nohz_tick_stopped(void);
117extern bool tick_nohz_tick_stopped_cpu(int cpu); 117extern bool tick_nohz_tick_stopped_cpu(int cpu);
118extern void tick_nohz_idle_stop_tick(void); 118extern void tick_nohz_idle_stop_tick(void);
119extern void tick_nohz_idle_restart_tick(void);
119extern void tick_nohz_idle_enter(void); 120extern void tick_nohz_idle_enter(void);
120extern void tick_nohz_idle_exit(void); 121extern void tick_nohz_idle_exit(void);
121extern void tick_nohz_irq_exit(void); 122extern void tick_nohz_irq_exit(void);
@@ -137,6 +138,7 @@ static inline void tick_nohz_idle_stop_tick_protected(void)
137static inline int tick_nohz_tick_stopped(void) { return 0; } 138static inline int tick_nohz_tick_stopped(void) { return 0; }
138static inline int tick_nohz_tick_stopped_cpu(int cpu) { return 0; } 139static inline int tick_nohz_tick_stopped_cpu(int cpu) { return 0; }
139static inline void tick_nohz_idle_stop_tick(void) { } 140static inline void tick_nohz_idle_stop_tick(void) { }
141static inline void tick_nohz_idle_restart_tick(void) { }
140static inline void tick_nohz_idle_enter(void) { } 142static inline void tick_nohz_idle_enter(void) { }
141static inline void tick_nohz_idle_exit(void) { } 143static 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
1027static 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
1033void 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}