aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cpu.c
diff options
context:
space:
mode:
authorAshok Raj <ashok.raj@intel.com>2005-11-09 00:34:24 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-09 10:55:50 -0500
commit90d45d17f3e68608ac7ba8fc3d7acce022a19c8e (patch)
tree615b2f21c3e02e0ec901febd180014fed64a6a01 /kernel/cpu.c
parent330d57fb98a916fa8e1363846540dd420e99499a (diff)
[PATCH] cpu hotplug: fix locking in cpufreq drivers
When calling target drivers to set frequency, we take cpucontrol lock. When we modified the code to accomodate CPU hotplug, there was an attempt to take a double lock of cpucontrol leading to a deadlock. Since the current thread context is already holding the cpucontrol lock, we dont need to make another attempt to acquire it. Now we leave a trace in current->flags indicating current thread already is under cpucontrol lock held, so we dont attempt to do this another time. Thanks to Andrew Morton for the beating:-) From: Brice Goglin <Brice.Goglin@ens-lyon.org> Build fix (akpm: this patch is still unpleasant. Ashok continues to look for a cleaner solution, doesn't he? ;)) Signed-off-by: Ashok Raj <ashok.raj@intel.com> Signed-off-by: Brice Goglin <Brice.Goglin@ens-lyon.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel/cpu.c')
-rw-r--r--kernel/cpu.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 3619e939182e..d61ba88f34e5 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -21,6 +21,24 @@ EXPORT_SYMBOL_GPL(cpucontrol);
21 21
22static struct notifier_block *cpu_chain; 22static struct notifier_block *cpu_chain;
23 23
24/*
25 * Used to check by callers if they need to acquire the cpucontrol
26 * or not to protect a cpu from being removed. Its sometimes required to
27 * call these functions both for normal operations, and in response to
28 * a cpu being added/removed. If the context of the call is in the same
29 * thread context as a CPU hotplug thread, we dont need to take the lock
30 * since its already protected
31 * check drivers/cpufreq/cpufreq.c for its usage - Ashok Raj
32 */
33
34int current_in_cpu_hotplug(void)
35{
36 return (current->flags & PF_HOTPLUG_CPU);
37}
38
39EXPORT_SYMBOL_GPL(current_in_cpu_hotplug);
40
41
24/* Need to know about CPUs going up/down? */ 42/* Need to know about CPUs going up/down? */
25int register_cpu_notifier(struct notifier_block *nb) 43int register_cpu_notifier(struct notifier_block *nb)
26{ 44{
@@ -94,6 +112,13 @@ int cpu_down(unsigned int cpu)
94 goto out; 112 goto out;
95 } 113 }
96 114
115 /*
116 * Leave a trace in current->flags indicating we are already in
117 * process of performing CPU hotplug. Callers can check if cpucontrol
118 * is already acquired by current thread, and if so not cause
119 * a dead lock by not acquiring the lock
120 */
121 current->flags |= PF_HOTPLUG_CPU;
97 err = notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE, 122 err = notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE,
98 (void *)(long)cpu); 123 (void *)(long)cpu);
99 if (err == NOTIFY_BAD) { 124 if (err == NOTIFY_BAD) {
@@ -146,6 +171,7 @@ out_thread:
146out_allowed: 171out_allowed:
147 set_cpus_allowed(current, old_allowed); 172 set_cpus_allowed(current, old_allowed);
148out: 173out:
174 current->flags &= ~PF_HOTPLUG_CPU;
149 unlock_cpu_hotplug(); 175 unlock_cpu_hotplug();
150 return err; 176 return err;
151} 177}
@@ -163,6 +189,12 @@ int __devinit cpu_up(unsigned int cpu)
163 ret = -EINVAL; 189 ret = -EINVAL;
164 goto out; 190 goto out;
165 } 191 }
192
193 /*
194 * Leave a trace in current->flags indicating we are already in
195 * process of performing CPU hotplug.
196 */
197 current->flags |= PF_HOTPLUG_CPU;
166 ret = notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu); 198 ret = notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu);
167 if (ret == NOTIFY_BAD) { 199 if (ret == NOTIFY_BAD) {
168 printk("%s: attempt to bring up CPU %u failed\n", 200 printk("%s: attempt to bring up CPU %u failed\n",
@@ -185,6 +217,7 @@ out_notify:
185 if (ret != 0) 217 if (ret != 0)
186 notifier_call_chain(&cpu_chain, CPU_UP_CANCELED, hcpu); 218 notifier_call_chain(&cpu_chain, CPU_UP_CANCELED, hcpu);
187out: 219out:
220 current->flags &= ~PF_HOTPLUG_CPU;
188 up(&cpucontrol); 221 up(&cpucontrol);
189 return ret; 222 return ret;
190} 223}