diff options
Diffstat (limited to 'arch/mn10300/kernel/process.c')
| -rw-r--r-- | arch/mn10300/kernel/process.c | 215 |
1 files changed, 42 insertions, 173 deletions
diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c index 0d0f8049a17..3707da583d0 100644 --- a/arch/mn10300/kernel/process.c +++ b/arch/mn10300/kernel/process.c @@ -14,7 +14,6 @@ #include <linux/kernel.h> #include <linux/mm.h> #include <linux/smp.h> -#include <linux/smp_lock.h> #include <linux/stddef.h> #include <linux/unistd.h> #include <linux/ptrace.h> @@ -26,9 +25,9 @@ #include <linux/err.h> #include <linux/fs.h> #include <linux/slab.h> +#include <linux/rcupdate.h> #include <asm/uaccess.h> #include <asm/pgtable.h> -#include <asm/system.h> #include <asm/io.h> #include <asm/processor.h> #include <asm/mmu_context.h> @@ -38,12 +37,6 @@ #include "internal.h" /* - * power management idle function, if any.. - */ -void (*pm_idle)(void); -EXPORT_SYMBOL(pm_idle); - -/* * return saved PC of a blocked thread. */ unsigned long thread_saved_pc(struct task_struct *tsk) @@ -57,78 +50,19 @@ unsigned long thread_saved_pc(struct task_struct *tsk) void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); -#if !defined(CONFIG_SMP) || defined(CONFIG_HOTPLUG_CPU) -/* - * we use this if we don't have any better idle routine - */ -static void default_idle(void) -{ - local_irq_disable(); - if (!need_resched()) - safe_halt(); - else - local_irq_enable(); -} - -#else /* !CONFIG_SMP || CONFIG_HOTPLUG_CPU */ /* * On SMP it's slightly faster (but much more power-consuming!) * to poll the ->work.need_resched flag instead of waiting for the * cross-CPU IPI to arrive. Use this option with caution. + * + * tglx: No idea why this depends on HOTPLUG_CPU !?! */ -static inline void poll_idle(void) -{ - int oldval; - - local_irq_enable(); - - /* - * Deal with another CPU just having chosen a thread to - * run here: - */ - oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED); - - if (!oldval) { - set_thread_flag(TIF_POLLING_NRFLAG); - while (!need_resched()) - cpu_relax(); - clear_thread_flag(TIF_POLLING_NRFLAG); - } else { - set_need_resched(); - } -} -#endif /* !CONFIG_SMP || CONFIG_HOTPLUG_CPU */ - -/* - * the idle thread - * - there's no useful work to be done, so just try to conserve power and have - * a low exit latency (ie sit in a loop waiting for somebody to say that - * they'd like to reschedule) - */ -void cpu_idle(void) +#if !defined(CONFIG_SMP) || defined(CONFIG_HOTPLUG_CPU) +void arch_cpu_idle(void) { - /* endless idle loop with no priority at all */ - for (;;) { - while (!need_resched()) { - void (*idle)(void); - - smp_rmb(); - idle = pm_idle; - if (!idle) { -#if defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU) - idle = poll_idle; -#else /* CONFIG_SMP && !CONFIG_HOTPLUG_CPU */ - idle = default_idle; -#endif /* CONFIG_SMP && !CONFIG_HOTPLUG_CPU */ - } - idle(); - } - - preempt_enable_no_resched(); - schedule(); - preempt_disable(); - } + safe_halt(); } +#endif void release_segments(struct mm_struct *mm) { @@ -136,7 +70,7 @@ void release_segments(struct mm_struct *mm) void machine_restart(char *cmd) { -#ifdef CONFIG_GDBSTUB +#ifdef CONFIG_KERNEL_DEBUGGER gdbstub_exit(0); #endif @@ -149,44 +83,24 @@ void machine_restart(char *cmd) void machine_halt(void) { -#ifdef CONFIG_GDBSTUB +#ifdef CONFIG_KERNEL_DEBUGGER gdbstub_exit(0); #endif } void machine_power_off(void) { -#ifdef CONFIG_GDBSTUB +#ifdef CONFIG_KERNEL_DEBUGGER gdbstub_exit(0); #endif } void show_regs(struct pt_regs *regs) { + show_regs_print_info(KERN_DEFAULT); } /* - * create a kernel thread - */ -int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - - regs.a2 = (unsigned long) fn; - regs.d2 = (unsigned long) arg; - regs.pc = (unsigned long) kernel_thread_helper; - local_save_flags(regs.epsw); - regs.epsw |= EPSW_IE | EPSW_IM_7; - - /* Ok, create the new process.. */ - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, - NULL, NULL); -} -EXPORT_SYMBOL(kernel_thread); - -/* * free current thread data structures etc.. */ void exit_thread(void) @@ -212,12 +126,14 @@ void copy_segments(struct task_struct *p, struct mm_struct *new_mm) } /* - * this gets called before we allocate a new thread and copy the current task - * into it so that we can store lazy state into memory + * this gets called so that we can store lazy state into memory and copy the + * current task into the new thread. */ -void prepare_to_copy(struct task_struct *tsk) +int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) { - unlazy_fpu(tsk); + unlazy_fpu(src); + *dst = *src; + return 0; } /* @@ -226,95 +142,48 @@ void prepare_to_copy(struct task_struct *tsk) */ int copy_thread(unsigned long clone_flags, unsigned long c_usp, unsigned long ustk_size, - struct task_struct *p, struct pt_regs *kregs) + struct task_struct *p) { struct thread_info *ti = task_thread_info(p); - struct pt_regs *c_uregs, *c_kregs, *uregs; + struct pt_regs *c_regs; unsigned long c_ksp; - uregs = current->thread.uregs; - c_ksp = (unsigned long) task_stack_page(p) + THREAD_SIZE; /* allocate the userspace exception frame and set it up */ c_ksp -= sizeof(struct pt_regs); - c_uregs = (struct pt_regs *) c_ksp; - - p->thread.uregs = c_uregs; - *c_uregs = *uregs; - c_uregs->sp = c_usp; - c_uregs->epsw &= ~EPSW_FE; /* my FPU */ - + c_regs = (struct pt_regs *) c_ksp; c_ksp -= 12; /* allocate function call ABI slack */ - /* the new TLS pointer is passed in as arg #5 to sys_clone() */ - if (clone_flags & CLONE_SETTLS) - c_uregs->e2 = current_frame()->d3; - - /* set up the return kernel frame if called from kernel_thread() */ - c_kregs = c_uregs; - if (kregs != uregs) { - c_ksp -= sizeof(struct pt_regs); - c_kregs = (struct pt_regs *) c_ksp; - *c_kregs = *kregs; - c_kregs->sp = c_usp; - c_kregs->next = c_uregs; -#ifdef CONFIG_MN10300_CURRENT_IN_E2 - c_kregs->e2 = (unsigned long) p; /* current */ -#endif - - c_ksp -= 12; /* allocate function call ABI slack */ - } - /* set up things up so the scheduler can start the new task */ - ti->frame = c_kregs; - p->thread.a3 = (unsigned long) c_kregs; + p->thread.uregs = c_regs; + ti->frame = c_regs; + p->thread.a3 = (unsigned long) c_regs; p->thread.sp = c_ksp; - p->thread.pc = (unsigned long) ret_from_fork; - p->thread.wchan = (unsigned long) ret_from_fork; + p->thread.wchan = p->thread.pc; p->thread.usp = c_usp; - return 0; -} - -/* - * clone a process - * - tlsptr is retrieved by copy_thread() from current_frame()->d3 - */ -asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, - int __user *parent_tidptr, int __user *child_tidptr, - int __user *tlsptr) -{ - return do_fork(clone_flags, newsp ?: current_frame()->sp, - current_frame(), 0, parent_tidptr, child_tidptr); -} - -asmlinkage long sys_fork(void) -{ - return do_fork(SIGCHLD, current_frame()->sp, - current_frame(), 0, NULL, NULL); -} + if (unlikely(p->flags & PF_KTHREAD)) { + memset(c_regs, 0, sizeof(struct pt_regs)); + c_regs->a0 = c_usp; /* function */ + c_regs->d0 = ustk_size; /* argument */ + local_save_flags(c_regs->epsw); + c_regs->epsw |= EPSW_IE | EPSW_IM_7; + p->thread.pc = (unsigned long) ret_from_kernel_thread; + return 0; + } + *c_regs = *current_pt_regs(); + if (c_usp) + c_regs->sp = c_usp; + c_regs->epsw &= ~EPSW_FE; /* my FPU */ -asmlinkage long sys_vfork(void) -{ - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, current_frame()->sp, - current_frame(), 0, NULL, NULL); -} + /* the new TLS pointer is passed in as arg #5 to sys_clone() */ + if (clone_flags & CLONE_SETTLS) + c_regs->e2 = current_frame()->d3; -asmlinkage long sys_execve(const char __user *name, - const char __user *const __user *argv, - const char __user *const __user *envp) -{ - char *filename; - int error; + p->thread.pc = (unsigned long) ret_from_fork; - filename = getname(name); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - return error; - error = do_execve(filename, argv, envp, current_frame()); - putname(filename); - return error; + return 0; } unsigned long get_wchan(struct task_struct *p) |
