aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Piggin <nickpiggin@yahoo.com.au>2005-11-09 00:39:01 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-09 10:56:33 -0500
commit5bfb5d690f36d316a5f3b4f7775fda996faa6b12 (patch)
treeea53f15293d1ddb49c316eb65df85e939a4f6e5e
parentede3d0fba99520f268067917b50858d788bc41da (diff)
[PATCH] sched: disable preempt in idle tasks
Run idle threads with preempt disabled. Also corrected a bugs in arm26's cpu_idle (make it actually call schedule()). How did it ever work before? Might fix the CPU hotplugging hang which Nigel Cunningham noted. We think the bug hits if the idle thread is preempted after checking need_resched() and before going to sleep, then the CPU offlined. After calling stop_machine_run, the CPU eventually returns from preemption and into the idle thread and goes to sleep. The CPU will continue executing previous idle and have no chance to call play_dead. By disabling preemption until we are ready to explicitly schedule, this bug is fixed and the idle threads generally become more robust. From: alexs <ashepard@u.washington.edu> PPC build fix From: Yoichi Yuasa <yuasa@hh.iij4u.or.jp> MIPS build fix Signed-off-by: Nick Piggin <npiggin@suse.de> Signed-off-by: Yoichi Yuasa <yuasa@hh.iij4u.or.jp> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/arm/kernel/process.c4
-rw-r--r--arch/arm/kernel/smp.c5
-rw-r--r--arch/arm26/kernel/process.c12
-rw-r--r--arch/cris/arch-v32/kernel/smp.c1
-rw-r--r--arch/cris/kernel/process.c2
-rw-r--r--arch/frv/kernel/process.c6
-rw-r--r--arch/h8300/kernel/process.c28
-rw-r--r--arch/i386/kernel/process.c4
-rw-r--r--arch/i386/kernel/smpboot.c1
-rw-r--r--arch/ia64/kernel/process.c2
-rw-r--r--arch/ia64/kernel/smpboot.c1
-rw-r--r--arch/m32r/kernel/process.c2
-rw-r--r--arch/m32r/kernel/smpboot.c1
-rw-r--r--arch/m68k/kernel/process.c2
-rw-r--r--arch/mips/kernel/process.c2
-rw-r--r--arch/mips/kernel/smp.c4
-rw-r--r--arch/parisc/kernel/process.c2
-rw-r--r--arch/parisc/kernel/smp.c1
-rw-r--r--arch/powerpc/platforms/iseries/setup.c4
-rw-r--r--arch/powerpc/platforms/pseries/setup.c4
-rw-r--r--arch/ppc/kernel/idle.c17
-rw-r--r--arch/ppc/kernel/smp.c1
-rw-r--r--arch/ppc64/kernel/idle.c4
-rw-r--r--arch/s390/kernel/process.c11
-rw-r--r--arch/s390/kernel/smp.c1
-rw-r--r--arch/sh/kernel/process.c2
-rw-r--r--arch/sh/kernel/smp.c5
-rw-r--r--arch/sh64/kernel/process.c2
-rw-r--r--arch/sparc/kernel/process.c4
-rw-r--r--arch/sparc64/kernel/process.c4
-rw-r--r--arch/sparc64/kernel/smp.c3
-rw-r--r--arch/v850/kernel/process.c16
-rw-r--r--arch/x86_64/kernel/process.c2
-rw-r--r--arch/x86_64/kernel/smpboot.c1
-rw-r--r--arch/xtensa/kernel/process.c3
-rw-r--r--init/main.c4
36 files changed, 125 insertions, 43 deletions
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index ba298277becd..93dd92cc12f8 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -116,13 +116,13 @@ void cpu_idle(void)
116 116
117 if (!idle) 117 if (!idle)
118 idle = default_idle; 118 idle = default_idle;
119 preempt_disable();
120 leds_event(led_idle_start); 119 leds_event(led_idle_start);
121 while (!need_resched()) 120 while (!need_resched())
122 idle(); 121 idle();
123 leds_event(led_idle_end); 122 leds_event(led_idle_end);
124 preempt_enable(); 123 preempt_enable_no_resched();
125 schedule(); 124 schedule();
125 preempt_disable();
126 } 126 }
127} 127}
128 128
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 77e2e9ca89fa..e55ea952f7aa 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -256,7 +256,9 @@ void __cpuexit cpu_die(void)
256asmlinkage void __cpuinit secondary_start_kernel(void) 256asmlinkage void __cpuinit secondary_start_kernel(void)
257{ 257{
258 struct mm_struct *mm = &init_mm; 258 struct mm_struct *mm = &init_mm;
259 unsigned int cpu = smp_processor_id(); 259 unsigned int cpu;
260
261 cpu = smp_processor_id();
260 262
261 printk("CPU%u: Booted secondary processor\n", cpu); 263 printk("CPU%u: Booted secondary processor\n", cpu);
262 264
@@ -273,6 +275,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
273 local_flush_tlb_all(); 275 local_flush_tlb_all();
274 276
275 cpu_init(); 277 cpu_init();
278 preempt_disable();
276 279
277 /* 280 /*
278 * Give the platform a chance to do its own initialisation. 281 * Give the platform a chance to do its own initialisation.
diff --git a/arch/arm26/kernel/process.c b/arch/arm26/kernel/process.c
index 9eb9964d32a7..15833a0057dd 100644
--- a/arch/arm26/kernel/process.c
+++ b/arch/arm26/kernel/process.c
@@ -74,15 +74,13 @@ __setup("hlt", hlt_setup);
74void cpu_idle(void) 74void cpu_idle(void)
75{ 75{
76 /* endless idle loop with no priority at all */ 76 /* endless idle loop with no priority at all */
77 preempt_disable();
78 while (1) { 77 while (1) {
79 while (!need_resched()) { 78 while (!need_resched())
80 local_irq_disable(); 79 cpu_relax();
81 if (!need_resched() && !hlt_counter) 80 preempt_enable_no_resched();
82 local_irq_enable(); 81 schedule();
83 } 82 preempt_disable();
84 } 83 }
85 schedule();
86} 84}
87 85
88static char reboot_mode = 'h'; 86static char reboot_mode = 'h';
diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c
index 957f551ba5ce..13867f4fad16 100644
--- a/arch/cris/arch-v32/kernel/smp.c
+++ b/arch/cris/arch-v32/kernel/smp.c
@@ -161,6 +161,7 @@ void __init smp_callin(void)
161 REG_WR(intr_vect, irq_regs[cpu], rw_mask, vect_mask); 161 REG_WR(intr_vect, irq_regs[cpu], rw_mask, vect_mask);
162 unmask_irq(IPI_INTR_VECT); 162 unmask_irq(IPI_INTR_VECT);
163 unmask_irq(TIMER_INTR_VECT); 163 unmask_irq(TIMER_INTR_VECT);
164 preempt_disable();
164 local_irq_enable(); 165 local_irq_enable();
165 166
166 cpu_set(cpu, cpu_online_map); 167 cpu_set(cpu, cpu_online_map);
diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c
index 949a0e40e03c..7c80afb10460 100644
--- a/arch/cris/kernel/process.c
+++ b/arch/cris/kernel/process.c
@@ -218,7 +218,9 @@ void cpu_idle (void)
218 idle = default_idle; 218 idle = default_idle;
219 idle(); 219 idle();
220 } 220 }
221 preempt_enable_no_resched();
221 schedule(); 222 schedule();
223 preempt_disable();
222 } 224 }
223} 225}
224 226
diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c
index 3001b82b1514..54a452136f00 100644
--- a/arch/frv/kernel/process.c
+++ b/arch/frv/kernel/process.c
@@ -77,16 +77,20 @@ void (*idle)(void) = core_sleep_idle;
77 */ 77 */
78void cpu_idle(void) 78void cpu_idle(void)
79{ 79{
80 int cpu = smp_processor_id();
81
80 /* endless idle loop with no priority at all */ 82 /* endless idle loop with no priority at all */
81 while (1) { 83 while (1) {
82 while (!need_resched()) { 84 while (!need_resched()) {
83 irq_stat[smp_processor_id()].idle_timestamp = jiffies; 85 irq_stat[cpu].idle_timestamp = jiffies;
84 86
85 if (!frv_dma_inprogress && idle) 87 if (!frv_dma_inprogress && idle)
86 idle(); 88 idle();
87 } 89 }
88 90
91 preempt_enable_no_resched();
89 schedule(); 92 schedule();
93 preempt_disable();
90 } 94 }
91} 95}
92 96
diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c
index 27f1fce64ce4..fe21adf3e75e 100644
--- a/arch/h8300/kernel/process.c
+++ b/arch/h8300/kernel/process.c
@@ -53,22 +53,18 @@ asmlinkage void ret_from_fork(void);
53#if !defined(CONFIG_H8300H_SIM) && !defined(CONFIG_H8S_SIM) 53#if !defined(CONFIG_H8300H_SIM) && !defined(CONFIG_H8S_SIM)
54void default_idle(void) 54void default_idle(void)
55{ 55{
56 while(1) { 56 local_irq_disable();
57 if (!need_resched()) { 57 if (!need_resched()) {
58 local_irq_enable(); 58 local_irq_enable();
59 __asm__("sleep"); 59 /* XXX: race here! What if need_resched() gets set now? */
60 local_irq_disable(); 60 __asm__("sleep");
61 } 61 } else
62 schedule(); 62 local_irq_enable();
63 }
64} 63}
65#else 64#else
66void default_idle(void) 65void default_idle(void)
67{ 66{
68 while(1) { 67 cpu_relax();
69 if (need_resched())
70 schedule();
71 }
72} 68}
73#endif 69#endif
74void (*idle)(void) = default_idle; 70void (*idle)(void) = default_idle;
@@ -81,7 +77,13 @@ void (*idle)(void) = default_idle;
81 */ 77 */
82void cpu_idle(void) 78void cpu_idle(void)
83{ 79{
84 idle(); 80 while (1) {
81 while (!need_resched())
82 idle();
83 preempt_enable_no_resched();
84 schedule();
85 preempt_disable();
86 }
85} 87}
86 88
87void machine_restart(char * __unused) 89void machine_restart(char * __unused)
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 7a14fdfd3af9..5296e284ea36 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -179,7 +179,7 @@ static inline void play_dead(void)
179 */ 179 */
180void cpu_idle(void) 180void cpu_idle(void)
181{ 181{
182 int cpu = raw_smp_processor_id(); 182 int cpu = smp_processor_id();
183 183
184 /* endless idle loop with no priority at all */ 184 /* endless idle loop with no priority at all */
185 while (1) { 185 while (1) {
@@ -201,7 +201,9 @@ void cpu_idle(void)
201 __get_cpu_var(irq_stat).idle_timestamp = jiffies; 201 __get_cpu_var(irq_stat).idle_timestamp = jiffies;
202 idle(); 202 idle();
203 } 203 }
204 preempt_enable_no_resched();
204 schedule(); 205 schedule();
206 preempt_disable();
205 } 207 }
206} 208}
207 209
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 47ec76794d02..bc5a9d97466b 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -485,6 +485,7 @@ static void __devinit start_secondary(void *unused)
485 * things done here to the most necessary things. 485 * things done here to the most necessary things.
486 */ 486 */
487 cpu_init(); 487 cpu_init();
488 preempt_disable();
488 smp_callin(); 489 smp_callin();
489 while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) 490 while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
490 rep_nop(); 491 rep_nop();
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 051e050359e4..4c621fc3c3b9 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -292,7 +292,9 @@ cpu_idle (void)
292#ifdef CONFIG_SMP 292#ifdef CONFIG_SMP
293 normal_xtp(); 293 normal_xtp();
294#endif 294#endif
295 preempt_enable_no_resched();
295 schedule(); 296 schedule();
297 preempt_disable();
296 check_pgt_cache(); 298 check_pgt_cache();
297 if (cpu_is_offline(smp_processor_id())) 299 if (cpu_is_offline(smp_processor_id()))
298 play_dead(); 300 play_dead();
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 400a48987124..8f44e7d2df66 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -399,6 +399,7 @@ start_secondary (void *unused)
399 Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id()); 399 Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id());
400 efi_map_pal_code(); 400 efi_map_pal_code();
401 cpu_init(); 401 cpu_init();
402 preempt_disable();
402 smp_callin(); 403 smp_callin();
403 404
404 cpu_idle(); 405 cpu_idle();
diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c
index ea13a8f4d8b0..cc4b571e5db7 100644
--- a/arch/m32r/kernel/process.c
+++ b/arch/m32r/kernel/process.c
@@ -104,7 +104,9 @@ void cpu_idle (void)
104 104
105 idle(); 105 idle();
106 } 106 }
107 preempt_enable_no_resched();
107 schedule(); 108 schedule();
109 preempt_disable();
108 } 110 }
109} 111}
110 112
diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c
index 640d592ea072..b90c54169fa5 100644
--- a/arch/m32r/kernel/smpboot.c
+++ b/arch/m32r/kernel/smpboot.c
@@ -426,6 +426,7 @@ void __init smp_cpus_done(unsigned int max_cpus)
426int __init start_secondary(void *unused) 426int __init start_secondary(void *unused)
427{ 427{
428 cpu_init(); 428 cpu_init();
429 preempt_disable();
429 smp_callin(); 430 smp_callin();
430 while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) 431 while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
431 cpu_relax(); 432 cpu_relax();
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index 11b1b90ba6ba..13d109328a42 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -102,7 +102,9 @@ void cpu_idle(void)
102 while (1) { 102 while (1) {
103 while (!need_resched()) 103 while (!need_resched())
104 idle(); 104 idle();
105 preempt_enable_no_resched();
105 schedule(); 106 schedule();
107 preempt_disable();
106 } 108 }
107} 109}
108 110
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 4fe3d5715c41..dd725779d91f 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -52,7 +52,9 @@ ATTRIB_NORET void cpu_idle(void)
52 while (!need_resched()) 52 while (!need_resched())
53 if (cpu_wait) 53 if (cpu_wait)
54 (*cpu_wait)(); 54 (*cpu_wait)();
55 preempt_enable_no_resched();
55 schedule(); 56 schedule();
57 preempt_disable();
56 } 58 }
57} 59}
58 60
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index fcacf1aae98a..25472fcaf715 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -82,7 +82,7 @@ extern ATTRIB_NORET void cpu_idle(void);
82 */ 82 */
83asmlinkage void start_secondary(void) 83asmlinkage void start_secondary(void)
84{ 84{
85 unsigned int cpu = smp_processor_id(); 85 unsigned int cpu;
86 86
87 cpu_probe(); 87 cpu_probe();
88 cpu_report(); 88 cpu_report();
@@ -95,6 +95,8 @@ asmlinkage void start_secondary(void)
95 */ 95 */
96 96
97 calibrate_delay(); 97 calibrate_delay();
98 preempt_disable();
99 cpu = smp_processor_id();
98 cpu_data[cpu].udelay_val = loops_per_jiffy; 100 cpu_data[cpu].udelay_val = loops_per_jiffy;
99 101
100 prom_smp_finish(); 102 prom_smp_finish();
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index 7fdca87ef647..f482f78de435 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -92,7 +92,9 @@ void cpu_idle(void)
92 while (1) { 92 while (1) {
93 while (!need_resched()) 93 while (!need_resched())
94 barrier(); 94 barrier();
95 preempt_enable_no_resched();
95 schedule(); 96 schedule();
97 preempt_disable();
96 check_pgt_cache(); 98 check_pgt_cache();
97 } 99 }
98} 100}
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index 5db3be4e2704..a9ecf6465784 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -463,6 +463,7 @@ void __init smp_callin(void)
463#endif 463#endif
464 464
465 smp_cpu_init(slave_id); 465 smp_cpu_init(slave_id);
466 preempt_disable();
466 467
467#if 0 /* NOT WORKING YET - see entry.S */ 468#if 0 /* NOT WORKING YET - see entry.S */
468 istack = (void *)__get_free_pages(GFP_KERNEL,ISTACK_ORDER); 469 istack = (void *)__get_free_pages(GFP_KERNEL,ISTACK_ORDER);
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index d3e4bf756c83..0130f2619dac 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -694,7 +694,9 @@ static void iseries_shared_idle(void)
694 if (hvlpevent_is_pending()) 694 if (hvlpevent_is_pending())
695 process_iSeries_events(); 695 process_iSeries_events();
696 696
697 preempt_enable_no_resched();
697 schedule(); 698 schedule();
699 preempt_disable();
698 } 700 }
699} 701}
700 702
@@ -726,7 +728,9 @@ static void iseries_dedicated_idle(void)
726 } 728 }
727 729
728 ppc64_runlatch_on(); 730 ppc64_runlatch_on();
731 preempt_enable_no_resched();
729 schedule(); 732 schedule();
733 preempt_disable();
730 } 734 }
731} 735}
732 736
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index e78c39368841..4854f5eb5c3d 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -539,7 +539,9 @@ static void pseries_dedicated_idle(void)
539 lpaca->lppaca.idle = 0; 539 lpaca->lppaca.idle = 0;
540 ppc64_runlatch_on(); 540 ppc64_runlatch_on();
541 541
542 preempt_enable_no_resched();
542 schedule(); 543 schedule();
544 preempt_disable();
543 545
544 if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) 546 if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
545 cpu_die(); 547 cpu_die();
@@ -583,7 +585,9 @@ static void pseries_shared_idle(void)
583 lpaca->lppaca.idle = 0; 585 lpaca->lppaca.idle = 0;
584 ppc64_runlatch_on(); 586 ppc64_runlatch_on();
585 587
588 preempt_enable_no_resched();
586 schedule(); 589 schedule();
590 preempt_disable();
587 591
588 if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) 592 if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
589 cpu_die(); 593 cpu_die();
diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
index 11e5b44713f7..a6141f05c919 100644
--- a/arch/ppc/kernel/idle.c
+++ b/arch/ppc/kernel/idle.c
@@ -53,10 +53,6 @@ void default_idle(void)
53 } 53 }
54#endif 54#endif
55 } 55 }
56 if (need_resched())
57 schedule();
58 if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
59 cpu_die();
60} 56}
61 57
62/* 58/*
@@ -64,11 +60,22 @@ void default_idle(void)
64 */ 60 */
65void cpu_idle(void) 61void cpu_idle(void)
66{ 62{
67 for (;;) 63 int cpu = smp_processor_id();
64
65 for (;;) {
68 if (ppc_md.idle != NULL) 66 if (ppc_md.idle != NULL)
69 ppc_md.idle(); 67 ppc_md.idle();
70 else 68 else
71 default_idle(); 69 default_idle();
70 if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
71 cpu_die();
72 if (need_resched()) {
73 preempt_enable_no_resched();
74 schedule();
75 preempt_disable();
76 }
77
78 }
72} 79}
73 80
74#if defined(CONFIG_SYSCTL) && defined(CONFIG_6xx) 81#if defined(CONFIG_SYSCTL) && defined(CONFIG_6xx)
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index bc5bf1124836..43b8fc2ca591 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -341,6 +341,7 @@ int __devinit start_secondary(void *unused)
341 cpu = smp_processor_id(); 341 cpu = smp_processor_id();
342 smp_store_cpu_info(cpu); 342 smp_store_cpu_info(cpu);
343 set_dec(tb_ticks_per_jiffy); 343 set_dec(tb_ticks_per_jiffy);
344 preempt_disable();
344 cpu_callin_map[cpu] = 1; 345 cpu_callin_map[cpu] = 1;
345 346
346 printk("CPU %d done callin...\n", cpu); 347 printk("CPU %d done callin...\n", cpu);
diff --git a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c
index 8fec27469802..909ea669af91 100644
--- a/arch/ppc64/kernel/idle.c
+++ b/arch/ppc64/kernel/idle.c
@@ -61,7 +61,9 @@ void default_idle(void)
61 } 61 }
62 62
63 ppc64_runlatch_on(); 63 ppc64_runlatch_on();
64 preempt_enable_no_resched();
64 schedule(); 65 schedule();
66 preempt_disable();
65 if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) 67 if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
66 cpu_die(); 68 cpu_die();
67 } 69 }
@@ -77,7 +79,9 @@ void native_idle(void)
77 79
78 if (need_resched()) { 80 if (need_resched()) {
79 ppc64_runlatch_on(); 81 ppc64_runlatch_on();
82 preempt_enable_no_resched();
80 schedule(); 83 schedule();
84 preempt_disable();
81 } 85 }
82 86
83 if (cpu_is_offline(smp_processor_id()) && 87 if (cpu_is_offline(smp_processor_id()) &&
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 9f3dff6c0b72..66ca5757e368 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -102,7 +102,6 @@ void default_idle(void)
102 local_irq_disable(); 102 local_irq_disable();
103 if (need_resched()) { 103 if (need_resched()) {
104 local_irq_enable(); 104 local_irq_enable();
105 schedule();
106 return; 105 return;
107 } 106 }
108 107
@@ -139,8 +138,14 @@ void default_idle(void)
139 138
140void cpu_idle(void) 139void cpu_idle(void)
141{ 140{
142 for (;;) 141 for (;;) {
143 default_idle(); 142 while (!need_resched())
143 default_idle();
144
145 preempt_enable_no_resched();
146 schedule();
147 preempt_disable();
148 }
144} 149}
145 150
146void show_regs(struct pt_regs *regs) 151void show_regs(struct pt_regs *regs)
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index e13c87b446b2..5856b3fda6bf 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -533,6 +533,7 @@ int __devinit start_secondary(void *cpuvoid)
533{ 533{
534 /* Setup the cpu */ 534 /* Setup the cpu */
535 cpu_init(); 535 cpu_init();
536 preempt_disable();
536 /* init per CPU timer */ 537 /* init per CPU timer */
537 init_cpu_timer(); 538 init_cpu_timer();
538#ifdef CONFIG_VIRT_TIMER 539#ifdef CONFIG_VIRT_TIMER
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index 6dce9d0b81f8..1cbc26b796ad 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -64,7 +64,9 @@ void default_idle(void)
64 cpu_sleep(); 64 cpu_sleep();
65 } 65 }
66 66
67 preempt_enable_no_resched();
67 schedule(); 68 schedule();
69 preempt_disable();
68 } 70 }
69} 71}
70 72
diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c
index 5ecefc02896a..59e49b18252c 100644
--- a/arch/sh/kernel/smp.c
+++ b/arch/sh/kernel/smp.c
@@ -112,7 +112,9 @@ int __cpu_up(unsigned int cpu)
112 112
113int start_secondary(void *unused) 113int start_secondary(void *unused)
114{ 114{
115 unsigned int cpu = smp_processor_id(); 115 unsigned int cpu;
116
117 cpu = smp_processor_id();
116 118
117 atomic_inc(&init_mm.mm_count); 119 atomic_inc(&init_mm.mm_count);
118 current->active_mm = &init_mm; 120 current->active_mm = &init_mm;
@@ -120,6 +122,7 @@ int start_secondary(void *unused)
120 smp_store_cpu_info(cpu); 122 smp_store_cpu_info(cpu);
121 123
122 __smp_slave_init(cpu); 124 __smp_slave_init(cpu);
125 preempt_disable();
123 per_cpu_trap_init(); 126 per_cpu_trap_init();
124 127
125 atomic_inc(&cpus_booted); 128 atomic_inc(&cpus_booted);
diff --git a/arch/sh64/kernel/process.c b/arch/sh64/kernel/process.c
index efde41c0cd66..0c09537449b3 100644
--- a/arch/sh64/kernel/process.c
+++ b/arch/sh64/kernel/process.c
@@ -334,7 +334,9 @@ void default_idle(void)
334 } 334 }
335 local_irq_enable(); 335 local_irq_enable();
336 } 336 }
337 preempt_enable_no_resched();
337 schedule(); 338 schedule();
339 preempt_disable();
338 } 340 }
339} 341}
340 342
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
index 29e72b57d4fd..c39f4d01096d 100644
--- a/arch/sparc/kernel/process.c
+++ b/arch/sparc/kernel/process.c
@@ -120,7 +120,9 @@ void cpu_idle(void)
120 (*pm_idle)(); 120 (*pm_idle)();
121 } 121 }
122 122
123 preempt_enable_no_resched();
123 schedule(); 124 schedule();
125 preempt_disable();
124 check_pgt_cache(); 126 check_pgt_cache();
125 } 127 }
126} 128}
@@ -133,7 +135,9 @@ void cpu_idle(void)
133 /* endless idle loop with no priority at all */ 135 /* endless idle loop with no priority at all */
134 while(1) { 136 while(1) {
135 if(need_resched()) { 137 if(need_resched()) {
138 preempt_enable_no_resched();
136 schedule(); 139 schedule();
140 preempt_disable();
137 check_pgt_cache(); 141 check_pgt_cache();
138 } 142 }
139 barrier(); /* or else gcc optimizes... */ 143 barrier(); /* or else gcc optimizes... */
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 7d10b0397091..2f89206e008f 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -74,7 +74,9 @@ void cpu_idle(void)
74 while (!need_resched()) 74 while (!need_resched())
75 barrier(); 75 barrier();
76 76
77 preempt_enable_no_resched();
77 schedule(); 78 schedule();
79 preempt_disable();
78 check_pgt_cache(); 80 check_pgt_cache();
79 } 81 }
80} 82}
@@ -93,7 +95,9 @@ void cpu_idle(void)
93 if (need_resched()) { 95 if (need_resched()) {
94 unidle_me(); 96 unidle_me();
95 clear_thread_flag(TIF_POLLING_NRFLAG); 97 clear_thread_flag(TIF_POLLING_NRFLAG);
98 preempt_enable_no_resched();
96 schedule(); 99 schedule();
100 preempt_disable();
97 set_thread_flag(TIF_POLLING_NRFLAG); 101 set_thread_flag(TIF_POLLING_NRFLAG);
98 check_pgt_cache(); 102 check_pgt_cache();
99 } 103 }
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 5d90ee9aebf1..8aca4b1dc04e 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -168,6 +168,9 @@ void __init smp_callin(void)
168 rmb(); 168 rmb();
169 169
170 cpu_set(cpuid, cpu_online_map); 170 cpu_set(cpuid, cpu_online_map);
171
172 /* idle thread is expected to have preempt disabled */
173 preempt_disable();
171} 174}
172 175
173void cpu_panic(void) 176void cpu_panic(void)
diff --git a/arch/v850/kernel/process.c b/arch/v850/kernel/process.c
index 9c708c32c1f0..39cf247cdae4 100644
--- a/arch/v850/kernel/process.c
+++ b/arch/v850/kernel/process.c
@@ -36,11 +36,8 @@ extern void ret_from_fork (void);
36/* The idle loop. */ 36/* The idle loop. */
37void default_idle (void) 37void default_idle (void)
38{ 38{
39 while (1) { 39 while (! need_resched ())
40 while (! need_resched ()) 40 asm ("halt; nop; nop; nop; nop; nop" ::: "cc");
41 asm ("halt; nop; nop; nop; nop; nop" ::: "cc");
42 schedule ();
43 }
44} 41}
45 42
46void (*idle)(void) = default_idle; 43void (*idle)(void) = default_idle;
@@ -54,7 +51,14 @@ void (*idle)(void) = default_idle;
54void cpu_idle (void) 51void cpu_idle (void)
55{ 52{
56 /* endless idle loop with no priority at all */ 53 /* endless idle loop with no priority at all */
57 (*idle) (); 54 while (1) {
55 while (!need_resched())
56 (*idle) ();
57
58 preempt_enable_no_resched();
59 schedule();
60 preempt_disable();
61 }
58} 62}
59 63
60/* 64/*
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index b5a89c0bdf59..571f9fe490ce 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -204,7 +204,9 @@ void cpu_idle (void)
204 idle(); 204 idle();
205 } 205 }
206 206
207 preempt_enable_no_resched();
207 schedule(); 208 schedule();
209 preempt_disable();
208 } 210 }
209} 211}
210 212
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index 4b5b088ec102..c4e59bbdc187 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -472,6 +472,7 @@ void __cpuinit start_secondary(void)
472 * things done here to the most necessary things. 472 * things done here to the most necessary things.
473 */ 473 */
474 cpu_init(); 474 cpu_init();
475 preempt_disable();
475 smp_callin(); 476 smp_callin();
476 477
477 /* otherwise gcc will move up the smp_processor_id before the cpu_init */ 478 /* otherwise gcc will move up the smp_processor_id before the cpu_init */
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
index 08ef6d82ee51..6a44b54ae817 100644
--- a/arch/xtensa/kernel/process.c
+++ b/arch/xtensa/kernel/process.c
@@ -96,8 +96,9 @@ void cpu_idle(void)
96 while (1) { 96 while (1) {
97 while (!need_resched()) 97 while (!need_resched())
98 platform_idle(); 98 platform_idle();
99 preempt_enable(); 99 preempt_enable_no_resched();
100 schedule(); 100 schedule();
101 preempt_disable();
101 } 102 }
102} 103}
103 104
diff --git a/init/main.c b/init/main.c
index f142d4035341..27f97f9b4636 100644
--- a/init/main.c
+++ b/init/main.c
@@ -394,14 +394,16 @@ static void noinline rest_init(void)
394 kernel_thread(init, NULL, CLONE_FS | CLONE_SIGHAND); 394 kernel_thread(init, NULL, CLONE_FS | CLONE_SIGHAND);
395 numa_default_policy(); 395 numa_default_policy();
396 unlock_kernel(); 396 unlock_kernel();
397 preempt_enable_no_resched();
398 397
399 /* 398 /*
400 * The boot idle thread must execute schedule() 399 * The boot idle thread must execute schedule()
401 * at least one to get things moving: 400 * at least one to get things moving:
402 */ 401 */
402 preempt_enable_no_resched();
403 schedule(); 403 schedule();
404 preempt_disable();
404 405
406 /* Call into cpu_idle with preempt disabled */
405 cpu_idle(); 407 cpu_idle();
406} 408}
407 409