Commit 86c1b9ae authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Use CPU_UP_PREPARE properly

From: Rusty Russell <rusty@rustcorp.com.au>

The cpu hotplug code actually provides two notifiers: CPU_UP_PREPARE
which preceeds the online and can fail, and CPU_ONLINE which can't.

Current usage is only done at boot, so this distinction doesn't
matter, but it's a bad example to set.  This also means that the
migration threads do not have to be higher priority than the
others, since they are ready to go before any CPU_ONLINE callbacks
are done.

This patch is experimental but fairly straight foward: I haven't been
able to test it since extracting it from the hotplug cpu code, so it's
possible I screwed something up.
parent 79caa7d5
...@@ -2806,33 +2806,39 @@ static int migration_call(struct notifier_block *nfb, unsigned long action, ...@@ -2806,33 +2806,39 @@ static int migration_call(struct notifier_block *nfb, unsigned long action,
struct task_struct *p; struct task_struct *p;
switch (action) { switch (action) {
case CPU_ONLINE: case CPU_UP_PREPARE:
p = kthread_create(migration_thread, hcpu, "migration/%d",cpu); p = kthread_create(migration_thread, hcpu, "migration/%d",cpu);
if (IS_ERR(p)) if (IS_ERR(p))
return NOTIFY_BAD; return NOTIFY_BAD;
kthread_bind(p, cpu); kthread_bind(p, cpu);
cpu_rq(cpu)->migration_thread = p; cpu_rq(cpu)->migration_thread = p;
wake_up_process(p); break;
case CPU_ONLINE:
/* Strictly unneccessary, as first user will wake it. */
wake_up_process(cpu_rq(cpu)->migration_thread);
break; break;
} }
return NOTIFY_OK; return NOTIFY_OK;
} }
/* Want this before the other threads, so they can use set_cpus_allowed. */ /*
static struct notifier_block migration_notifier = { * We want this after the other threads, so they can use set_cpus_allowed
.notifier_call = &migration_call, * from their CPU_OFFLINE callback
.priority = 10, */
static struct notifier_block __devinitdata migration_notifier = {
.notifier_call = migration_call,
.priority = -10,
}; };
__init int migration_init(void) int __init migration_init(void)
{ {
void *cpu = (void *)(long)smp_processor_id();
/* Start one for boot CPU. */ /* Start one for boot CPU. */
migration_call(&migration_notifier, CPU_ONLINE, migration_call(&migration_notifier, CPU_UP_PREPARE, cpu);
(void *)(long)smp_processor_id()); migration_call(&migration_notifier, CPU_ONLINE, cpu);
register_cpu_notifier(&migration_notifier); register_cpu_notifier(&migration_notifier);
return 0; return 0;
} }
#endif #endif
/* /*
......
...@@ -340,7 +340,10 @@ static int __devinit cpu_callback(struct notifier_block *nfb, ...@@ -340,7 +340,10 @@ static int __devinit cpu_callback(struct notifier_block *nfb,
int hotcpu = (unsigned long)hcpu; int hotcpu = (unsigned long)hcpu;
struct task_struct *p; struct task_struct *p;
if (action == CPU_ONLINE) { switch (action) {
case CPU_UP_PREPARE:
BUG_ON(per_cpu(tasklet_vec, hotcpu).list);
BUG_ON(per_cpu(tasklet_hi_vec, hotcpu).list);
p = kthread_create(ksoftirqd, hcpu, "ksoftirqd/%d", hotcpu); p = kthread_create(ksoftirqd, hcpu, "ksoftirqd/%d", hotcpu);
if (IS_ERR(p)) { if (IS_ERR(p)) {
printk("ksoftirqd for %i failed\n", hotcpu); printk("ksoftirqd for %i failed\n", hotcpu);
...@@ -348,7 +351,11 @@ static int __devinit cpu_callback(struct notifier_block *nfb, ...@@ -348,7 +351,11 @@ static int __devinit cpu_callback(struct notifier_block *nfb,
} }
per_cpu(ksoftirqd, hotcpu) = p; per_cpu(ksoftirqd, hotcpu) = p;
kthread_bind(p, hotcpu); kthread_bind(p, hotcpu);
wake_up_process(p); per_cpu(ksoftirqd, hotcpu) = p;
break;
case CPU_ONLINE:
wake_up_process(per_cpu(ksoftirqd, hotcpu));
break;
} }
return NOTIFY_OK; return NOTIFY_OK;
} }
...@@ -359,7 +366,9 @@ static struct notifier_block __devinitdata cpu_nfb = { ...@@ -359,7 +366,9 @@ static struct notifier_block __devinitdata cpu_nfb = {
__init int spawn_ksoftirqd(void) __init int spawn_ksoftirqd(void)
{ {
cpu_callback(&cpu_nfb, CPU_ONLINE, (void *)(long)smp_processor_id()); void *cpu = (void *)(long)smp_processor_id();
cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
register_cpu_notifier(&cpu_nfb); register_cpu_notifier(&cpu_nfb);
return 0; return 0;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment