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 <a.p.zijlstra@chello.nl> Cc: Alex Shi <lkml.alex@gmail.com> Link: http://lkml.kernel.org/n/tip-6uc3wk5s9udxtdl9cnku0vtt@git.kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
		
							parent
							
								
									c3decf0dfb
								
							
						
					
					
						commit
						d039ac6080
					
				| @ -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 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user