diff options
Diffstat (limited to 'arch/mn10300/kernel/process.c')
-rw-r--r-- | arch/mn10300/kernel/process.c | 61 |
1 files changed, 47 insertions, 14 deletions
diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c index f48373e2bc1c..0d0f8049a17b 100644 --- a/arch/mn10300/kernel/process.c +++ b/arch/mn10300/kernel/process.c | |||
@@ -57,6 +57,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk) | |||
57 | void (*pm_power_off)(void); | 57 | void (*pm_power_off)(void); |
58 | EXPORT_SYMBOL(pm_power_off); | 58 | EXPORT_SYMBOL(pm_power_off); |
59 | 59 | ||
60 | #if !defined(CONFIG_SMP) || defined(CONFIG_HOTPLUG_CPU) | ||
60 | /* | 61 | /* |
61 | * we use this if we don't have any better idle routine | 62 | * we use this if we don't have any better idle routine |
62 | */ | 63 | */ |
@@ -69,6 +70,35 @@ static void default_idle(void) | |||
69 | local_irq_enable(); | 70 | local_irq_enable(); |
70 | } | 71 | } |
71 | 72 | ||
73 | #else /* !CONFIG_SMP || CONFIG_HOTPLUG_CPU */ | ||
74 | /* | ||
75 | * On SMP it's slightly faster (but much more power-consuming!) | ||
76 | * to poll the ->work.need_resched flag instead of waiting for the | ||
77 | * cross-CPU IPI to arrive. Use this option with caution. | ||
78 | */ | ||
79 | static inline void poll_idle(void) | ||
80 | { | ||
81 | int oldval; | ||
82 | |||
83 | local_irq_enable(); | ||
84 | |||
85 | /* | ||
86 | * Deal with another CPU just having chosen a thread to | ||
87 | * run here: | ||
88 | */ | ||
89 | oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED); | ||
90 | |||
91 | if (!oldval) { | ||
92 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
93 | while (!need_resched()) | ||
94 | cpu_relax(); | ||
95 | clear_thread_flag(TIF_POLLING_NRFLAG); | ||
96 | } else { | ||
97 | set_need_resched(); | ||
98 | } | ||
99 | } | ||
100 | #endif /* !CONFIG_SMP || CONFIG_HOTPLUG_CPU */ | ||
101 | |||
72 | /* | 102 | /* |
73 | * the idle thread | 103 | * the idle thread |
74 | * - there's no useful work to be done, so just try to conserve power and have | 104 | * - there's no useful work to be done, so just try to conserve power and have |
@@ -77,8 +107,6 @@ static void default_idle(void) | |||
77 | */ | 107 | */ |
78 | void cpu_idle(void) | 108 | void cpu_idle(void) |
79 | { | 109 | { |
80 | int cpu = smp_processor_id(); | ||
81 | |||
82 | /* endless idle loop with no priority at all */ | 110 | /* endless idle loop with no priority at all */ |
83 | for (;;) { | 111 | for (;;) { |
84 | while (!need_resched()) { | 112 | while (!need_resched()) { |
@@ -86,10 +114,13 @@ void cpu_idle(void) | |||
86 | 114 | ||
87 | smp_rmb(); | 115 | smp_rmb(); |
88 | idle = pm_idle; | 116 | idle = pm_idle; |
89 | if (!idle) | 117 | if (!idle) { |
118 | #if defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU) | ||
119 | idle = poll_idle; | ||
120 | #else /* CONFIG_SMP && !CONFIG_HOTPLUG_CPU */ | ||
90 | idle = default_idle; | 121 | idle = default_idle; |
91 | 122 | #endif /* CONFIG_SMP && !CONFIG_HOTPLUG_CPU */ | |
92 | irq_stat[cpu].idle_timestamp = jiffies; | 123 | } |
93 | idle(); | 124 | idle(); |
94 | } | 125 | } |
95 | 126 | ||
@@ -197,6 +228,7 @@ int copy_thread(unsigned long clone_flags, | |||
197 | unsigned long c_usp, unsigned long ustk_size, | 228 | unsigned long c_usp, unsigned long ustk_size, |
198 | struct task_struct *p, struct pt_regs *kregs) | 229 | struct task_struct *p, struct pt_regs *kregs) |
199 | { | 230 | { |
231 | struct thread_info *ti = task_thread_info(p); | ||
200 | struct pt_regs *c_uregs, *c_kregs, *uregs; | 232 | struct pt_regs *c_uregs, *c_kregs, *uregs; |
201 | unsigned long c_ksp; | 233 | unsigned long c_ksp; |
202 | 234 | ||
@@ -217,7 +249,7 @@ int copy_thread(unsigned long clone_flags, | |||
217 | 249 | ||
218 | /* the new TLS pointer is passed in as arg #5 to sys_clone() */ | 250 | /* the new TLS pointer is passed in as arg #5 to sys_clone() */ |
219 | if (clone_flags & CLONE_SETTLS) | 251 | if (clone_flags & CLONE_SETTLS) |
220 | c_uregs->e2 = __frame->d3; | 252 | c_uregs->e2 = current_frame()->d3; |
221 | 253 | ||
222 | /* set up the return kernel frame if called from kernel_thread() */ | 254 | /* set up the return kernel frame if called from kernel_thread() */ |
223 | c_kregs = c_uregs; | 255 | c_kregs = c_uregs; |
@@ -235,7 +267,7 @@ int copy_thread(unsigned long clone_flags, | |||
235 | } | 267 | } |
236 | 268 | ||
237 | /* set up things up so the scheduler can start the new task */ | 269 | /* set up things up so the scheduler can start the new task */ |
238 | p->thread.__frame = c_kregs; | 270 | ti->frame = c_kregs; |
239 | p->thread.a3 = (unsigned long) c_kregs; | 271 | p->thread.a3 = (unsigned long) c_kregs; |
240 | p->thread.sp = c_ksp; | 272 | p->thread.sp = c_ksp; |
241 | p->thread.pc = (unsigned long) ret_from_fork; | 273 | p->thread.pc = (unsigned long) ret_from_fork; |
@@ -247,25 +279,26 @@ int copy_thread(unsigned long clone_flags, | |||
247 | 279 | ||
248 | /* | 280 | /* |
249 | * clone a process | 281 | * clone a process |
250 | * - tlsptr is retrieved by copy_thread() from __frame->d3 | 282 | * - tlsptr is retrieved by copy_thread() from current_frame()->d3 |
251 | */ | 283 | */ |
252 | asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, | 284 | asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, |
253 | int __user *parent_tidptr, int __user *child_tidptr, | 285 | int __user *parent_tidptr, int __user *child_tidptr, |
254 | int __user *tlsptr) | 286 | int __user *tlsptr) |
255 | { | 287 | { |
256 | return do_fork(clone_flags, newsp ?: __frame->sp, __frame, 0, | 288 | return do_fork(clone_flags, newsp ?: current_frame()->sp, |
257 | parent_tidptr, child_tidptr); | 289 | current_frame(), 0, parent_tidptr, child_tidptr); |
258 | } | 290 | } |
259 | 291 | ||
260 | asmlinkage long sys_fork(void) | 292 | asmlinkage long sys_fork(void) |
261 | { | 293 | { |
262 | return do_fork(SIGCHLD, __frame->sp, __frame, 0, NULL, NULL); | 294 | return do_fork(SIGCHLD, current_frame()->sp, |
295 | current_frame(), 0, NULL, NULL); | ||
263 | } | 296 | } |
264 | 297 | ||
265 | asmlinkage long sys_vfork(void) | 298 | asmlinkage long sys_vfork(void) |
266 | { | 299 | { |
267 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, __frame->sp, __frame, | 300 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, current_frame()->sp, |
268 | 0, NULL, NULL); | 301 | current_frame(), 0, NULL, NULL); |
269 | } | 302 | } |
270 | 303 | ||
271 | asmlinkage long sys_execve(const char __user *name, | 304 | asmlinkage long sys_execve(const char __user *name, |
@@ -279,7 +312,7 @@ asmlinkage long sys_execve(const char __user *name, | |||
279 | error = PTR_ERR(filename); | 312 | error = PTR_ERR(filename); |
280 | if (IS_ERR(filename)) | 313 | if (IS_ERR(filename)) |
281 | return error; | 314 | return error; |
282 | error = do_execve(filename, argv, envp, __frame); | 315 | error = do_execve(filename, argv, envp, current_frame()); |
283 | putname(filename); | 316 | putname(filename); |
284 | return error; | 317 | return error; |
285 | } | 318 | } |