aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sched/core.c')
-rw-r--r--kernel/sched/core.c99
1 files changed, 80 insertions, 19 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 725ee7c1c8cf..2bdd17616437 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -5556,15 +5556,20 @@ static cpumask_var_t sched_domains_tmpmask; /* sched_domains_mutex */
5556 5556
5557#ifdef CONFIG_SCHED_DEBUG 5557#ifdef CONFIG_SCHED_DEBUG
5558 5558
5559static __read_mostly int sched_domain_debug_enabled; 5559static __read_mostly int sched_debug_enabled;
5560 5560
5561static int __init sched_domain_debug_setup(char *str) 5561static int __init sched_debug_setup(char *str)
5562{ 5562{
5563 sched_domain_debug_enabled = 1; 5563 sched_debug_enabled = 1;
5564 5564
5565 return 0; 5565 return 0;
5566} 5566}
5567early_param("sched_debug", sched_domain_debug_setup); 5567early_param("sched_debug", sched_debug_setup);
5568
5569static inline bool sched_debug(void)
5570{
5571 return sched_debug_enabled;
5572}
5568 5573
5569static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level, 5574static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level,
5570 struct cpumask *groupmask) 5575 struct cpumask *groupmask)
@@ -5657,7 +5662,7 @@ static void sched_domain_debug(struct sched_domain *sd, int cpu)
5657{ 5662{
5658 int level = 0; 5663 int level = 0;
5659 5664
5660 if (!sched_domain_debug_enabled) 5665 if (!sched_debug_enabled)
5661 return; 5666 return;
5662 5667
5663 if (!sd) { 5668 if (!sd) {
@@ -5678,6 +5683,10 @@ static void sched_domain_debug(struct sched_domain *sd, int cpu)
5678} 5683}
5679#else /* !CONFIG_SCHED_DEBUG */ 5684#else /* !CONFIG_SCHED_DEBUG */
5680# define sched_domain_debug(sd, cpu) do { } while (0) 5685# define sched_domain_debug(sd, cpu) do { } while (0)
5686static inline bool sched_debug(void)
5687{
5688 return false;
5689}
5681#endif /* CONFIG_SCHED_DEBUG */ 5690#endif /* CONFIG_SCHED_DEBUG */
5682 5691
5683static int sd_degenerate(struct sched_domain *sd) 5692static int sd_degenerate(struct sched_domain *sd)
@@ -6373,7 +6382,6 @@ static struct sched_domain_topology_level *sched_domain_topology = default_topol
6373#ifdef CONFIG_NUMA 6382#ifdef CONFIG_NUMA
6374 6383
6375static int sched_domains_numa_levels; 6384static int sched_domains_numa_levels;
6376static int sched_domains_numa_scale;
6377static int *sched_domains_numa_distance; 6385static int *sched_domains_numa_distance;
6378static struct cpumask ***sched_domains_numa_masks; 6386static struct cpumask ***sched_domains_numa_masks;
6379static int sched_domains_curr_level; 6387static int sched_domains_curr_level;
@@ -6438,6 +6446,42 @@ static const struct cpumask *sd_numa_mask(int cpu)
6438 return sched_domains_numa_masks[sched_domains_curr_level][cpu_to_node(cpu)]; 6446 return sched_domains_numa_masks[sched_domains_curr_level][cpu_to_node(cpu)];
6439} 6447}
6440 6448
6449static void sched_numa_warn(const char *str)
6450{
6451 static int done = false;
6452 int i,j;
6453
6454 if (done)
6455 return;
6456
6457 done = true;
6458
6459 printk(KERN_WARNING "ERROR: %s\n\n", str);
6460
6461 for (i = 0; i < nr_node_ids; i++) {
6462 printk(KERN_WARNING " ");
6463 for (j = 0; j < nr_node_ids; j++)
6464 printk(KERN_CONT "%02d ", node_distance(i,j));
6465 printk(KERN_CONT "\n");
6466 }
6467 printk(KERN_WARNING "\n");
6468}
6469
6470static bool find_numa_distance(int distance)
6471{
6472 int i;
6473
6474 if (distance == node_distance(0, 0))
6475 return true;
6476
6477 for (i = 0; i < sched_domains_numa_levels; i++) {
6478 if (sched_domains_numa_distance[i] == distance)
6479 return true;
6480 }
6481
6482 return false;
6483}
6484
6441static void sched_init_numa(void) 6485static void sched_init_numa(void)
6442{ 6486{
6443 int next_distance, curr_distance = node_distance(0, 0); 6487 int next_distance, curr_distance = node_distance(0, 0);
@@ -6445,7 +6489,6 @@ static void sched_init_numa(void)
6445 int level = 0; 6489 int level = 0;
6446 int i, j, k; 6490 int i, j, k;
6447 6491
6448 sched_domains_numa_scale = curr_distance;
6449 sched_domains_numa_distance = kzalloc(sizeof(int) * nr_node_ids, GFP_KERNEL); 6492 sched_domains_numa_distance = kzalloc(sizeof(int) * nr_node_ids, GFP_KERNEL);
6450 if (!sched_domains_numa_distance) 6493 if (!sched_domains_numa_distance)
6451 return; 6494 return;
@@ -6456,23 +6499,41 @@ static void sched_init_numa(void)
6456 * 6499 *
6457 * Assumes node_distance(0,j) includes all distances in 6500 * Assumes node_distance(0,j) includes all distances in
6458 * node_distance(i,j) in order to avoid cubic time. 6501 * node_distance(i,j) in order to avoid cubic time.
6459 *
6460 * XXX: could be optimized to O(n log n) by using sort()
6461 */ 6502 */
6462 next_distance = curr_distance; 6503 next_distance = curr_distance;
6463 for (i = 0; i < nr_node_ids; i++) { 6504 for (i = 0; i < nr_node_ids; i++) {
6464 for (j = 0; j < nr_node_ids; j++) { 6505 for (j = 0; j < nr_node_ids; j++) {
6465 int distance = node_distance(0, j); 6506 for (k = 0; k < nr_node_ids; k++) {
6466 if (distance > curr_distance && 6507 int distance = node_distance(i, k);
6467 (distance < next_distance || 6508
6468 next_distance == curr_distance)) 6509 if (distance > curr_distance &&
6469 next_distance = distance; 6510 (distance < next_distance ||
6511 next_distance == curr_distance))
6512 next_distance = distance;
6513
6514 /*
6515 * While not a strong assumption it would be nice to know
6516 * about cases where if node A is connected to B, B is not
6517 * equally connected to A.
6518 */
6519 if (sched_debug() && node_distance(k, i) != distance)
6520 sched_numa_warn("Node-distance not symmetric");
6521
6522 if (sched_debug() && i && !find_numa_distance(distance))
6523 sched_numa_warn("Node-0 not representative");
6524 }
6525 if (next_distance != curr_distance) {
6526 sched_domains_numa_distance[level++] = next_distance;
6527 sched_domains_numa_levels = level;
6528 curr_distance = next_distance;
6529 } else break;
6470 } 6530 }
6471 if (next_distance != curr_distance) { 6531
6472 sched_domains_numa_distance[level++] = next_distance; 6532 /*
6473 sched_domains_numa_levels = level; 6533 * In case of sched_debug() we verify the above assumption.
6474 curr_distance = next_distance; 6534 */
6475 } else break; 6535 if (!sched_debug())
6536 break;
6476 } 6537 }
6477 /* 6538 /*
6478 * 'level' contains the number of unique distances, excluding the 6539 * 'level' contains the number of unique distances, excluding the