aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/process.c')
-rw-r--r--arch/i386/kernel/process.c32
1 files changed, 19 insertions, 13 deletions
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index b0a07801d9df..dd53c58f64f1 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -205,7 +205,7 @@ void cpu_idle(void)
205void cpu_idle_wait(void) 205void cpu_idle_wait(void)
206{ 206{
207 unsigned int cpu, this_cpu = get_cpu(); 207 unsigned int cpu, this_cpu = get_cpu();
208 cpumask_t map; 208 cpumask_t map, tmp = current->cpus_allowed;
209 209
210 set_cpus_allowed(current, cpumask_of_cpu(this_cpu)); 210 set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
211 put_cpu(); 211 put_cpu();
@@ -227,6 +227,8 @@ void cpu_idle_wait(void)
227 } 227 }
228 cpus_and(map, map, cpu_online_map); 228 cpus_and(map, map, cpu_online_map);
229 } while (!cpus_empty(map)); 229 } while (!cpus_empty(map));
230
231 set_cpus_allowed(current, tmp);
230} 232}
231EXPORT_SYMBOL_GPL(cpu_idle_wait); 233EXPORT_SYMBOL_GPL(cpu_idle_wait);
232 234
@@ -236,20 +238,28 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
236 * We execute MONITOR against need_resched and enter optimized wait state 238 * We execute MONITOR against need_resched and enter optimized wait state
237 * through MWAIT. Whenever someone changes need_resched, we would be woken 239 * through MWAIT. Whenever someone changes need_resched, we would be woken
238 * up from MWAIT (without an IPI). 240 * up from MWAIT (without an IPI).
241 *
242 * New with Core Duo processors, MWAIT can take some hints based on CPU
243 * capability.
239 */ 244 */
240static void mwait_idle(void) 245void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
241{ 246{
242 local_irq_enable(); 247 if (!need_resched()) {
243
244 while (!need_resched()) {
245 __monitor((void *)&current_thread_info()->flags, 0, 0); 248 __monitor((void *)&current_thread_info()->flags, 0, 0);
246 smp_mb(); 249 smp_mb();
247 if (need_resched()) 250 if (!need_resched())
248 break; 251 __mwait(eax, ecx);
249 __mwait(0, 0);
250 } 252 }
251} 253}
252 254
255/* Default MONITOR/MWAIT with no hints, used for default C1 state */
256static void mwait_idle(void)
257{
258 local_irq_enable();
259 while (!need_resched())
260 mwait_idle_with_hints(0, 0);
261}
262
253void __devinit select_idle_routine(const struct cpuinfo_x86 *c) 263void __devinit select_idle_routine(const struct cpuinfo_x86 *c)
254{ 264{
255 if (cpu_has(c, X86_FEATURE_MWAIT)) { 265 if (cpu_has(c, X86_FEATURE_MWAIT)) {
@@ -328,7 +338,6 @@ extern void kernel_thread_helper(void);
328int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) 338int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
329{ 339{
330 struct pt_regs regs; 340 struct pt_regs regs;
331 int err;
332 341
333 memset(&regs, 0, sizeof(regs)); 342 memset(&regs, 0, sizeof(regs));
334 343
@@ -343,10 +352,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
343 regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2; 352 regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;
344 353
345 /* Ok, create the new process.. */ 354 /* Ok, create the new process.. */
346 err = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL); 355 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
347 if (err == 0) /* terminate kernel stack */
348 task_pt_regs(current)->eip = 0;
349 return err;
350} 356}
351EXPORT_SYMBOL(kernel_thread); 357EXPORT_SYMBOL(kernel_thread);
352 358