diff options
Diffstat (limited to 'kernel/time/tick-common.c')
-rw-r--r-- | kernel/time/tick-common.c | 54 |
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 | */ |
48 | int tick_do_timer_cpu __read_mostly = TICK_DO_TIMER_BOOT; | 48 | int 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 | */ | ||
55 | static 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 | ||
179 | static 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 | |||
188 | static 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); |