History

cpu_stop: add dummy implementation for UP

When !CONFIG_SMP, cpu_stop functions weren't defined at all which could lead to build failures if UP code uses cpu_stop facility. Add dummy cpu_stop implementation for UP. The waiting variants execute the work function directly with preempt disabled and stop_one_cpu_nowait() schedules a workqueue work. Makefile and ifdefs around stop_machine implementation are updated to accomodate CONFIG_SMP && !CONFIG_STOP_MACHINE case.

Tejun Heo committed 16 years ago

Commit bbf1bb31 parent fc390cd3 files · +68 −7Browse files

Unified · Split

3 files
  1. include/linux/stop_machine.h +63 −6
  2. kernel/Makefile +1 −1
  3. kernel/stop_machine.c +4 −0
include/linux/stop_machine.h+63−6
@@ -6,8 +6,6 @@ · 5 unmodified lines
66 #include <linux/list.h>
77 #include <asm/system.h>
88
9−#if defined(CONFIG_STOP_MACHINE) && defined(CONFIG_SMP)
10−
119 /*
1210 * stop_cpu[s]() is simplistic per-cpu maximum priority cpu
1311 * monopolization mechanism. The caller can specify a non-sleeping
@@ -18,9 +16,10 @@ · 4 unmodified lines
1816 * up and requests are guaranteed to be served as long as the target
1917 * cpus are online.
2018 */
21−
2219 typedef int (*cpu_stop_fn_t)(void *arg);
2320
21+#ifdef CONFIG_SMP
22+
2423 struct cpu_stop_work {
2524 struct list_head list; /* cpu_stopper->works */
2625 cpu_stop_fn_t fn;
@@ -34,12 +33,70 @@ void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg, · 7 unmodified lines
3433 int stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg);
3534 int try_stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg);
3635
36+#else /* CONFIG_SMP */
37+
38+#include <linux/workqueue.h>
39+
40+struct cpu_stop_work {
41+ struct work_struct work;
42+ cpu_stop_fn_t fn;
43+ void *arg;
44+};
45+
46+static inline int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg)
47+{
48+ int ret = -ENOENT;
49+ preempt_disable();
50+ if (cpu == smp_processor_id())
51+ ret = fn(arg);
52+ preempt_enable();
53+ return ret;
54+}
55+
56+static void stop_one_cpu_nowait_workfn(struct work_struct *work)
57+{
58+ struct cpu_stop_work *stwork =
59+ container_of(work, struct cpu_stop_work, work);
60+ preempt_disable();
61+ stwork->fn(stwork->arg);
62+ preempt_enable();
63+}
64+
65+static inline void stop_one_cpu_nowait(unsigned int cpu,
66+ cpu_stop_fn_t fn, void *arg,
67+ struct cpu_stop_work *work_buf)
68+{
69+ if (cpu == smp_processor_id()) {
70+ INIT_WORK(&work_buf->work, stop_one_cpu_nowait_workfn);
71+ work_buf->fn = fn;
72+ work_buf->arg = arg;
73+ schedule_work(&work_buf->work);
74+ }
75+}
76+
77+static inline int stop_cpus(const struct cpumask *cpumask,
78+ cpu_stop_fn_t fn, void *arg)
79+{
80+ if (cpumask_test_cpu(raw_smp_processor_id(), cpumask))
81+ return stop_one_cpu(raw_smp_processor_id(), fn, arg);
82+ return -ENOENT;
83+}
84+
85+static inline int try_stop_cpus(const struct cpumask *cpumask,
86+ cpu_stop_fn_t fn, void *arg)
87+{
88+ return stop_cpus(cpumask, fn, arg);
89+}
90+
91+#endif /* CONFIG_SMP */
92+
3793 /*
3894 * stop_machine "Bogolock": stop the entire machine, disable
3995 * interrupts. This is a very heavy lock, which is equivalent to
4096 * grabbing every spinlock (and more). So the "read" side to such a
4197 * lock is anything which disables preeempt.
4298 */
99+#if defined(CONFIG_STOP_MACHINE) && defined(CONFIG_SMP)
43100
44101 /**
45102 * stop_machine: freeze the machine on all CPUs and run this function
@@ -67,7 +124,7 @@ int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus); · 21 unmodified lines
67124 */
68125 int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus);
69126
70−#else
127+#else /* CONFIG_STOP_MACHINE && CONFIG_SMP */
71128
72129 static inline int stop_machine(int (*fn)(void *), void *data,
73130 const struct cpumask *cpus)
@@ -79,5 +136,5 @@ static inline int stop_machine(int (*fn)(void *), void *data, · 5 unmodified lines
79136 return ret;
80137 }
81138
82−#endif /* CONFIG_SMP */
83−#endif /* _LINUX_STOP_MACHINE */
139+#endif /* CONFIG_STOP_MACHINE && CONFIG_SMP */
140+#endif /* _LINUX_STOP_MACHINE */
kernel/Makefile+1−1
@@ -68,7 +68,7 @@ obj-$(CONFIG_USER_NS) += user_namespace.o · 67 unmodified lines
6868 obj-$(CONFIG_PID_NS) += pid_namespace.o
6969 obj-$(CONFIG_IKCONFIG) += configs.o
7070 obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o
71−obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
71+obj-$(CONFIG_SMP) += stop_machine.o
7272 obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o
7373 obj-$(CONFIG_AUDIT) += audit.o auditfilter.o audit_watch.o
7474 obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
kernel/stop_machine.c+4−0
@@ -375,6 +375,8 @@ static int __init cpu_stop_init(void) · 374 unmodified lines
375375 }
376376 early_initcall(cpu_stop_init);
377377
378+#ifdef CONFIG_STOP_MACHINE
379+
378380 /* This controls the threads on each CPU. */
379381 enum stopmachine_state {
380382 /* Dummy starting state for thread. */
@@ -477,3 +479,5 @@ int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus) · 96 unmodified lines
477479 return ret;
478480 }
479481 EXPORT_SYMBOL_GPL(stop_machine);
482+
483+#endif /* CONFIG_STOP_MACHINE */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t