History

smp: quit unconditionally enabling irq in on_each_cpu_mask and on_each_cpu_cond

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}.

David Daney committed 13 years ago

Commit fa688201 parent c14c3382 files · +55 −46Browse files

Unified · Split

2 files
  1. include/linux/smp.h +16 −46
  2. kernel/up.c +39 −0
include/linux/smp.h+16−46
@@ -29,6 +29,22 @@ extern unsigned int total_cpus; · 28 unmodified lines
2929 int smp_call_function_single(int cpuid, smp_call_func_t func, void *info,
3030 int wait);
3131
32+/*
33+ * Call a function on processors specified by mask, which might include
34+ * the local one.
35+ */
36+void on_each_cpu_mask(const struct cpumask *mask, smp_call_func_t func,
37+ void *info, bool wait);
38+
39+/*
40+ * Call a function on each processor for which the supplied function
41+ * cond_func returns a positive value. This may include the local
42+ * processor.
43+ */
44+void on_each_cpu_cond(bool (*cond_func)(int cpu, void *info),
45+ smp_call_func_t func, void *info, bool wait,
46+ gfp_t gfp_flags);
47+
3248 #ifdef CONFIG_SMP
3349
3450 #include <linux/preempt.h>
@@ -100,22 +116,6 @@ static inline void call_function_init(void) { } · 65 unmodified lines
100116 */
101117 int on_each_cpu(smp_call_func_t func, void *info, int wait);
102118
103−/*
104− * Call a function on processors specified by mask, which might include
105− * the local one.
106− */
107−void on_each_cpu_mask(const struct cpumask *mask, smp_call_func_t func,
108− void *info, bool wait);
109−
110−/*
111− * Call a function on each processor for which the supplied function
112− * cond_func returns a positive value. This may include the local
113− * processor.
114− */
115−void on_each_cpu_cond(bool (*cond_func)(int cpu, void *info),
116− smp_call_func_t func, void *info, bool wait,
117− gfp_t gfp_flags);
118−
119119 /*
120120 * Mark the boot cpu "online" so that it can call console drivers in
121121 * printk() and can access its per-cpu storage.
@@ -151,36 +151,6 @@ static inline int on_each_cpu(smp_call_func_t func, void *info, int wait) · 29 unmodified lines
151151 return 0;
152152 }
153153
154−/*
155− * Note we still need to test the mask even for UP
156− * because we actually can get an empty mask from
157− * code that on SMP might call us without the local
158− * CPU in the mask.
159− */
160−#define on_each_cpu_mask(mask, func, info, wait) \
161− do { \
162− if (cpumask_test_cpu(0, (mask))) { \
163− local_irq_disable(); \
164− (func)(info); \
165− local_irq_enable(); \
166− } \
167− } while (0)
168−/*
169− * Preemption is disabled here to make sure the cond_func is called under the
170− * same condtions in UP and SMP.
171− */
172−#define on_each_cpu_cond(cond_func, func, info, wait, gfp_flags)\
173− do { \
174− void *__info = (info); \
175− preempt_disable(); \
176− if ((cond_func)(0, __info)) { \
177− local_irq_disable(); \
178− (func)(__info); \
179− local_irq_enable(); \
180− } \
181− preempt_enable(); \
182− } while (0)
183−
184154 static inline void smp_send_reschedule(int cpu) { }
185155 #define smp_prepare_boot_cpu() do {} while (0)
186156 #define smp_call_function_many(mask, func, info, wait) \
kernel/up.c+39−0
@@ -19,3 +19,42 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, · 18 unmodified lines
1919 return 0;
2020 }
2121 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);