[PATCH 1/3] stop_machine: short exit path for if we cannot createenough threads

From: Hidetoshi Seto
Date: Mon Apr 28 2008 - 21:29:54 EST


stop_machine_run() invokes kthread 'kstopmachine' and the kthread
creates its children for every other cpus.

The current implementation migrates the child thread to its target
cpu as soon as it is created. It means that the children always
bother some of other cpus even if we cannot create enough threads.

This patch enable us to skip the migration of children if we
cannot have enough threads.

Signed-off-by: Hidetoshi Seto <seto.hidetoshi@xxxxxxxxxxxxxx>
---
kernel/stop_machine.c | 29 +++++++++++++++++++----------
1 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 0101aee..5331ee5 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -20,6 +20,7 @@
/* Thread to stop each CPU in user context. */
enum stopmachine_state {
STOPMACHINE_WAIT,
+ STOPMACHINE_DEPLOY,
STOPMACHINE_PREPARE,
STOPMACHINE_DISABLE_IRQ,
STOPMACHINE_EXIT,
@@ -34,9 +35,16 @@ static int stopmachine(void *cpu)
int irqs_disabled = 0;
int prepared = 0;

+ /* Wait sisters */
+ while (stopmachine_state == STOPMACHINE_WAIT)
+ yield();
+ /* short path for cancel */
+ if (stopmachine_state == STOPMACHINE_EXIT)
+ goto exit;
+
set_cpus_allowed_ptr(current, &cpumask_of_cpu((int)(long)cpu));

- /* Ack: we are alive */
+ /* Ack: we arrived */
smp_mb(); /* Theoretically the ack = 0 might not be on this CPU yet. */
atomic_inc(&stopmachine_thread_ack);

@@ -65,7 +73,7 @@ static int stopmachine(void *cpu)
else
cpu_relax();
}
-
+exit:
/* Ack: we are exiting. */
smp_mb(); /* Must read state first. */
atomic_inc(&stopmachine_thread_ack);
@@ -101,20 +109,15 @@ static int stop_machine(void)
continue;
ret = kernel_thread(stopmachine, (void *)(long)i,CLONE_KERNEL);
if (ret < 0)
- break;
+ goto exit_threads;
stopmachine_num_threads++;
}

- /* Wait for them all to come to life. */
+ /* Wait for them all to come to life on the target. */
+ stopmachine_state = STOPMACHINE_DEPLOY;
while (atomic_read(&stopmachine_thread_ack) != stopmachine_num_threads)
yield();

- /* If some failed, kill them all. */
- if (ret < 0) {
- stopmachine_set_state(STOPMACHINE_EXIT);
- return ret;
- }
-
/* Now they are all started, make them hold the CPUs, ready. */
preempt_disable();
stopmachine_set_state(STOPMACHINE_PREPARE);
@@ -125,6 +128,12 @@ static int stop_machine(void)
stopmachine_set_state(STOPMACHINE_DISABLE_IRQ);

return 0;
+
+exit_threads:
+ /* Wait for them all to exit, since stop is canceled */
+ stopmachine_set_state(STOPMACHINE_EXIT);
+
+ return ret;
}

static void restart_machine(void)

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/