kernel core: add smp_call_function_any()
PATCH 2/9 kernel core: add smp_call_function_any()
From: Rusty Russell <[email protected]>
Andrew points out that acpi-cpufreq uses cpumask_any, when it really would prefer to use the same CPU if possible (to avoid an IPI). In general, this seems a good idea to offer.
Signed-off-by Rusty Russell <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Venkatesh Pallipadi <[email protected]>
Cc Len Brown <[email protected]>
Cc Zhao Yakui <[email protected]>
Cc Dave Jones <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Mike Galbraith <[email protected]>
Cc "Zhang, Yanmin" <[email protected]>
Cc Jaswinder Singh Rajput <[email protected]>
Signed-off-by Andrew Morton <[email protected]>
---
include/linux/smp.h | 3 +++ kernel/smp.c | 40 ++++++++++++++++++++++++++++++++++++++++ kernel/up.c | 12 ++++++++++++ 3 files changed, 55 insertions(+)
include/linux/smp.h renamed from include/linux/smp.h~kernel-core-add-smp_call_function_any +3 -0
@@ -27,6 +27,9 @@ extern unsigned int total_cpus;int smp_call_function_single (int cpuid,void (*func) (void *info),void *info,int wait); +int smp_call_function_any (const struct cpumask *mask, +void (*func)(void *info),void *info,int wait); +#ifdef CONFIG_SMP #include <linux/preempt.h>
kernel/smp.c renamed from kernel/smp.c~kernel-core-add-smp_call_function_any +40 -0
@@ -315,6 +315,46 @@ int smp_call_function_single(int cpu, vo }EXPORT_SYMBOL (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. +* @func: The function to run. This must be fast and non-blocking. +* @info: An arbitrary pointer to pass to the function. +* @wait: If true, wait until function has completed. +* +* Returns 0 on success, else a negative status code (if no cpus were online). +* Note that @wait will be implicitly turned on in case of allocation failures, +* since we fall back to on-stack allocation. +*/ +int smp_call_function_any (const struct cpumask *mask, +void (*func)(void *info),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); +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: + ret =smp_call_function_single (cpu, func, info, wait); +put_cpu (); +return ret; +} +EXPORT_SYMBOL_GPL (smp_call_function_any); +/** * __smp_call_function_single(): Run a function on another CPU * @cpu: The CPU to run on.
kernel/up.c renamed from kernel/up.c~kernel-core-add-smp_call_function_any +12 -0
@@ -19,3 +19,15 @@ int smp_call_function_single(int cpu, voreturn 0 ; }EXPORT_SYMBOL (smp_call_function_single); + +int smp_call_function_any (const struct cpumask *mask, +void (*func)(void *info),void *info, +int wait) +{ +local_irq_disable (); + (func)(info); +local_irq_enable (); + +return 0 ; +} +EXPORT_SYMBOL_GPL (smp_call_function_any);
_