Provide function to call given function on any cpu from a given cpu mask while providing own csd structure.
Signed-off-by: Jan Kara <j...@suse.cz> --- include/linux/smp.h | 9 +++++++ kernel/smp.c | 67 +++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/include/linux/smp.h b/include/linux/smp.h index 1e8c72100eda..37aa794a93ce 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -100,6 +100,8 @@ void smp_call_function_many(const struct cpumask *mask, int smp_call_function_any(const struct cpumask *mask, smp_call_func_t func, void *info, int wait); +int __smp_call_function_any(const struct cpumask *mask, + struct call_single_data *csd, int wait); void kick_all_cpus_sync(void); @@ -149,6 +151,13 @@ smp_call_function_any(const struct cpumask *mask, smp_call_func_t func, return smp_call_function_single(0, func, info, wait); } +static inline int +__smp_call_function_any(const struct cpumask *mask, + struct call_single_data *csd, int wait) +{ + return __smp_call_function_single(0, csd, wait); +} + static inline void kick_all_cpus_sync(void) { } #endif /* !SMP */ diff --git a/kernel/smp.c b/kernel/smp.c index 2efcfa1d11ee..4c44554ff5b6 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -238,6 +238,27 @@ int smp_call_function_single(int cpu, smp_call_func_t func, void *info, } EXPORT_SYMBOL(smp_call_function_single); +static unsigned int pick_any_cpu(const struct cpumask *mask) +{ + unsigned int cpu = smp_processor_id(); + const struct cpumask *nodemask; + + /* Try for same CPU (cheapest) */ + if (cpumask_test_cpu(cpu, mask)) + return cpu; + + /* Try for same node. */ + nodemask = cpumask_of_node(cpu_to_node(cpu)); + for (cpu = cpumask_first_and(nodemask, mask); cpu < nr_cpu_ids; + cpu = cpumask_next_and(cpu, nodemask, mask)) { + if (cpu_online(cpu)) + return cpu; + } + + /* Any online will do */ + return cpumask_any_and(mask, cpu_online_mask); +} + /* * smp_call_function_any - Run a function on any of the given cpus * @mask: The mask of cpus it can run on. @@ -256,27 +277,13 @@ int smp_call_function_any(const struct cpumask *mask, smp_call_func_t func, void *info, int wait) { unsigned int cpu; - const struct cpumask *nodemask; int ret; - /* Try for same CPU (cheapest) */ - cpu = get_cpu(); - if (cpumask_test_cpu(cpu, mask)) - goto call; - - /* Try for same node. */ - nodemask = cpumask_of_node(cpu_to_node(cpu)); - for (cpu = cpumask_first_and(nodemask, mask); cpu < nr_cpu_ids; - cpu = cpumask_next_and(cpu, nodemask, mask)) { - if (cpu_online(cpu)) - goto call; - } - - /* Any online will do: smp_call_function_single handles nr_cpu_ids. */ - cpu = cpumask_any_and(mask, cpu_online_mask); -call: + preempt_disable(); + cpu = pick_any_cpu(mask); + /* smp_call_function_single handles nr_cpu_ids. */ ret = smp_call_function_single(cpu, func, info, wait); - put_cpu(); + preempt_enable(); return ret; } EXPORT_SYMBOL_GPL(smp_call_function_any); @@ -322,6 +329,30 @@ int __smp_call_function_single(int cpu, struct call_single_data *csd, int wait) } EXPORT_SYMBOL_GPL(__smp_call_function_single); +/* + * __smp_call_function_any - Run a function on any of the given cpus + * @mask: The mask of cpus it can run on. + * @csd: Pre-allocated and setup data structure + * @wait: If true, wait until function has completed. + * + * Like smp_call_function_any() but allow caller to pass in a pre-allocated + * data structure. + */ +int __smp_call_function_any(const struct cpumask *mask, + struct call_single_data *csd, int wait) +{ + unsigned int cpu; + int ret; + + preempt_disable(); + cpu = pick_any_cpu(mask); + /* smp_call_function_single handles nr_cpu_ids. */ + ret = __smp_call_function_single(cpu, csd, wait); + preempt_enable(); + return ret; +} +EXPORT_SYMBOL_GPL(__smp_call_function_any); + /** * smp_call_function_many(): Run a function on a set of other CPUs. * @mask: The set of cpus to run on (only runs on online subset). -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/