As in commit f21afc25f9ed ("smp.h: Use local_irq_{save,restore}() in !SMP version of on_each_cpu()"), we don't want to enable irqs if they are not already enabled. There are currently no known problematical callers of these functions, but since it is a known failure pattern, we preemptively fix them. Since they are not trivial functions, make them non-inline by moving them to up.c. This also makes it so we don't have to fix #include dependancies for preempt_{disable,enable}.
Showing the changes to kernel (1 of 2 files). Show all
Unified · Split
| @@ -19,3 +19,42 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, · 18 unmodified lines | ||
| 19 | 19 | return 0; |
| 20 | 20 | } |
| 21 | 21 | EXPORT_SYMBOL(smp_call_function_single); |
| 22 | + | |
| 23 | +/* | |
| 24 | + * Note we still need to test the mask even for UP | |
| 25 | + * because we actually can get an empty mask from | |
| 26 | + * code that on SMP might call us without the local | |
| 27 | + * CPU in the mask. | |
| 28 | + */ | |
| 29 | +void on_each_cpu_mask(const struct cpumask *mask, | |
| 30 | + smp_call_func_t func, void *info, bool wait) | |
| 31 | +{ | |
| 32 | + unsigned long flags; | |
| 33 | + | |
| 34 | + if (cpumask_test_cpu(0, mask)) { | |
| 35 | + local_irq_save(flags); | |
| 36 | + func(info); | |
| 37 | + local_irq_restore(flags); | |
| 38 | + } | |
| 39 | +} | |
| 40 | +EXPORT_SYMBOL(on_each_cpu_mask); | |
| 41 | + | |
| 42 | +/* | |
| 43 | + * Preemption is disabled here to make sure the cond_func is called under the | |
| 44 | + * same condtions in UP and SMP. | |
| 45 | + */ | |
| 46 | +void on_each_cpu_cond(bool (*cond_func)(int cpu, void *info), | |
| 47 | + smp_call_func_t func, void *info, bool wait, | |
| 48 | + gfp_t gfp_flags) | |
| 49 | +{ | |
| 50 | + unsigned long flags; | |
| 51 | + | |
| 52 | + preempt_disable(); | |
| 53 | + if (cond_func(0, info)) { | |
| 54 | + local_irq_save(flags); | |
| 55 | + func(info); | |
| 56 | + local_irq_restore(flags); | |
| 57 | + } | |
| 58 | + preempt_enable(); | |
| 59 | +} | |
| 60 | +EXPORT_SYMBOL(on_each_cpu_cond); | |