diff options
-rw-r--r-- | kernel/sched.c | 104 |
1 files changed, 38 insertions, 66 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index ddf418810c39..6b956bd9b49a 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -5489,15 +5489,17 @@ __setup ("isolcpus=", isolated_cpu_setup); | |||
5489 | * covered by the given span, and will set each group's ->cpumask correctly, | 5489 | * covered by the given span, and will set each group's ->cpumask correctly, |
5490 | * and ->cpu_power to 0. | 5490 | * and ->cpu_power to 0. |
5491 | */ | 5491 | */ |
5492 | static void init_sched_build_groups(struct sched_group groups[], cpumask_t span, | 5492 | static void |
5493 | int (*group_fn)(int cpu)) | 5493 | init_sched_build_groups(struct sched_group groups[], cpumask_t span, |
5494 | const cpumask_t *cpu_map, | ||
5495 | int (*group_fn)(int cpu, const cpumask_t *cpu_map)) | ||
5494 | { | 5496 | { |
5495 | struct sched_group *first = NULL, *last = NULL; | 5497 | struct sched_group *first = NULL, *last = NULL; |
5496 | cpumask_t covered = CPU_MASK_NONE; | 5498 | cpumask_t covered = CPU_MASK_NONE; |
5497 | int i; | 5499 | int i; |
5498 | 5500 | ||
5499 | for_each_cpu_mask(i, span) { | 5501 | for_each_cpu_mask(i, span) { |
5500 | int group = group_fn(i); | 5502 | int group = group_fn(i, cpu_map); |
5501 | struct sched_group *sg = &groups[group]; | 5503 | struct sched_group *sg = &groups[group]; |
5502 | int j; | 5504 | int j; |
5503 | 5505 | ||
@@ -5508,7 +5510,7 @@ static void init_sched_build_groups(struct sched_group groups[], cpumask_t span, | |||
5508 | sg->cpu_power = 0; | 5510 | sg->cpu_power = 0; |
5509 | 5511 | ||
5510 | for_each_cpu_mask(j, span) { | 5512 | for_each_cpu_mask(j, span) { |
5511 | if (group_fn(j) != group) | 5513 | if (group_fn(j, cpu_map) != group) |
5512 | continue; | 5514 | continue; |
5513 | 5515 | ||
5514 | cpu_set(j, covered); | 5516 | cpu_set(j, covered); |
@@ -6084,7 +6086,7 @@ int sched_smt_power_savings = 0, sched_mc_power_savings = 0; | |||
6084 | static DEFINE_PER_CPU(struct sched_domain, cpu_domains); | 6086 | static DEFINE_PER_CPU(struct sched_domain, cpu_domains); |
6085 | static struct sched_group sched_group_cpus[NR_CPUS]; | 6087 | static struct sched_group sched_group_cpus[NR_CPUS]; |
6086 | 6088 | ||
6087 | static int cpu_to_cpu_group(int cpu) | 6089 | static int cpu_to_cpu_group(int cpu, const cpumask_t *cpu_map) |
6088 | { | 6090 | { |
6089 | return cpu; | 6091 | return cpu; |
6090 | } | 6092 | } |
@@ -6095,31 +6097,36 @@ static int cpu_to_cpu_group(int cpu) | |||
6095 | */ | 6097 | */ |
6096 | #ifdef CONFIG_SCHED_MC | 6098 | #ifdef CONFIG_SCHED_MC |
6097 | static DEFINE_PER_CPU(struct sched_domain, core_domains); | 6099 | static DEFINE_PER_CPU(struct sched_domain, core_domains); |
6098 | static struct sched_group *sched_group_core_bycpu[NR_CPUS]; | 6100 | static struct sched_group sched_group_core[NR_CPUS]; |
6099 | #endif | 6101 | #endif |
6100 | 6102 | ||
6101 | #if defined(CONFIG_SCHED_MC) && defined(CONFIG_SCHED_SMT) | 6103 | #if defined(CONFIG_SCHED_MC) && defined(CONFIG_SCHED_SMT) |
6102 | static int cpu_to_core_group(int cpu) | 6104 | static int cpu_to_core_group(int cpu, const cpumask_t *cpu_map) |
6103 | { | 6105 | { |
6104 | return first_cpu(cpu_sibling_map[cpu]); | 6106 | cpumask_t mask = cpu_sibling_map[cpu]; |
6107 | cpus_and(mask, mask, *cpu_map); | ||
6108 | return first_cpu(mask); | ||
6105 | } | 6109 | } |
6106 | #elif defined(CONFIG_SCHED_MC) | 6110 | #elif defined(CONFIG_SCHED_MC) |
6107 | static int cpu_to_core_group(int cpu) | 6111 | static int cpu_to_core_group(int cpu, const cpumask_t *cpu_map) |
6108 | { | 6112 | { |
6109 | return cpu; | 6113 | return cpu; |
6110 | } | 6114 | } |
6111 | #endif | 6115 | #endif |
6112 | 6116 | ||
6113 | static DEFINE_PER_CPU(struct sched_domain, phys_domains); | 6117 | static DEFINE_PER_CPU(struct sched_domain, phys_domains); |
6114 | static struct sched_group *sched_group_phys_bycpu[NR_CPUS]; | 6118 | static struct sched_group sched_group_phys[NR_CPUS]; |
6115 | 6119 | ||
6116 | static int cpu_to_phys_group(int cpu) | 6120 | static int cpu_to_phys_group(int cpu, const cpumask_t *cpu_map) |
6117 | { | 6121 | { |
6118 | #ifdef CONFIG_SCHED_MC | 6122 | #ifdef CONFIG_SCHED_MC |
6119 | cpumask_t mask = cpu_coregroup_map(cpu); | 6123 | cpumask_t mask = cpu_coregroup_map(cpu); |
6124 | cpus_and(mask, mask, *cpu_map); | ||
6120 | return first_cpu(mask); | 6125 | return first_cpu(mask); |
6121 | #elif defined(CONFIG_SCHED_SMT) | 6126 | #elif defined(CONFIG_SCHED_SMT) |
6122 | return first_cpu(cpu_sibling_map[cpu]); | 6127 | cpumask_t mask = cpu_sibling_map[cpu]; |
6128 | cpus_and(mask, mask, *cpu_map); | ||
6129 | return first_cpu(mask); | ||
6123 | #else | 6130 | #else |
6124 | return cpu; | 6131 | return cpu; |
6125 | #endif | 6132 | #endif |
@@ -6137,7 +6144,7 @@ static struct sched_group **sched_group_nodes_bycpu[NR_CPUS]; | |||
6137 | static DEFINE_PER_CPU(struct sched_domain, allnodes_domains); | 6144 | static DEFINE_PER_CPU(struct sched_domain, allnodes_domains); |
6138 | static struct sched_group *sched_group_allnodes_bycpu[NR_CPUS]; | 6145 | static struct sched_group *sched_group_allnodes_bycpu[NR_CPUS]; |
6139 | 6146 | ||
6140 | static int cpu_to_allnodes_group(int cpu) | 6147 | static int cpu_to_allnodes_group(int cpu, const cpumask_t *cpu_map) |
6141 | { | 6148 | { |
6142 | return cpu_to_node(cpu); | 6149 | return cpu_to_node(cpu); |
6143 | } | 6150 | } |
@@ -6169,12 +6176,11 @@ next_sg: | |||
6169 | } | 6176 | } |
6170 | #endif | 6177 | #endif |
6171 | 6178 | ||
6179 | #ifdef CONFIG_NUMA | ||
6172 | /* Free memory allocated for various sched_group structures */ | 6180 | /* Free memory allocated for various sched_group structures */ |
6173 | static void free_sched_groups(const cpumask_t *cpu_map) | 6181 | static void free_sched_groups(const cpumask_t *cpu_map) |
6174 | { | 6182 | { |
6175 | int cpu; | 6183 | int cpu, i; |
6176 | #ifdef CONFIG_NUMA | ||
6177 | int i; | ||
6178 | 6184 | ||
6179 | for_each_cpu_mask(cpu, *cpu_map) { | 6185 | for_each_cpu_mask(cpu, *cpu_map) { |
6180 | struct sched_group *sched_group_allnodes | 6186 | struct sched_group *sched_group_allnodes |
@@ -6211,20 +6217,12 @@ next_sg: | |||
6211 | kfree(sched_group_nodes); | 6217 | kfree(sched_group_nodes); |
6212 | sched_group_nodes_bycpu[cpu] = NULL; | 6218 | sched_group_nodes_bycpu[cpu] = NULL; |
6213 | } | 6219 | } |
6214 | #endif | ||
6215 | for_each_cpu_mask(cpu, *cpu_map) { | ||
6216 | if (sched_group_phys_bycpu[cpu]) { | ||
6217 | kfree(sched_group_phys_bycpu[cpu]); | ||
6218 | sched_group_phys_bycpu[cpu] = NULL; | ||
6219 | } | ||
6220 | #ifdef CONFIG_SCHED_MC | ||
6221 | if (sched_group_core_bycpu[cpu]) { | ||
6222 | kfree(sched_group_core_bycpu[cpu]); | ||
6223 | sched_group_core_bycpu[cpu] = NULL; | ||
6224 | } | ||
6225 | #endif | ||
6226 | } | ||
6227 | } | 6220 | } |
6221 | #else | ||
6222 | static void free_sched_groups(const cpumask_t *cpu_map) | ||
6223 | { | ||
6224 | } | ||
6225 | #endif | ||
6228 | 6226 | ||
6229 | /* | 6227 | /* |
6230 | * Build sched domains for a given set of cpus and attach the sched domains | 6228 | * Build sched domains for a given set of cpus and attach the sched domains |
@@ -6233,10 +6231,6 @@ next_sg: | |||
6233 | static int build_sched_domains(const cpumask_t *cpu_map) | 6231 | static int build_sched_domains(const cpumask_t *cpu_map) |
6234 | { | 6232 | { |
6235 | int i; | 6233 | int i; |
6236 | struct sched_group *sched_group_phys = NULL; | ||
6237 | #ifdef CONFIG_SCHED_MC | ||
6238 | struct sched_group *sched_group_core = NULL; | ||
6239 | #endif | ||
6240 | #ifdef CONFIG_NUMA | 6234 | #ifdef CONFIG_NUMA |
6241 | struct sched_group **sched_group_nodes = NULL; | 6235 | struct sched_group **sched_group_nodes = NULL; |
6242 | struct sched_group *sched_group_allnodes = NULL; | 6236 | struct sched_group *sched_group_allnodes = NULL; |
@@ -6282,7 +6276,7 @@ static int build_sched_domains(const cpumask_t *cpu_map) | |||
6282 | sd = &per_cpu(allnodes_domains, i); | 6276 | sd = &per_cpu(allnodes_domains, i); |
6283 | *sd = SD_ALLNODES_INIT; | 6277 | *sd = SD_ALLNODES_INIT; |
6284 | sd->span = *cpu_map; | 6278 | sd->span = *cpu_map; |
6285 | group = cpu_to_allnodes_group(i); | 6279 | group = cpu_to_allnodes_group(i, cpu_map); |
6286 | sd->groups = &sched_group_allnodes[group]; | 6280 | sd->groups = &sched_group_allnodes[group]; |
6287 | p = sd; | 6281 | p = sd; |
6288 | } else | 6282 | } else |
@@ -6295,42 +6289,18 @@ static int build_sched_domains(const cpumask_t *cpu_map) | |||
6295 | cpus_and(sd->span, sd->span, *cpu_map); | 6289 | cpus_and(sd->span, sd->span, *cpu_map); |
6296 | #endif | 6290 | #endif |
6297 | 6291 | ||
6298 | if (!sched_group_phys) { | ||
6299 | sched_group_phys | ||
6300 | = kmalloc(sizeof(struct sched_group) * NR_CPUS, | ||
6301 | GFP_KERNEL); | ||
6302 | if (!sched_group_phys) { | ||
6303 | printk (KERN_WARNING "Can not alloc phys sched" | ||
6304 | "group\n"); | ||
6305 | goto error; | ||
6306 | } | ||
6307 | sched_group_phys_bycpu[i] = sched_group_phys; | ||
6308 | } | ||
6309 | |||
6310 | p = sd; | 6292 | p = sd; |
6311 | sd = &per_cpu(phys_domains, i); | 6293 | sd = &per_cpu(phys_domains, i); |
6312 | group = cpu_to_phys_group(i); | 6294 | group = cpu_to_phys_group(i, cpu_map); |
6313 | *sd = SD_CPU_INIT; | 6295 | *sd = SD_CPU_INIT; |
6314 | sd->span = nodemask; | 6296 | sd->span = nodemask; |
6315 | sd->parent = p; | 6297 | sd->parent = p; |
6316 | sd->groups = &sched_group_phys[group]; | 6298 | sd->groups = &sched_group_phys[group]; |
6317 | 6299 | ||
6318 | #ifdef CONFIG_SCHED_MC | 6300 | #ifdef CONFIG_SCHED_MC |
6319 | if (!sched_group_core) { | ||
6320 | sched_group_core | ||
6321 | = kmalloc(sizeof(struct sched_group) * NR_CPUS, | ||
6322 | GFP_KERNEL); | ||
6323 | if (!sched_group_core) { | ||
6324 | printk (KERN_WARNING "Can not alloc core sched" | ||
6325 | "group\n"); | ||
6326 | goto error; | ||
6327 | } | ||
6328 | sched_group_core_bycpu[i] = sched_group_core; | ||
6329 | } | ||
6330 | |||
6331 | p = sd; | 6301 | p = sd; |
6332 | sd = &per_cpu(core_domains, i); | 6302 | sd = &per_cpu(core_domains, i); |
6333 | group = cpu_to_core_group(i); | 6303 | group = cpu_to_core_group(i, cpu_map); |
6334 | *sd = SD_MC_INIT; | 6304 | *sd = SD_MC_INIT; |
6335 | sd->span = cpu_coregroup_map(i); | 6305 | sd->span = cpu_coregroup_map(i); |
6336 | cpus_and(sd->span, sd->span, *cpu_map); | 6306 | cpus_and(sd->span, sd->span, *cpu_map); |
@@ -6341,7 +6311,7 @@ static int build_sched_domains(const cpumask_t *cpu_map) | |||
6341 | #ifdef CONFIG_SCHED_SMT | 6311 | #ifdef CONFIG_SCHED_SMT |
6342 | p = sd; | 6312 | p = sd; |
6343 | sd = &per_cpu(cpu_domains, i); | 6313 | sd = &per_cpu(cpu_domains, i); |
6344 | group = cpu_to_cpu_group(i); | 6314 | group = cpu_to_cpu_group(i, cpu_map); |
6345 | *sd = SD_SIBLING_INIT; | 6315 | *sd = SD_SIBLING_INIT; |
6346 | sd->span = cpu_sibling_map[i]; | 6316 | sd->span = cpu_sibling_map[i]; |
6347 | cpus_and(sd->span, sd->span, *cpu_map); | 6317 | cpus_and(sd->span, sd->span, *cpu_map); |
@@ -6359,7 +6329,7 @@ static int build_sched_domains(const cpumask_t *cpu_map) | |||
6359 | continue; | 6329 | continue; |
6360 | 6330 | ||
6361 | init_sched_build_groups(sched_group_cpus, this_sibling_map, | 6331 | init_sched_build_groups(sched_group_cpus, this_sibling_map, |
6362 | &cpu_to_cpu_group); | 6332 | cpu_map, &cpu_to_cpu_group); |
6363 | } | 6333 | } |
6364 | #endif | 6334 | #endif |
6365 | 6335 | ||
@@ -6371,7 +6341,7 @@ static int build_sched_domains(const cpumask_t *cpu_map) | |||
6371 | if (i != first_cpu(this_core_map)) | 6341 | if (i != first_cpu(this_core_map)) |
6372 | continue; | 6342 | continue; |
6373 | init_sched_build_groups(sched_group_core, this_core_map, | 6343 | init_sched_build_groups(sched_group_core, this_core_map, |
6374 | &cpu_to_core_group); | 6344 | cpu_map, &cpu_to_core_group); |
6375 | } | 6345 | } |
6376 | #endif | 6346 | #endif |
6377 | 6347 | ||
@@ -6385,14 +6355,14 @@ static int build_sched_domains(const cpumask_t *cpu_map) | |||
6385 | continue; | 6355 | continue; |
6386 | 6356 | ||
6387 | init_sched_build_groups(sched_group_phys, nodemask, | 6357 | init_sched_build_groups(sched_group_phys, nodemask, |
6388 | &cpu_to_phys_group); | 6358 | cpu_map, &cpu_to_phys_group); |
6389 | } | 6359 | } |
6390 | 6360 | ||
6391 | #ifdef CONFIG_NUMA | 6361 | #ifdef CONFIG_NUMA |
6392 | /* Set up node groups */ | 6362 | /* Set up node groups */ |
6393 | if (sched_group_allnodes) | 6363 | if (sched_group_allnodes) |
6394 | init_sched_build_groups(sched_group_allnodes, *cpu_map, | 6364 | init_sched_build_groups(sched_group_allnodes, *cpu_map, |
6395 | &cpu_to_allnodes_group); | 6365 | cpu_map, &cpu_to_allnodes_group); |
6396 | 6366 | ||
6397 | for (i = 0; i < MAX_NUMNODES; i++) { | 6367 | for (i = 0; i < MAX_NUMNODES; i++) { |
6398 | /* Set up node groups */ | 6368 | /* Set up node groups */ |
@@ -6537,7 +6507,7 @@ static int build_sched_domains(const cpumask_t *cpu_map) | |||
6537 | init_numa_sched_groups_power(sched_group_nodes[i]); | 6507 | init_numa_sched_groups_power(sched_group_nodes[i]); |
6538 | 6508 | ||
6539 | if (sched_group_allnodes) { | 6509 | if (sched_group_allnodes) { |
6540 | int group = cpu_to_allnodes_group(first_cpu(*cpu_map)); | 6510 | int group = cpu_to_allnodes_group(first_cpu(*cpu_map), cpu_map); |
6541 | struct sched_group *sg = &sched_group_allnodes[group]; | 6511 | struct sched_group *sg = &sched_group_allnodes[group]; |
6542 | 6512 | ||
6543 | init_numa_sched_groups_power(sg); | 6513 | init_numa_sched_groups_power(sg); |
@@ -6563,9 +6533,11 @@ static int build_sched_domains(const cpumask_t *cpu_map) | |||
6563 | 6533 | ||
6564 | return 0; | 6534 | return 0; |
6565 | 6535 | ||
6536 | #ifdef CONFIG_NUMA | ||
6566 | error: | 6537 | error: |
6567 | free_sched_groups(cpu_map); | 6538 | free_sched_groups(cpu_map); |
6568 | return -ENOMEM; | 6539 | return -ENOMEM; |
6540 | #endif | ||
6569 | } | 6541 | } |
6570 | /* | 6542 | /* |
6571 | * Set up scheduler domains and groups. Callers must hold the hotplug lock. | 6543 | * Set up scheduler domains and groups. Callers must hold the hotplug lock. |