diff options
author | Yuqi Jin <jinyuqi@huawei.com> | 2021-01-05 12:10:18 +1100 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2021-01-08 14:52:33 +1100 |
commit | 6783fd584e90290d6631685d5e40b1a802db81b0 (patch) | |
tree | 45b6d9fb698ec2f2d226acdbcaf4b699155b3418 | |
parent | e869a71f0257211cddd2cf53ab5ad1b7f70ee810 (diff) | |
download | linux-6783fd584e90290d6631685d5e40b1a802db81b0.tar.gz linux-6783fd584e90290d6631685d5e40b1a802db81b0.tar.xz |
lib-optimize-cpumask_local_spread-v8
1. Fix confusing comments
2. Improve the loop for choosing the nearest node.
Link: https://lkml.kernel.org/r/1609759109-62925-1-git-send-email-zhangshaokun@hisilicon.com
Signed-off-by: Yuqi Jin <jinyuqi@huawei.com>
Signed-off-by: Shaokun Zhang <zhangshaokun@hisilicon.com>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Juergen Gross <jgross@suse.com>
Cc: Paul Burton <paul.burton@mips.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Mike Rapoport <rppt@linux.ibm.com>
Cc: Anshuman Khandual <anshuman.khandual@arm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
-rw-r--r-- | include/linux/cpumask.h | 2 | ||||
-rw-r--r-- | lib/cpumask.c | 61 |
2 files changed, 32 insertions, 31 deletions
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 383684e30f12..ab0c2a39bfb4 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -189,7 +189,7 @@ static inline unsigned int cpumask_any_but(const struct cpumask *mask, return 1; } -static inline unsigned int cpumask_local_spread(unsigned int i, int node) +static inline unsigned int cpumask_local_spread(unsigned int cpu_index, int node) { return 0; } diff --git a/lib/cpumask.c b/lib/cpumask.c index fb4b704c7265..1885c314e410 100644 --- a/lib/cpumask.c +++ b/lib/cpumask.c @@ -193,80 +193,81 @@ void __init free_bootmem_cpumask_var(cpumask_var_t mask) } #endif -static int find_nearest_node(int node, bool *used) +static int find_nearest_node(int node, nodemask_t nodes) { int i, min_dist, node_id = -1; /* Choose the first unused node to compare */ - for (i = 0; i < nr_node_ids; i++) { - if (used[i] == false) { + for (i = 0; i < nr_node_ids; i++) + if (!node_isset(i, nodes)) { min_dist = node_distance(node, i); node_id = i; break; } - } /* Compare and return the nearest node */ - for (i = 0; i < nr_node_ids; i++) { - if (node_distance(node, i) < min_dist && used[i] == false) { + for (i = 0; i < nr_node_ids; i++) + if (!node_isset(i, nodes) && + node_distance(node, i) < min_dist) { min_dist = node_distance(node, i); node_id = i; } - } return node_id; } /** * cpumask_local_spread - select the i'th cpu with local numa cpu's first - * @i: index number + * @cpu_index: index number * @node: local numa_node * * This function selects an online CPU according to a numa aware policy; - * local cpus are returned first, followed by the next one which is the - * nearest unused NUMA node based on NUMA distance, then it wraps around. + * Loop through all the online CPUs on the system. Start with the CPUs on + * 'node', then fall back to CPUs on NUMA nodes which are increasingly far + * away. * - * It's not very efficient, but useful for setup. + * This function is not very efficient, especially for large 'cpu_index' + * because it loops over the same CPUs on each call and does not remember + * its state from previous calls, but it is useful for setup. */ -unsigned int cpumask_local_spread(unsigned int i, int node) +unsigned int cpumask_local_spread(unsigned int cpu_index, int node) { - static DEFINE_SPINLOCK(spread_lock); - static bool used[MAX_NUMNODES]; - unsigned long flags; - int cpu, hk_flags, j, id; + int cpu, hk_flags, j, ncpus, id; const struct cpumask *mask; + struct cpumask nmsk; + nodemask_t nodes_msk; hk_flags = HK_FLAG_DOMAIN | HK_FLAG_MANAGED_IRQ; mask = housekeeping_cpumask(hk_flags); /* Wrap: we always want a cpu. */ - i %= cpumask_weight(mask); + cpu_index %= cpumask_weight(mask); if (node == NUMA_NO_NODE) { for_each_cpu(cpu, mask) { - if (i-- == 0) + if (cpu_index-- == 0) return cpu; } } else { - spin_lock_irqsave(&spread_lock, flags); - memset(used, 0, nr_node_ids * sizeof(bool)); /* select node according to the distance from local node */ + nodes_clear(nodes_msk); for (j = 0; j < nr_node_ids; j++) { - id = find_nearest_node(node, used); + id = find_nearest_node(node, nodes_msk); if (id < 0) break; - - for_each_cpu_and(cpu, cpumask_of_node(id), mask) - if (i-- == 0) { - spin_unlock_irqrestore(&spread_lock, - flags); + cpumask_and(&nmsk, mask, cpumask_of_node(id)); + ncpus = cpumask_weight(&nmsk); + if (cpu_index >= ncpus) { + cpu_index -= ncpus; + node_set(id, nodes_msk); + continue; + } + for_each_cpu(cpu, &nmsk) + if (cpu_index-- == 0) return cpu; - } - used[id] = true; } - spin_unlock_irqrestore(&spread_lock, flags); for_each_cpu(cpu, mask) - if (i-- == 0) + if (cpu_index-- == 0) return cpu; } BUG(); |