workqueue: add wq_numa_tbl_len and wq_numa_possible_cpumask[]
Unbound workqueues are going to be NUMA-affine.  Add wq_numa_tbl_len
and wq_numa_possible_cpumask[] in preparation.  The former is the
highest NUMA node ID + 1 and the latter is masks of possibles CPUs for
each NUMA node.
This patch only introduces these.  Future patches will make use of
them.
v2: NUMA initialization move into wq_numa_init().  Also, the possible
    cpumask array is not created if there aren't multiple nodes on the
    system.  wq_numa_enabled bool added.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Lai Jiangshan <laijs@cn.fujitsu.com>
	
	
This commit is contained in:
		
					parent
					
						
							
								a892cacc7f
							
						
					
				
			
			
				commit
				
					
						bce903809a
					
				
			
		
					 1 changed files with 46 additions and 0 deletions
				
			
		|  | @ -44,6 +44,7 @@ | ||||||
| #include <linux/jhash.h> | #include <linux/jhash.h> | ||||||
| #include <linux/hashtable.h> | #include <linux/hashtable.h> | ||||||
| #include <linux/rculist.h> | #include <linux/rculist.h> | ||||||
|  | #include <linux/nodemask.h> | ||||||
| 
 | 
 | ||||||
| #include "workqueue_internal.h" | #include "workqueue_internal.h" | ||||||
| 
 | 
 | ||||||
|  | @ -253,6 +254,12 @@ struct workqueue_struct { | ||||||
| 
 | 
 | ||||||
| static struct kmem_cache *pwq_cache; | static struct kmem_cache *pwq_cache; | ||||||
| 
 | 
 | ||||||
|  | static int wq_numa_tbl_len;		/* highest possible NUMA node id + 1 */ | ||||||
|  | static cpumask_var_t *wq_numa_possible_cpumask; | ||||||
|  | 					/* possible CPUs of each node */ | ||||||
|  | 
 | ||||||
|  | static bool wq_numa_enabled;		/* unbound NUMA affinity enabled */ | ||||||
|  | 
 | ||||||
| static DEFINE_MUTEX(wq_pool_mutex);	/* protects pools and workqueues list */ | static DEFINE_MUTEX(wq_pool_mutex);	/* protects pools and workqueues list */ | ||||||
| static DEFINE_SPINLOCK(wq_mayday_lock);	/* protects wq->maydays list */ | static DEFINE_SPINLOCK(wq_mayday_lock);	/* protects wq->maydays list */ | ||||||
| 
 | 
 | ||||||
|  | @ -4407,6 +4414,43 @@ out_unlock: | ||||||
| } | } | ||||||
| #endif /* CONFIG_FREEZER */ | #endif /* CONFIG_FREEZER */ | ||||||
| 
 | 
 | ||||||
|  | static void __init wq_numa_init(void) | ||||||
|  | { | ||||||
|  | 	cpumask_var_t *tbl; | ||||||
|  | 	int node, cpu; | ||||||
|  | 
 | ||||||
|  | 	/* determine NUMA pwq table len - highest node id + 1 */ | ||||||
|  | 	for_each_node(node) | ||||||
|  | 		wq_numa_tbl_len = max(wq_numa_tbl_len, node + 1); | ||||||
|  | 
 | ||||||
|  | 	if (num_possible_nodes() <= 1) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * We want masks of possible CPUs of each node which isn't readily | ||||||
|  | 	 * available.  Build one from cpu_to_node() which should have been | ||||||
|  | 	 * fully initialized by now. | ||||||
|  | 	 */ | ||||||
|  | 	tbl = kzalloc(wq_numa_tbl_len * sizeof(tbl[0]), GFP_KERNEL); | ||||||
|  | 	BUG_ON(!tbl); | ||||||
|  | 
 | ||||||
|  | 	for_each_node(node) | ||||||
|  | 		BUG_ON(!alloc_cpumask_var_node(&tbl[node], GFP_KERNEL, node)); | ||||||
|  | 
 | ||||||
|  | 	for_each_possible_cpu(cpu) { | ||||||
|  | 		node = cpu_to_node(cpu); | ||||||
|  | 		if (WARN_ON(node == NUMA_NO_NODE)) { | ||||||
|  | 			pr_warn("workqueue: NUMA node mapping not available for cpu%d, disabling NUMA support\n", cpu); | ||||||
|  | 			/* happens iff arch is bonkers, let's just proceed */ | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		cpumask_set_cpu(cpu, tbl[node]); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	wq_numa_possible_cpumask = tbl; | ||||||
|  | 	wq_numa_enabled = true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int __init init_workqueues(void) | static int __init init_workqueues(void) | ||||||
| { | { | ||||||
| 	int std_nice[NR_STD_WORKER_POOLS] = { 0, HIGHPRI_NICE_LEVEL }; | 	int std_nice[NR_STD_WORKER_POOLS] = { 0, HIGHPRI_NICE_LEVEL }; | ||||||
|  | @ -4423,6 +4467,8 @@ static int __init init_workqueues(void) | ||||||
| 	cpu_notifier(workqueue_cpu_up_callback, CPU_PRI_WORKQUEUE_UP); | 	cpu_notifier(workqueue_cpu_up_callback, CPU_PRI_WORKQUEUE_UP); | ||||||
| 	hotcpu_notifier(workqueue_cpu_down_callback, CPU_PRI_WORKQUEUE_DOWN); | 	hotcpu_notifier(workqueue_cpu_down_callback, CPU_PRI_WORKQUEUE_DOWN); | ||||||
| 
 | 
 | ||||||
|  | 	wq_numa_init(); | ||||||
|  | 
 | ||||||
| 	/* initialize CPU pools */ | 	/* initialize CPU pools */ | ||||||
| 	for_each_possible_cpu(cpu) { | 	for_each_possible_cpu(cpu) { | ||||||
| 		struct worker_pool *pool; | 		struct worker_pool *pool; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Tejun Heo
				Tejun Heo