diff options
| author | Ingo Molnar <mingo@kernel.org> | 2013-04-21 05:04:42 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2013-04-21 05:04:42 -0400 |
| commit | 2727872dfe5d273f313f8a0c0dd0fcc58e96cde7 (patch) | |
| tree | 069ceb12d981f33d997afd214c2082a6685a2fd0 /kernel/time | |
| parent | 65d798f0f9339ae2c4ebe9480e3260b33382a584 (diff) | |
| parent | f98823ac758ba1aa77c6e3f8ad4ef3ad84ee0a7c (diff) | |
Merge branch 'timers/nohz-reviewed' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic/linux-dynticks into timers/nohz
Pull full dynticks timekeeping and RCU improvements from Frederic Weisbecker.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/time')
| -rw-r--r-- | kernel/time/Kconfig | 10 | ||||
| -rw-r--r-- | kernel/time/tick-sched.c | 77 |
2 files changed, 51 insertions, 36 deletions
diff --git a/kernel/time/Kconfig b/kernel/time/Kconfig index 358d601a4fec..99c3f13dd478 100644 --- a/kernel/time/Kconfig +++ b/kernel/time/Kconfig | |||
| @@ -128,6 +128,16 @@ config NO_HZ_FULL | |||
| 128 | 128 | ||
| 129 | endchoice | 129 | endchoice |
| 130 | 130 | ||
| 131 | config NO_HZ_FULL_ALL | ||
| 132 | bool "Full dynticks system on all CPUs by default" | ||
| 133 | depends on NO_HZ_FULL | ||
| 134 | help | ||
| 135 | If the user doesn't pass the nohz_full boot option to | ||
| 136 | define the range of full dynticks CPUs, consider that all | ||
| 137 | CPUs in the system are full dynticks by default. | ||
| 138 | Note the boot CPU will still be kept outside the range to | ||
| 139 | handle the timekeeping duty. | ||
| 140 | |||
| 131 | config NO_HZ | 141 | config NO_HZ |
| 132 | bool "Old Idle dynticks config" | 142 | bool "Old Idle dynticks config" |
| 133 | depends on !ARCH_USES_GETTIMEOFFSET && GENERIC_CLOCKEVENTS | 143 | depends on !ARCH_USES_GETTIMEOFFSET && GENERIC_CLOCKEVENTS |
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 369b5769fc97..a76e09044f9f 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
| @@ -158,11 +158,21 @@ int tick_nohz_full_cpu(int cpu) | |||
| 158 | /* Parse the boot-time nohz CPU list from the kernel parameters. */ | 158 | /* Parse the boot-time nohz CPU list from the kernel parameters. */ |
| 159 | static int __init tick_nohz_full_setup(char *str) | 159 | static int __init tick_nohz_full_setup(char *str) |
| 160 | { | 160 | { |
| 161 | int cpu; | ||
| 162 | |||
| 161 | alloc_bootmem_cpumask_var(&nohz_full_mask); | 163 | alloc_bootmem_cpumask_var(&nohz_full_mask); |
| 162 | if (cpulist_parse(str, nohz_full_mask) < 0) | 164 | if (cpulist_parse(str, nohz_full_mask) < 0) { |
| 163 | pr_warning("NOHZ: Incorrect nohz_full cpumask\n"); | 165 | pr_warning("NOHZ: Incorrect nohz_full cpumask\n"); |
| 164 | else | 166 | return 1; |
| 165 | have_nohz_full_mask = true; | 167 | } |
| 168 | |||
| 169 | cpu = smp_processor_id(); | ||
| 170 | if (cpumask_test_cpu(cpu, nohz_full_mask)) { | ||
| 171 | pr_warning("NO_HZ: Clearing %d from nohz_full range for timekeeping\n", cpu); | ||
| 172 | cpumask_clear_cpu(cpu, nohz_full_mask); | ||
| 173 | } | ||
| 174 | have_nohz_full_mask = true; | ||
| 175 | |||
| 166 | return 1; | 176 | return 1; |
| 167 | } | 177 | } |
| 168 | __setup("nohz_full=", tick_nohz_full_setup); | 178 | __setup("nohz_full=", tick_nohz_full_setup); |
| @@ -193,51 +203,46 @@ static int __cpuinit tick_nohz_cpu_down_callback(struct notifier_block *nfb, | |||
| 193 | */ | 203 | */ |
| 194 | static char __initdata nohz_full_buf[NR_CPUS + 1]; | 204 | static char __initdata nohz_full_buf[NR_CPUS + 1]; |
| 195 | 205 | ||
| 196 | static int __init init_tick_nohz_full(void) | 206 | static int tick_nohz_init_all(void) |
| 197 | { | 207 | { |
| 198 | cpumask_var_t online_nohz; | 208 | int err = -1; |
| 199 | int cpu; | ||
| 200 | 209 | ||
| 201 | if (!have_nohz_full_mask) | 210 | #ifdef CONFIG_NO_HZ_FULL_ALL |
| 202 | return 0; | 211 | if (!alloc_cpumask_var(&nohz_full_mask, GFP_KERNEL)) { |
| 212 | pr_err("NO_HZ: Can't allocate full dynticks cpumask\n"); | ||
| 213 | return err; | ||
| 214 | } | ||
| 215 | err = 0; | ||
| 216 | cpumask_setall(nohz_full_mask); | ||
| 217 | cpumask_clear_cpu(smp_processor_id(), nohz_full_mask); | ||
| 218 | have_nohz_full_mask = true; | ||
| 219 | #endif | ||
| 220 | return err; | ||
| 221 | } | ||
| 203 | 222 | ||
| 204 | cpu_notifier(tick_nohz_cpu_down_callback, 0); | 223 | void __init tick_nohz_init(void) |
| 224 | { | ||
| 225 | int cpu; | ||
| 205 | 226 | ||
| 206 | if (!zalloc_cpumask_var(&online_nohz, GFP_KERNEL)) { | 227 | if (!have_nohz_full_mask) { |
| 207 | pr_warning("NO_HZ: Not enough memory to check full nohz mask\n"); | 228 | if (tick_nohz_init_all() < 0) |
| 208 | return -ENOMEM; | 229 | return; |
| 209 | } | 230 | } |
| 210 | 231 | ||
| 211 | /* | 232 | cpu_notifier(tick_nohz_cpu_down_callback, 0); |
| 212 | * CPUs can probably not be concurrently offlined on initcall time. | ||
| 213 | * But we are paranoid, aren't we? | ||
| 214 | */ | ||
| 215 | get_online_cpus(); | ||
| 216 | 233 | ||
| 217 | /* Ensure we keep a CPU outside the dynticks range for timekeeping */ | 234 | /* Make sure full dynticks CPU are also RCU nocbs */ |
| 218 | cpumask_and(online_nohz, cpu_online_mask, nohz_full_mask); | 235 | for_each_cpu(cpu, nohz_full_mask) { |
| 219 | if (cpumask_equal(online_nohz, cpu_online_mask)) { | 236 | if (!rcu_is_nocb_cpu(cpu)) { |
| 220 | pr_warning("NO_HZ: Must keep at least one online CPU " | 237 | pr_warning("NO_HZ: CPU %d is not RCU nocb: " |
| 221 | "out of nohz_full range\n"); | 238 | "cleared from nohz_full range", cpu); |
| 222 | /* | 239 | cpumask_clear_cpu(cpu, nohz_full_mask); |
| 223 | * We know the current CPU doesn't have its tick stopped. | 240 | } |
| 224 | * Let's use it for the timekeeping duty. | ||
| 225 | */ | ||
| 226 | preempt_disable(); | ||
| 227 | cpu = smp_processor_id(); | ||
| 228 | pr_warning("NO_HZ: Clearing %d from nohz_full range\n", cpu); | ||
| 229 | cpumask_clear_cpu(cpu, nohz_full_mask); | ||
| 230 | preempt_enable(); | ||
| 231 | } | 241 | } |
| 232 | put_online_cpus(); | ||
| 233 | free_cpumask_var(online_nohz); | ||
| 234 | 242 | ||
| 235 | cpulist_scnprintf(nohz_full_buf, sizeof(nohz_full_buf), nohz_full_mask); | 243 | cpulist_scnprintf(nohz_full_buf, sizeof(nohz_full_buf), nohz_full_mask); |
| 236 | pr_info("NO_HZ: Full dynticks CPUs: %s.\n", nohz_full_buf); | 244 | pr_info("NO_HZ: Full dynticks CPUs: %s.\n", nohz_full_buf); |
| 237 | |||
| 238 | return 0; | ||
| 239 | } | 245 | } |
| 240 | core_initcall(init_tick_nohz_full); | ||
| 241 | #else | 246 | #else |
| 242 | #define have_nohz_full_mask (0) | 247 | #define have_nohz_full_mask (0) |
| 243 | #endif | 248 | #endif |
