linux-mips
[Top] [All Lists]

[PATCH] MIPS: move idle task creation to work queue

To: ralf@linux-mips.org, linux-mips@linux-mips.org
Subject: [PATCH] MIPS: move idle task creation to work queue
From: maksim.rayskiy@gmail.com
Date: Fri, 11 Feb 2011 19:22:26 -0800
Cc: "Maksim Rayskiy" <mrayskiy@broadcom.com>
Original-recipient: rfc822;linux-mips@linux-mips.org
Sender: linux-mips-bounce@linux-mips.org
From: Maksim Rayskiy <mrayskiy@broadcom.com>

To avoid forking usertask when creating an idle task, move fork_idle
to a work queue.
This is a small improvement to previous commit 467f0b8.

Signed-off-by: Maksim Rayskiy <mrayskiy@broadcom.com>
---

Ralf, this is per your suggestion. The code is mostly copy-pasted
from arch/x86/kernel/smpboot.c

 arch/mips/kernel/smp.c |   32 ++++++++++++++++++++++++++------
 1 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 4593916..98bd504 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -193,6 +193,21 @@ void __devinit smp_prepare_boot_cpu(void)
  */
 static struct task_struct *cpu_idle_thread[NR_CPUS];
 
+struct create_idle {
+       struct work_struct work;
+       struct task_struct *idle;
+       struct completion done;
+       int cpu;
+};
+
+static void __cpuinit do_fork_idle(struct work_struct *work)
+{
+       struct create_idle *c_idle =
+               container_of(work, struct create_idle, work);
+       c_idle->idle = fork_idle(c_idle->cpu);
+       complete(&c_idle->done);
+}
+
 int __cpuinit __cpu_up(unsigned int cpu)
 {
        struct task_struct *idle;
@@ -203,16 +218,21 @@ int __cpuinit __cpu_up(unsigned int cpu)
         * Linux can schedule processes on this slave.
         */
        if (!cpu_idle_thread[cpu]) {
-               idle = fork_idle(cpu);
-               cpu_idle_thread[cpu] = idle;
+               /* Schedule work item to avoid forking user task.
+                  Ported from x86 */
+               struct create_idle c_idle = {
+                       .cpu    = cpu,
+                       .done   = COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
+               };
+
+               INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle);
+               schedule_work(&c_idle.work);
+               wait_for_completion(&c_idle.done);
+               idle = cpu_idle_thread[cpu] = c_idle.idle;
 
                if (IS_ERR(idle))
                        panic(KERN_ERR "Fork failed for CPU %d", cpu);
 
-               if (idle->mm) {
-                       mmput(idle->mm);
-                       idle->mm = NULL;
-               }
        } else {
                idle = cpu_idle_thread[cpu];
                init_idle(idle, cpu);
-- 
1.7.3.2



<Prev in Thread] Current Thread [Next in Thread>