aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/tick-common.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/time/tick-common.c')
-rw-r--r--kernel/time/tick-common.c54
1 files changed, 49 insertions, 5 deletions
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index 529143b4c8d2..59225b484e4e 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -46,6 +46,14 @@ ktime_t tick_period;
46 * procedure also covers cpu hotplug. 46 * procedure also covers cpu hotplug.
47 */ 47 */
48int tick_do_timer_cpu __read_mostly = TICK_DO_TIMER_BOOT; 48int tick_do_timer_cpu __read_mostly = TICK_DO_TIMER_BOOT;
49#ifdef CONFIG_NO_HZ_FULL
50/*
51 * tick_do_timer_boot_cpu indicates the boot CPU temporarily owns
52 * tick_do_timer_cpu and it should be taken over by an eligible secondary
53 * when one comes online.
54 */
55static int tick_do_timer_boot_cpu __read_mostly = -1;
56#endif
49 57
50/* 58/*
51 * Debugging: see timer_list.c 59 * Debugging: see timer_list.c
@@ -149,7 +157,7 @@ void tick_setup_periodic(struct clock_event_device *dev, int broadcast)
149 !tick_broadcast_oneshot_active()) { 157 !tick_broadcast_oneshot_active()) {
150 clockevents_switch_state(dev, CLOCK_EVT_STATE_PERIODIC); 158 clockevents_switch_state(dev, CLOCK_EVT_STATE_PERIODIC);
151 } else { 159 } else {
152 unsigned long seq; 160 unsigned int seq;
153 ktime_t next; 161 ktime_t next;
154 162
155 do { 163 do {
@@ -167,6 +175,26 @@ void tick_setup_periodic(struct clock_event_device *dev, int broadcast)
167 } 175 }
168} 176}
169 177
178#ifdef CONFIG_NO_HZ_FULL
179static void giveup_do_timer(void *info)
180{
181 int cpu = *(unsigned int *)info;
182
183 WARN_ON(tick_do_timer_cpu != smp_processor_id());
184
185 tick_do_timer_cpu = cpu;
186}
187
188static void tick_take_do_timer_from_boot(void)
189{
190 int cpu = smp_processor_id();
191 int from = tick_do_timer_boot_cpu;
192
193 if (from >= 0 && from != cpu)
194 smp_call_function_single(from, giveup_do_timer, &cpu, 1);
195}
196#endif
197
170/* 198/*
171 * Setup the tick device 199 * Setup the tick device
172 */ 200 */
@@ -186,12 +214,26 @@ static void tick_setup_device(struct tick_device *td,
186 * this cpu: 214 * this cpu:
187 */ 215 */
188 if (tick_do_timer_cpu == TICK_DO_TIMER_BOOT) { 216 if (tick_do_timer_cpu == TICK_DO_TIMER_BOOT) {
189 if (!tick_nohz_full_cpu(cpu)) 217 tick_do_timer_cpu = cpu;
190 tick_do_timer_cpu = cpu; 218
191 else
192 tick_do_timer_cpu = TICK_DO_TIMER_NONE;
193 tick_next_period = ktime_get(); 219 tick_next_period = ktime_get();
194 tick_period = NSEC_PER_SEC / HZ; 220 tick_period = NSEC_PER_SEC / HZ;
221#ifdef CONFIG_NO_HZ_FULL
222 /*
223 * The boot CPU may be nohz_full, in which case set
224 * tick_do_timer_boot_cpu so the first housekeeping
225 * secondary that comes up will take do_timer from
226 * us.
227 */
228 if (tick_nohz_full_cpu(cpu))
229 tick_do_timer_boot_cpu = cpu;
230
231 } else if (tick_do_timer_boot_cpu != -1 &&
232 !tick_nohz_full_cpu(cpu)) {
233 tick_take_do_timer_from_boot();
234 tick_do_timer_boot_cpu = -1;
235 WARN_ON(tick_do_timer_cpu != cpu);
236#endif
195 } 237 }
196 238
197 /* 239 /*
@@ -487,6 +529,7 @@ void tick_freeze(void)
487 trace_suspend_resume(TPS("timekeeping_freeze"), 529 trace_suspend_resume(TPS("timekeeping_freeze"),
488 smp_processor_id(), true); 530 smp_processor_id(), true);
489 system_state = SYSTEM_SUSPEND; 531 system_state = SYSTEM_SUSPEND;
532 sched_clock_suspend();
490 timekeeping_suspend(); 533 timekeeping_suspend();
491 } else { 534 } else {
492 tick_suspend_local(); 535 tick_suspend_local();
@@ -510,6 +553,7 @@ void tick_unfreeze(void)
510 553
511 if (tick_freeze_depth == num_online_cpus()) { 554 if (tick_freeze_depth == num_online_cpus()) {
512 timekeeping_resume(); 555 timekeeping_resume();
556 sched_clock_resume();
513 system_state = SYSTEM_RUNNING; 557 system_state = SYSTEM_RUNNING;
514 trace_suspend_resume(TPS("timekeeping_freeze"), 558 trace_suspend_resume(TPS("timekeeping_freeze"),
515 smp_processor_id(), false); 559 smp_processor_id(), false);