vserver 1.9.5.x5
[linux-2.6.git] / arch / ia64 / kernel / process.c
index 56ffa1a..9129338 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/unistd.h>
 #include <linux/efi.h>
 #include <linux/interrupt.h>
+#include <linux/delay.h>
 
 #include <asm/cpu.h>
 #include <asm/delay.h>
@@ -39,6 +40,8 @@
 #include <asm/unwind.h>
 #include <asm/user.h>
 
+#include "entry.h"
+
 #ifdef CONFIG_PERFMON
 # include <asm/perfmon.h>
 #endif
 #include "sigframe.h"
 
 void (*ia64_mark_idle)(int);
+static cpumask_t cpu_idle_map;
 
+unsigned long boot_option_idle_override = 0;
+EXPORT_SYMBOL(boot_option_idle_override);
 
 void
 ia64_do_show_stack (struct unw_frame_info *info, void *arg)
@@ -185,6 +191,8 @@ default_idle (void)
        while (!need_resched())
                if (pal_halt && !pmu_active)
                        safe_halt();
+               else
+                       cpu_relax();
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -221,10 +229,28 @@ static inline void play_dead(void)
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
+
+void cpu_idle_wait(void)
+{
+        int cpu;
+        cpumask_t map;
+
+        for_each_online_cpu(cpu)
+                cpu_set(cpu, cpu_idle_map);
+
+        wmb();
+        do {
+                ssleep(1);
+                cpus_and(map, cpu_idle_map, cpu_online_map);
+        } while (!cpus_empty(map));
+}
+EXPORT_SYMBOL_GPL(cpu_idle_wait);
+
 void __attribute__((noreturn))
-cpu_idle (void *unused)
+cpu_idle (void)
 {
        void (*mark_idle)(int) = ia64_mark_idle;
+       int cpu = smp_processor_id();
 
        /* endless idle loop with no priority at all */
        while (1) {
@@ -237,17 +263,14 @@ cpu_idle (void *unused)
 
                        if (mark_idle)
                                (*mark_idle)(1);
-                       /*
-                        * Mark this as an RCU critical section so that
-                        * synchronize_kernel() in the unload path waits
-                        * for our completion.
-                        */
-                       rcu_read_lock();
+
+                       if (cpu_isset(cpu, cpu_idle_map))
+                               cpu_clear(cpu, cpu_idle_map);
+                       rmb();
                        idle = pm_idle;
                        if (!idle)
                                idle = default_idle;
                        (*idle)();
-                       rcu_read_unlock();
                }
 
                if (mark_idle)
@@ -609,7 +632,7 @@ dump_fpu (struct pt_regs *pt, elf_fpregset_t dst)
        return 1;       /* f0-f31 are always valid so we always return 1 */
 }
 
-asmlinkage long
+long
 sys_execve (char __user *filename, char __user * __user *argv, char __user * __user *envp,
            struct pt_regs *regs)
 {
@@ -646,7 +669,7 @@ kernel_thread (int (*fn)(void *), void *arg, unsigned long flags)
        regs.pt.cr_ifs = 1UL << 63;             /* mark as valid, empty frame */
        regs.sw.ar_fpsr = regs.pt.ar_fpsr = ia64_getreg(_IA64_REG_AR_FPSR);
        regs.sw.ar_bspstore = (unsigned long) current + IA64_RBS_OFFSET;
-
+       regs.sw.pr = (1 << PRED_KERNEL_STACK);
        return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs.pt, 0, NULL, NULL);
 }
 EXPORT_SYMBOL(kernel_thread);