sched: Validate assumptions in sched_init_numa( )
Commit-ID: d039ac60800fe8ed8522ec3b9ca796aaf748c18b Gitweb: http://git.kernel.org/tip/d039ac60800fe8ed8522ec3b9ca796aaf748c18b Author: Peter Zijlstra <[email protected]> AuthorDate: Thu, 31 May 2012 21:20:16 +0200 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 6 Jun 2012 16:52:30 +0200
sched: Validate assumptions in sched_init_numa()
Add some code to validate assumptions we're making and output warnings if they are not.
If this trigger we want to know about it.
Signed-off-by Peter Zijlstra <[email protected]>
Cc Alex Shi <[email protected]>
Signed-off-by Ingo Molnar <[email protected]>
--- kernel/sched/core.c | 99 +++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 80 insertions(+), 19 deletions(-)
kernel/sched/core.c +80 -19
@@ -5556,15 +5556,20 @@ static cpumask_var_t sched_domains_tmpmask; /* sched_domains_mutex */#ifdef CONFIG_SCHED_DEBUG -static __read_mostly int sched_domain_debug_enabled; +static __read_mostly int sched_debug_enabled; -static int __init sched_domain_debug_setup (char *str) +static int __init sched_debug_setup (char *str) { - sched_domain_debug_enabled =1 ; + sched_debug_enabled =1 ;return 0 ; } -early_param ("sched_debug" , sched_domain_debug_setup); +early_param ("sched_debug" , sched_debug_setup); + +static inline bool sched_debug (void ) +{ +return sched_debug_enabled; +}static int sched_domain_debug_one (struct sched_domain *sd,int cpu,int level,struct cpumask *groupmask)
@@ -5657,7 +5662,7 @@ static void sched_domain_debug(struct sched_domain *sd, int cpu) {int level =0 ; -if (!sched_domain_debug_enabled) +if (!sched_debug_enabled)return ;if (!sd) {
@@ -5678,6 +5683,10 @@ static void sched_domain_debug(struct sched_domain *sd, int cpu) }#else /* !CONFIG_SCHED_DEBUG */ # define sched_domain_debug (sd, cpu) do { } while (0) +static inline bool sched_debug (void ) +{ +return false; +}#endif /* CONFIG_SCHED_DEBUG */ static int sd_degenerate (struct sched_domain *sd)
@@ -6373,7 +6382,6 @@ static struct sched_domain_topology_level *sched_domain_topology = default_topol#ifdef CONFIG_NUMA static int sched_domains_numa_levels; -static int sched_domains_numa_scale;static int *sched_domains_numa_distance;static struct cpumask ***sched_domains_numa_masks;static int sched_domains_curr_level;
@@ -6438,6 +6446,42 @@ static const struct cpumask *sd_numa_mask(int cpu)return sched_domains_numa_masks[sched_domains_curr_level][cpu_to_node (cpu)]; } +static void sched_numa_warn (const char *str) +{ +static int done = false; +int i,j; + +if (done) +return ; + + done = true; + +printk (KERN_WARNING "ERROR: %s\n\n" , str); + +for (i =0 ; i < nr_node_ids; i++) { +printk (KERN_WARNING " " ); +for (j =0 ; j < nr_node_ids; j++) +printk (KERN_CONT "%02d " ,node_distance (i,j)); +printk (KERN_CONT "\n" ); + } +printk (KERN_WARNING "\n" ); +} + +static bool find_numa_distance (int distance) +{ +int i; + +if (distance ==node_distance (0 ,0 )) +return true; + +for (i =0 ; i < sched_domains_numa_levels; i++) { +if (sched_domains_numa_distance[i] == distance) +return true; + } + +return false; +} +static void sched_init_numa (void ) {int next_distance, curr_distance =node_distance (0 ,0 );
@@ -6445,7 +6489,6 @@ static void sched_init_numa(void)int level =0 ;int i, j, k; - sched_domains_numa_scale = curr_distance; sched_domains_numa_distance =kzalloc (sizeof (int ) * nr_node_ids,GFP_KERNEL );if (!sched_domains_numa_distance)return ;
@@ -6456,23 +6499,41 @@ static void sched_init_numa(void)* * Assumes node_distance(0,j) includes all distances in * node_distance(i,j) in order to avoid cubic time. -* -* XXX: could be optimized to O(n log n) by using sort() */ next_distance = curr_distance;for (i =0 ; i < nr_node_ids; i++) {for (j =0 ; j < nr_node_ids; j++) { -int distance =node_distance (0 , j); -if (distance > curr_distance && - (distance < next_distance || - next_distance == curr_distance)) - next_distance = distance; +for (k =0 ; k < nr_node_ids; k++) { +int distance =node_distance (i, k); + +if (distance > curr_distance && + (distance < next_distance || + next_distance == curr_distance)) + next_distance = distance; + +/* +* While not a strong assumption it would be nice to know +* about cases where if node A is connected to B, B is not +* equally connected to A. +*/ +if (sched_debug () &&node_distance (k, i) != distance) +sched_numa_warn ("Node-distance not symmetric" ); + +if (sched_debug () && i && !find_numa_distance (distance)) +sched_numa_warn ("Node-0 not representative" ); + } +if (next_distance != curr_distance) { + sched_domains_numa_distance[level++] = next_distance; + sched_domains_numa_levels = level; + curr_distance = next_distance; + }else break ; } -if (next_distance != curr_distance) { - sched_domains_numa_distance[level++] = next_distance; - sched_domains_numa_levels = level; - curr_distance = next_distance; - }else break ; + +/* +* In case of sched_debug() we verify the above assumption. +*/ +if (!sched_debug ()) +break ; }/* * 'level' contains the number of unique distances, excluding the