|
@@ -295,22 +295,12 @@ out:
|
|
|
/* Parse the boot-time nohz CPU list from the kernel parameters. */
|
|
|
static int __init tick_nohz_full_setup(char *str)
|
|
|
{
|
|
|
- int cpu;
|
|
|
-
|
|
|
alloc_bootmem_cpumask_var(&tick_nohz_full_mask);
|
|
|
- alloc_bootmem_cpumask_var(&housekeeping_mask);
|
|
|
if (cpulist_parse(str, tick_nohz_full_mask) < 0) {
|
|
|
pr_warning("NOHZ: Incorrect nohz_full cpumask\n");
|
|
|
+ free_bootmem_cpumask_var(tick_nohz_full_mask);
|
|
|
return 1;
|
|
|
}
|
|
|
-
|
|
|
- cpu = smp_processor_id();
|
|
|
- if (cpumask_test_cpu(cpu, tick_nohz_full_mask)) {
|
|
|
- pr_warning("NO_HZ: Clearing %d from nohz_full range for timekeeping\n", cpu);
|
|
|
- cpumask_clear_cpu(cpu, tick_nohz_full_mask);
|
|
|
- }
|
|
|
- cpumask_andnot(housekeeping_mask,
|
|
|
- cpu_possible_mask, tick_nohz_full_mask);
|
|
|
tick_nohz_full_running = true;
|
|
|
|
|
|
return 1;
|
|
@@ -349,18 +339,11 @@ static int tick_nohz_init_all(void)
|
|
|
|
|
|
#ifdef CONFIG_NO_HZ_FULL_ALL
|
|
|
if (!alloc_cpumask_var(&tick_nohz_full_mask, GFP_KERNEL)) {
|
|
|
- pr_err("NO_HZ: Can't allocate full dynticks cpumask\n");
|
|
|
- return err;
|
|
|
- }
|
|
|
- if (!alloc_cpumask_var(&housekeeping_mask, GFP_KERNEL)) {
|
|
|
- pr_err("NO_HZ: Can't allocate not-full dynticks cpumask\n");
|
|
|
+ WARN(1, "NO_HZ: Can't allocate full dynticks cpumask\n");
|
|
|
return err;
|
|
|
}
|
|
|
err = 0;
|
|
|
cpumask_setall(tick_nohz_full_mask);
|
|
|
- cpumask_clear_cpu(smp_processor_id(), tick_nohz_full_mask);
|
|
|
- cpumask_clear(housekeeping_mask);
|
|
|
- cpumask_set_cpu(smp_processor_id(), housekeeping_mask);
|
|
|
tick_nohz_full_running = true;
|
|
|
#endif
|
|
|
return err;
|
|
@@ -375,6 +358,37 @@ void __init tick_nohz_init(void)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ if (!alloc_cpumask_var(&housekeeping_mask, GFP_KERNEL)) {
|
|
|
+ WARN(1, "NO_HZ: Can't allocate not-full dynticks cpumask\n");
|
|
|
+ cpumask_clear(tick_nohz_full_mask);
|
|
|
+ tick_nohz_full_running = false;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Full dynticks uses irq work to drive the tick rescheduling on safe
|
|
|
+ * locking contexts. But then we need irq work to raise its own
|
|
|
+ * interrupts to avoid circular dependency on the tick
|
|
|
+ */
|
|
|
+ if (!arch_irq_work_has_interrupt()) {
|
|
|
+ pr_warning("NO_HZ: Can't run full dynticks because arch doesn't "
|
|
|
+ "support irq work self-IPIs\n");
|
|
|
+ cpumask_clear(tick_nohz_full_mask);
|
|
|
+ cpumask_copy(housekeeping_mask, cpu_possible_mask);
|
|
|
+ tick_nohz_full_running = false;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ cpu = smp_processor_id();
|
|
|
+
|
|
|
+ if (cpumask_test_cpu(cpu, tick_nohz_full_mask)) {
|
|
|
+ pr_warning("NO_HZ: Clearing %d from nohz_full range for timekeeping\n", cpu);
|
|
|
+ cpumask_clear_cpu(cpu, tick_nohz_full_mask);
|
|
|
+ }
|
|
|
+
|
|
|
+ cpumask_andnot(housekeeping_mask,
|
|
|
+ cpu_possible_mask, tick_nohz_full_mask);
|
|
|
+
|
|
|
for_each_cpu(cpu, tick_nohz_full_mask)
|
|
|
context_tracking_cpu_set(cpu);
|
|
|
|