diff options
Diffstat (limited to 'kernel/sched.c')
-rw-r--r-- | kernel/sched.c | 132 |
1 files changed, 64 insertions, 68 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index 479199ab14ab..a08387b5f7fa 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -5528,28 +5528,27 @@ static int __init isolated_cpu_setup(char *str) | |||
5528 | __setup ("isolcpus=", isolated_cpu_setup); | 5528 | __setup ("isolcpus=", isolated_cpu_setup); |
5529 | 5529 | ||
5530 | /* | 5530 | /* |
5531 | * init_sched_build_groups takes an array of groups, the cpumask we wish | 5531 | * init_sched_build_groups takes the cpumask we wish to span, and a pointer |
5532 | * to span, and a pointer to a function which identifies what group a CPU | 5532 | * to a function which identifies what group(along with sched group) a CPU |
5533 | * belongs to. The return value of group_fn must be a valid index into the | 5533 | * belongs to. The return value of group_fn must be a >= 0 and < NR_CPUS |
5534 | * groups[] array, and must be >= 0 and < NR_CPUS (due to the fact that we | 5534 | * (due to the fact that we keep track of groups covered with a cpumask_t). |
5535 | * keep track of groups covered with a cpumask_t). | ||
5536 | * | 5535 | * |
5537 | * init_sched_build_groups will build a circular linked list of the groups | 5536 | * init_sched_build_groups will build a circular linked list of the groups |
5538 | * covered by the given span, and will set each group's ->cpumask correctly, | 5537 | * covered by the given span, and will set each group's ->cpumask correctly, |
5539 | * and ->cpu_power to 0. | 5538 | * and ->cpu_power to 0. |
5540 | */ | 5539 | */ |
5541 | static void | 5540 | static void |
5542 | init_sched_build_groups(struct sched_group groups[], cpumask_t span, | 5541 | init_sched_build_groups(cpumask_t span, const cpumask_t *cpu_map, |
5543 | const cpumask_t *cpu_map, | 5542 | int (*group_fn)(int cpu, const cpumask_t *cpu_map, |
5544 | int (*group_fn)(int cpu, const cpumask_t *cpu_map)) | 5543 | struct sched_group **sg)) |
5545 | { | 5544 | { |
5546 | struct sched_group *first = NULL, *last = NULL; | 5545 | struct sched_group *first = NULL, *last = NULL; |
5547 | cpumask_t covered = CPU_MASK_NONE; | 5546 | cpumask_t covered = CPU_MASK_NONE; |
5548 | int i; | 5547 | int i; |
5549 | 5548 | ||
5550 | for_each_cpu_mask(i, span) { | 5549 | for_each_cpu_mask(i, span) { |
5551 | int group = group_fn(i, cpu_map); | 5550 | struct sched_group *sg; |
5552 | struct sched_group *sg = &groups[group]; | 5551 | int group = group_fn(i, cpu_map, &sg); |
5553 | int j; | 5552 | int j; |
5554 | 5553 | ||
5555 | if (cpu_isset(i, covered)) | 5554 | if (cpu_isset(i, covered)) |
@@ -5559,7 +5558,7 @@ init_sched_build_groups(struct sched_group groups[], cpumask_t span, | |||
5559 | sg->cpu_power = 0; | 5558 | sg->cpu_power = 0; |
5560 | 5559 | ||
5561 | for_each_cpu_mask(j, span) { | 5560 | for_each_cpu_mask(j, span) { |
5562 | if (group_fn(j, cpu_map) != group) | 5561 | if (group_fn(j, cpu_map, NULL) != group) |
5563 | continue; | 5562 | continue; |
5564 | 5563 | ||
5565 | cpu_set(j, covered); | 5564 | cpu_set(j, covered); |
@@ -6135,10 +6134,13 @@ int sched_smt_power_savings = 0, sched_mc_power_savings = 0; | |||
6135 | */ | 6134 | */ |
6136 | #ifdef CONFIG_SCHED_SMT | 6135 | #ifdef CONFIG_SCHED_SMT |
6137 | static DEFINE_PER_CPU(struct sched_domain, cpu_domains); | 6136 | static DEFINE_PER_CPU(struct sched_domain, cpu_domains); |
6138 | static struct sched_group sched_group_cpus[NR_CPUS]; | 6137 | static DEFINE_PER_CPU(struct sched_group, sched_group_cpus); |
6139 | 6138 | ||
6140 | static int cpu_to_cpu_group(int cpu, const cpumask_t *cpu_map) | 6139 | static int cpu_to_cpu_group(int cpu, const cpumask_t *cpu_map, |
6140 | struct sched_group **sg) | ||
6141 | { | 6141 | { |
6142 | if (sg) | ||
6143 | *sg = &per_cpu(sched_group_cpus, cpu); | ||
6142 | return cpu; | 6144 | return cpu; |
6143 | } | 6145 | } |
6144 | #endif | 6146 | #endif |
@@ -6148,39 +6150,52 @@ static int cpu_to_cpu_group(int cpu, const cpumask_t *cpu_map) | |||
6148 | */ | 6150 | */ |
6149 | #ifdef CONFIG_SCHED_MC | 6151 | #ifdef CONFIG_SCHED_MC |
6150 | static DEFINE_PER_CPU(struct sched_domain, core_domains); | 6152 | static DEFINE_PER_CPU(struct sched_domain, core_domains); |
6151 | static struct sched_group sched_group_core[NR_CPUS]; | 6153 | static DEFINE_PER_CPU(struct sched_group, sched_group_core); |
6152 | #endif | 6154 | #endif |
6153 | 6155 | ||
6154 | #if defined(CONFIG_SCHED_MC) && defined(CONFIG_SCHED_SMT) | 6156 | #if defined(CONFIG_SCHED_MC) && defined(CONFIG_SCHED_SMT) |
6155 | static int cpu_to_core_group(int cpu, const cpumask_t *cpu_map) | 6157 | static int cpu_to_core_group(int cpu, const cpumask_t *cpu_map, |
6158 | struct sched_group **sg) | ||
6156 | { | 6159 | { |
6160 | int group; | ||
6157 | cpumask_t mask = cpu_sibling_map[cpu]; | 6161 | cpumask_t mask = cpu_sibling_map[cpu]; |
6158 | cpus_and(mask, mask, *cpu_map); | 6162 | cpus_and(mask, mask, *cpu_map); |
6159 | return first_cpu(mask); | 6163 | group = first_cpu(mask); |
6164 | if (sg) | ||
6165 | *sg = &per_cpu(sched_group_core, group); | ||
6166 | return group; | ||
6160 | } | 6167 | } |
6161 | #elif defined(CONFIG_SCHED_MC) | 6168 | #elif defined(CONFIG_SCHED_MC) |
6162 | static int cpu_to_core_group(int cpu, const cpumask_t *cpu_map) | 6169 | static int cpu_to_core_group(int cpu, const cpumask_t *cpu_map, |
6170 | struct sched_group **sg) | ||
6163 | { | 6171 | { |
6172 | if (sg) | ||
6173 | *sg = &per_cpu(sched_group_core, cpu); | ||
6164 | return cpu; | 6174 | return cpu; |
6165 | } | 6175 | } |
6166 | #endif | 6176 | #endif |
6167 | 6177 | ||
6168 | static DEFINE_PER_CPU(struct sched_domain, phys_domains); | 6178 | static DEFINE_PER_CPU(struct sched_domain, phys_domains); |
6169 | static struct sched_group sched_group_phys[NR_CPUS]; | 6179 | static DEFINE_PER_CPU(struct sched_group, sched_group_phys); |
6170 | 6180 | ||
6171 | static int cpu_to_phys_group(int cpu, const cpumask_t *cpu_map) | 6181 | static int cpu_to_phys_group(int cpu, const cpumask_t *cpu_map, |
6182 | struct sched_group **sg) | ||
6172 | { | 6183 | { |
6184 | int group; | ||
6173 | #ifdef CONFIG_SCHED_MC | 6185 | #ifdef CONFIG_SCHED_MC |
6174 | cpumask_t mask = cpu_coregroup_map(cpu); | 6186 | cpumask_t mask = cpu_coregroup_map(cpu); |
6175 | cpus_and(mask, mask, *cpu_map); | 6187 | cpus_and(mask, mask, *cpu_map); |
6176 | return first_cpu(mask); | 6188 | group = first_cpu(mask); |
6177 | #elif defined(CONFIG_SCHED_SMT) | 6189 | #elif defined(CONFIG_SCHED_SMT) |
6178 | cpumask_t mask = cpu_sibling_map[cpu]; | 6190 | cpumask_t mask = cpu_sibling_map[cpu]; |
6179 | cpus_and(mask, mask, *cpu_map); | 6191 | cpus_and(mask, mask, *cpu_map); |
6180 | return first_cpu(mask); | 6192 | group = first_cpu(mask); |
6181 | #else | 6193 | #else |
6182 | return cpu; | 6194 | group = cpu; |
6183 | #endif | 6195 | #endif |
6196 | if (sg) | ||
6197 | *sg = &per_cpu(sched_group_phys, group); | ||
6198 | return group; | ||
6184 | } | 6199 | } |
6185 | 6200 | ||
6186 | #ifdef CONFIG_NUMA | 6201 | #ifdef CONFIG_NUMA |
@@ -6193,12 +6208,22 @@ static DEFINE_PER_CPU(struct sched_domain, node_domains); | |||
6193 | static struct sched_group **sched_group_nodes_bycpu[NR_CPUS]; | 6208 | static struct sched_group **sched_group_nodes_bycpu[NR_CPUS]; |
6194 | 6209 | ||
6195 | static DEFINE_PER_CPU(struct sched_domain, allnodes_domains); | 6210 | static DEFINE_PER_CPU(struct sched_domain, allnodes_domains); |
6196 | static struct sched_group *sched_group_allnodes_bycpu[NR_CPUS]; | 6211 | static DEFINE_PER_CPU(struct sched_group, sched_group_allnodes); |
6197 | 6212 | ||
6198 | static int cpu_to_allnodes_group(int cpu, const cpumask_t *cpu_map) | 6213 | static int cpu_to_allnodes_group(int cpu, const cpumask_t *cpu_map, |
6214 | struct sched_group **sg) | ||
6199 | { | 6215 | { |
6200 | return cpu_to_node(cpu); | 6216 | cpumask_t nodemask = node_to_cpumask(cpu_to_node(cpu)); |
6217 | int group; | ||
6218 | |||
6219 | cpus_and(nodemask, nodemask, *cpu_map); | ||
6220 | group = first_cpu(nodemask); | ||
6221 | |||
6222 | if (sg) | ||
6223 | *sg = &per_cpu(sched_group_allnodes, group); | ||
6224 | return group; | ||
6201 | } | 6225 | } |
6226 | |||
6202 | static void init_numa_sched_groups_power(struct sched_group *group_head) | 6227 | static void init_numa_sched_groups_power(struct sched_group *group_head) |
6203 | { | 6228 | { |
6204 | struct sched_group *sg = group_head; | 6229 | struct sched_group *sg = group_head; |
@@ -6234,16 +6259,9 @@ static void free_sched_groups(const cpumask_t *cpu_map) | |||
6234 | int cpu, i; | 6259 | int cpu, i; |
6235 | 6260 | ||
6236 | for_each_cpu_mask(cpu, *cpu_map) { | 6261 | for_each_cpu_mask(cpu, *cpu_map) { |
6237 | struct sched_group *sched_group_allnodes | ||
6238 | = sched_group_allnodes_bycpu[cpu]; | ||
6239 | struct sched_group **sched_group_nodes | 6262 | struct sched_group **sched_group_nodes |
6240 | = sched_group_nodes_bycpu[cpu]; | 6263 | = sched_group_nodes_bycpu[cpu]; |
6241 | 6264 | ||
6242 | if (sched_group_allnodes) { | ||
6243 | kfree(sched_group_allnodes); | ||
6244 | sched_group_allnodes_bycpu[cpu] = NULL; | ||
6245 | } | ||
6246 | |||
6247 | if (!sched_group_nodes) | 6265 | if (!sched_group_nodes) |
6248 | continue; | 6266 | continue; |
6249 | 6267 | ||
@@ -6337,7 +6355,7 @@ static int build_sched_domains(const cpumask_t *cpu_map) | |||
6337 | struct sched_domain *sd; | 6355 | struct sched_domain *sd; |
6338 | #ifdef CONFIG_NUMA | 6356 | #ifdef CONFIG_NUMA |
6339 | struct sched_group **sched_group_nodes = NULL; | 6357 | struct sched_group **sched_group_nodes = NULL; |
6340 | struct sched_group *sched_group_allnodes = NULL; | 6358 | int sd_allnodes = 0; |
6341 | 6359 | ||
6342 | /* | 6360 | /* |
6343 | * Allocate the per-node list of sched groups | 6361 | * Allocate the per-node list of sched groups |
@@ -6355,7 +6373,6 @@ static int build_sched_domains(const cpumask_t *cpu_map) | |||
6355 | * Set up domains for cpus specified by the cpu_map. | 6373 | * Set up domains for cpus specified by the cpu_map. |
6356 | */ | 6374 | */ |
6357 | for_each_cpu_mask(i, *cpu_map) { | 6375 | for_each_cpu_mask(i, *cpu_map) { |
6358 | int group; | ||
6359 | struct sched_domain *sd = NULL, *p; | 6376 | struct sched_domain *sd = NULL, *p; |
6360 | cpumask_t nodemask = node_to_cpumask(cpu_to_node(i)); | 6377 | cpumask_t nodemask = node_to_cpumask(cpu_to_node(i)); |
6361 | 6378 | ||
@@ -6364,26 +6381,12 @@ static int build_sched_domains(const cpumask_t *cpu_map) | |||
6364 | #ifdef CONFIG_NUMA | 6381 | #ifdef CONFIG_NUMA |
6365 | if (cpus_weight(*cpu_map) | 6382 | if (cpus_weight(*cpu_map) |
6366 | > SD_NODES_PER_DOMAIN*cpus_weight(nodemask)) { | 6383 | > SD_NODES_PER_DOMAIN*cpus_weight(nodemask)) { |
6367 | if (!sched_group_allnodes) { | ||
6368 | sched_group_allnodes | ||
6369 | = kmalloc_node(sizeof(struct sched_group) | ||
6370 | * MAX_NUMNODES, | ||
6371 | GFP_KERNEL, | ||
6372 | cpu_to_node(i)); | ||
6373 | if (!sched_group_allnodes) { | ||
6374 | printk(KERN_WARNING | ||
6375 | "Can not alloc allnodes sched group\n"); | ||
6376 | goto error; | ||
6377 | } | ||
6378 | sched_group_allnodes_bycpu[i] | ||
6379 | = sched_group_allnodes; | ||
6380 | } | ||
6381 | sd = &per_cpu(allnodes_domains, i); | 6384 | sd = &per_cpu(allnodes_domains, i); |
6382 | *sd = SD_ALLNODES_INIT; | 6385 | *sd = SD_ALLNODES_INIT; |
6383 | sd->span = *cpu_map; | 6386 | sd->span = *cpu_map; |
6384 | group = cpu_to_allnodes_group(i, cpu_map); | 6387 | cpu_to_allnodes_group(i, cpu_map, &sd->groups); |
6385 | sd->groups = &sched_group_allnodes[group]; | ||
6386 | p = sd; | 6388 | p = sd; |
6389 | sd_allnodes = 1; | ||
6387 | } else | 6390 | } else |
6388 | p = NULL; | 6391 | p = NULL; |
6389 | 6392 | ||
@@ -6398,36 +6401,33 @@ static int build_sched_domains(const cpumask_t *cpu_map) | |||
6398 | 6401 | ||
6399 | p = sd; | 6402 | p = sd; |
6400 | sd = &per_cpu(phys_domains, i); | 6403 | sd = &per_cpu(phys_domains, i); |
6401 | group = cpu_to_phys_group(i, cpu_map); | ||
6402 | *sd = SD_CPU_INIT; | 6404 | *sd = SD_CPU_INIT; |
6403 | sd->span = nodemask; | 6405 | sd->span = nodemask; |
6404 | sd->parent = p; | 6406 | sd->parent = p; |
6405 | if (p) | 6407 | if (p) |
6406 | p->child = sd; | 6408 | p->child = sd; |
6407 | sd->groups = &sched_group_phys[group]; | 6409 | cpu_to_phys_group(i, cpu_map, &sd->groups); |
6408 | 6410 | ||
6409 | #ifdef CONFIG_SCHED_MC | 6411 | #ifdef CONFIG_SCHED_MC |
6410 | p = sd; | 6412 | p = sd; |
6411 | sd = &per_cpu(core_domains, i); | 6413 | sd = &per_cpu(core_domains, i); |
6412 | group = cpu_to_core_group(i, cpu_map); | ||
6413 | *sd = SD_MC_INIT; | 6414 | *sd = SD_MC_INIT; |
6414 | sd->span = cpu_coregroup_map(i); | 6415 | sd->span = cpu_coregroup_map(i); |
6415 | cpus_and(sd->span, sd->span, *cpu_map); | 6416 | cpus_and(sd->span, sd->span, *cpu_map); |
6416 | sd->parent = p; | 6417 | sd->parent = p; |
6417 | p->child = sd; | 6418 | p->child = sd; |
6418 | sd->groups = &sched_group_core[group]; | 6419 | cpu_to_core_group(i, cpu_map, &sd->groups); |
6419 | #endif | 6420 | #endif |
6420 | 6421 | ||
6421 | #ifdef CONFIG_SCHED_SMT | 6422 | #ifdef CONFIG_SCHED_SMT |
6422 | p = sd; | 6423 | p = sd; |
6423 | sd = &per_cpu(cpu_domains, i); | 6424 | sd = &per_cpu(cpu_domains, i); |
6424 | group = cpu_to_cpu_group(i, cpu_map); | ||
6425 | *sd = SD_SIBLING_INIT; | 6425 | *sd = SD_SIBLING_INIT; |
6426 | sd->span = cpu_sibling_map[i]; | 6426 | sd->span = cpu_sibling_map[i]; |
6427 | cpus_and(sd->span, sd->span, *cpu_map); | 6427 | cpus_and(sd->span, sd->span, *cpu_map); |
6428 | sd->parent = p; | 6428 | sd->parent = p; |
6429 | p->child = sd; | 6429 | p->child = sd; |
6430 | sd->groups = &sched_group_cpus[group]; | 6430 | cpu_to_cpu_group(i, cpu_map, &sd->groups); |
6431 | #endif | 6431 | #endif |
6432 | } | 6432 | } |
6433 | 6433 | ||
@@ -6439,8 +6439,7 @@ static int build_sched_domains(const cpumask_t *cpu_map) | |||
6439 | if (i != first_cpu(this_sibling_map)) | 6439 | if (i != first_cpu(this_sibling_map)) |
6440 | continue; | 6440 | continue; |
6441 | 6441 | ||
6442 | init_sched_build_groups(sched_group_cpus, this_sibling_map, | 6442 | init_sched_build_groups(this_sibling_map, cpu_map, &cpu_to_cpu_group); |
6443 | cpu_map, &cpu_to_cpu_group); | ||
6444 | } | 6443 | } |
6445 | #endif | 6444 | #endif |
6446 | 6445 | ||
@@ -6451,8 +6450,7 @@ static int build_sched_domains(const cpumask_t *cpu_map) | |||
6451 | cpus_and(this_core_map, this_core_map, *cpu_map); | 6450 | cpus_and(this_core_map, this_core_map, *cpu_map); |
6452 | if (i != first_cpu(this_core_map)) | 6451 | if (i != first_cpu(this_core_map)) |
6453 | continue; | 6452 | continue; |
6454 | init_sched_build_groups(sched_group_core, this_core_map, | 6453 | init_sched_build_groups(this_core_map, cpu_map, &cpu_to_core_group); |
6455 | cpu_map, &cpu_to_core_group); | ||
6456 | } | 6454 | } |
6457 | #endif | 6455 | #endif |
6458 | 6456 | ||
@@ -6465,15 +6463,13 @@ static int build_sched_domains(const cpumask_t *cpu_map) | |||
6465 | if (cpus_empty(nodemask)) | 6463 | if (cpus_empty(nodemask)) |
6466 | continue; | 6464 | continue; |
6467 | 6465 | ||
6468 | init_sched_build_groups(sched_group_phys, nodemask, | 6466 | init_sched_build_groups(nodemask, cpu_map, &cpu_to_phys_group); |
6469 | cpu_map, &cpu_to_phys_group); | ||
6470 | } | 6467 | } |
6471 | 6468 | ||
6472 | #ifdef CONFIG_NUMA | 6469 | #ifdef CONFIG_NUMA |
6473 | /* Set up node groups */ | 6470 | /* Set up node groups */ |
6474 | if (sched_group_allnodes) | 6471 | if (sd_allnodes) |
6475 | init_sched_build_groups(sched_group_allnodes, *cpu_map, | 6472 | init_sched_build_groups(*cpu_map, cpu_map, &cpu_to_allnodes_group); |
6476 | cpu_map, &cpu_to_allnodes_group); | ||
6477 | 6473 | ||
6478 | for (i = 0; i < MAX_NUMNODES; i++) { | 6474 | for (i = 0; i < MAX_NUMNODES; i++) { |
6479 | /* Set up node groups */ | 6475 | /* Set up node groups */ |
@@ -6565,10 +6561,10 @@ static int build_sched_domains(const cpumask_t *cpu_map) | |||
6565 | for (i = 0; i < MAX_NUMNODES; i++) | 6561 | for (i = 0; i < MAX_NUMNODES; i++) |
6566 | init_numa_sched_groups_power(sched_group_nodes[i]); | 6562 | init_numa_sched_groups_power(sched_group_nodes[i]); |
6567 | 6563 | ||
6568 | if (sched_group_allnodes) { | 6564 | if (sd_allnodes) { |
6569 | int group = cpu_to_allnodes_group(first_cpu(*cpu_map), cpu_map); | 6565 | struct sched_group *sg; |
6570 | struct sched_group *sg = &sched_group_allnodes[group]; | ||
6571 | 6566 | ||
6567 | cpu_to_allnodes_group(first_cpu(*cpu_map), cpu_map, &sg); | ||
6572 | init_numa_sched_groups_power(sg); | 6568 | init_numa_sched_groups_power(sg); |
6573 | } | 6569 | } |
6574 | #endif | 6570 | #endif |