aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/cpu.c')
-rw-r--r--kernel/cpu.c44
1 files changed, 17 insertions, 27 deletions
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 6ba0f1ecb212..25bba73b1be3 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -14,6 +14,7 @@
14#include <linux/kthread.h> 14#include <linux/kthread.h>
15#include <linux/stop_machine.h> 15#include <linux/stop_machine.h>
16#include <linux/mutex.h> 16#include <linux/mutex.h>
17#include <linux/gfp.h>
17 18
18#ifdef CONFIG_SMP 19#ifdef CONFIG_SMP
19/* Serializes the updates to cpu_online_mask, cpu_present_mask */ 20/* Serializes the updates to cpu_online_mask, cpu_present_mask */
@@ -151,13 +152,13 @@ static inline void check_for_tasks(int cpu)
151 152
152 write_lock_irq(&tasklist_lock); 153 write_lock_irq(&tasklist_lock);
153 for_each_process(p) { 154 for_each_process(p) {
154 if (task_cpu(p) == cpu && 155 if (task_cpu(p) == cpu && p->state == TASK_RUNNING &&
155 (!cputime_eq(p->utime, cputime_zero) || 156 (!cputime_eq(p->utime, cputime_zero) ||
156 !cputime_eq(p->stime, cputime_zero))) 157 !cputime_eq(p->stime, cputime_zero)))
157 printk(KERN_WARNING "Task %s (pid = %d) is on cpu %d\ 158 printk(KERN_WARNING "Task %s (pid = %d) is on cpu %d "
158 (state = %ld, flags = %x) \n", 159 "(state = %ld, flags = %x)\n",
159 p->comm, task_pid_nr(p), cpu, 160 p->comm, task_pid_nr(p), cpu,
160 p->state, p->flags); 161 p->state, p->flags);
161 } 162 }
162 write_unlock_irq(&tasklist_lock); 163 write_unlock_irq(&tasklist_lock);
163} 164}
@@ -209,9 +210,12 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
209 return -ENOMEM; 210 return -ENOMEM;
210 211
211 cpu_hotplug_begin(); 212 cpu_hotplug_begin();
213 set_cpu_active(cpu, false);
212 err = __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE | mod, 214 err = __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE | mod,
213 hcpu, -1, &nr_calls); 215 hcpu, -1, &nr_calls);
214 if (err == NOTIFY_BAD) { 216 if (err == NOTIFY_BAD) {
217 set_cpu_active(cpu, true);
218
215 nr_calls--; 219 nr_calls--;
216 __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod, 220 __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod,
217 hcpu, nr_calls, NULL); 221 hcpu, nr_calls, NULL);
@@ -223,11 +227,11 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
223 227
224 /* Ensure that we are not runnable on dying cpu */ 228 /* Ensure that we are not runnable on dying cpu */
225 cpumask_copy(old_allowed, &current->cpus_allowed); 229 cpumask_copy(old_allowed, &current->cpus_allowed);
226 set_cpus_allowed_ptr(current, 230 set_cpus_allowed_ptr(current, cpu_active_mask);
227 cpumask_of(cpumask_any_but(cpu_online_mask, cpu)));
228 231
229 err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu)); 232 err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu));
230 if (err) { 233 if (err) {
234 set_cpu_active(cpu, true);
231 /* CPU didn't die: tell everyone. Can't complain. */ 235 /* CPU didn't die: tell everyone. Can't complain. */
232 if (raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod, 236 if (raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod,
233 hcpu) == NOTIFY_BAD) 237 hcpu) == NOTIFY_BAD)
@@ -278,23 +282,8 @@ int __ref cpu_down(unsigned int cpu)
278 goto out; 282 goto out;
279 } 283 }
280 284
281 set_cpu_active(cpu, false);
282
283 /*
284 * Make sure the all cpus did the reschedule and are not
285 * using stale version of the cpu_active_mask.
286 * This is not strictly necessary becuase stop_machine()
287 * that we run down the line already provides the required
288 * synchronization. But it's really a side effect and we do not
289 * want to depend on the innards of the stop_machine here.
290 */
291 synchronize_sched();
292
293 err = _cpu_down(cpu, 0); 285 err = _cpu_down(cpu, 0);
294 286
295 if (cpu_online(cpu))
296 set_cpu_active(cpu, true);
297
298out: 287out:
299 cpu_maps_update_done(); 288 cpu_maps_update_done();
300 stop_machine_destroy(); 289 stop_machine_destroy();
@@ -350,7 +339,7 @@ int __cpuinit cpu_up(unsigned int cpu)
350 if (!cpu_possible(cpu)) { 339 if (!cpu_possible(cpu)) {
351 printk(KERN_ERR "can't online cpu %d because it is not " 340 printk(KERN_ERR "can't online cpu %d because it is not "
352 "configured as may-hotadd at boot time\n", cpu); 341 "configured as may-hotadd at boot time\n", cpu);
353#if defined(CONFIG_IA64) || defined(CONFIG_X86_64) 342#if defined(CONFIG_IA64)
354 printk(KERN_ERR "please check additional_cpus= boot " 343 printk(KERN_ERR "please check additional_cpus= boot "
355 "parameter\n"); 344 "parameter\n");
356#endif 345#endif
@@ -383,19 +372,20 @@ int disable_nonboot_cpus(void)
383 return error; 372 return error;
384 cpu_maps_update_begin(); 373 cpu_maps_update_begin();
385 first_cpu = cpumask_first(cpu_online_mask); 374 first_cpu = cpumask_first(cpu_online_mask);
386 /* We take down all of the non-boot CPUs in one shot to avoid races 375 /*
376 * We take down all of the non-boot CPUs in one shot to avoid races
387 * with the userspace trying to use the CPU hotplug at the same time 377 * with the userspace trying to use the CPU hotplug at the same time
388 */ 378 */
389 cpumask_clear(frozen_cpus); 379 cpumask_clear(frozen_cpus);
380
390 printk("Disabling non-boot CPUs ...\n"); 381 printk("Disabling non-boot CPUs ...\n");
391 for_each_online_cpu(cpu) { 382 for_each_online_cpu(cpu) {
392 if (cpu == first_cpu) 383 if (cpu == first_cpu)
393 continue; 384 continue;
394 error = _cpu_down(cpu, 1); 385 error = _cpu_down(cpu, 1);
395 if (!error) { 386 if (!error)
396 cpumask_set_cpu(cpu, frozen_cpus); 387 cpumask_set_cpu(cpu, frozen_cpus);
397 printk("CPU%d is down\n", cpu); 388 else {
398 } else {
399 printk(KERN_ERR "Error taking CPU%d down: %d\n", 389 printk(KERN_ERR "Error taking CPU%d down: %d\n",
400 cpu, error); 390 cpu, error);
401 break; 391 break;