public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2.6.14-rc1-git5] sched: disable preempt in idle tasks
@ 2005-09-21 15:41 Nick Piggin
  2005-09-21 21:43 ` Nigel Cunningham
  2005-09-22  1:31 ` Andrew Morton
  0 siblings, 2 replies; 10+ messages in thread
From: Nick Piggin @ 2005-09-21 15:41 UTC (permalink / raw)
  To: Andrew Morton, Nigel Cunningham, Li, Shaohua, Srivatsa Vaddagiri,
	Linux Kernel Mailing List, Ian Molton

[-- Attachment #1: Type: text/plain, Size: 371 bytes --]

This patch should hopefully fix Nigel's bug.

Split out from sched-resched-opt.patch. Tested on i386 with acpi idle
and poll idle (previous iterations tested on various other architectures).

CCed Ian because I am amazed that arm26 ever managed to reschedule
out of the idle task without this... what am I missing?

Andrew please apply

Nick

-- 
SUSE Labs, Novell Inc.


[-- Attachment #2: sched-no-preempt-idle.patch --]
[-- Type: text/plain, Size: 21971 bytes --]

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?

Signed-off-by: Nick Piggin <npiggin@suse.de>

Index: linux-2.6/init/main.c
===================================================================
--- linux-2.6.orig/init/main.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/init/main.c	2005-09-22 01:04:03.000000000 +1000
@@ -394,14 +394,16 @@ static void noinline rest_init(void)
 	kernel_thread(init, NULL, CLONE_FS | CLONE_SIGHAND);
 	numa_default_policy();
 	unlock_kernel();
-	preempt_enable_no_resched();
 
 	/*
 	 * The boot idle thread must execute schedule()
 	 * at least one to get things moving:
 	 */
+	preempt_enable_no_resched();
 	schedule();
+	preempt_disable();
 
+	/* Call into cpu_idle with preempt disabled */
 	cpu_idle();
 } 
 
Index: linux-2.6/arch/i386/kernel/smpboot.c
===================================================================
--- linux-2.6.orig/arch/i386/kernel/smpboot.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/i386/kernel/smpboot.c	2005-09-22 01:04:03.000000000 +1000
@@ -478,6 +478,8 @@ set_cpu_sibling_map(int cpu)
  */
 static void __devinit start_secondary(void *unused)
 {
+	preempt_disable();
+
 	/*
 	 * Dont put anything before smp_callin(), SMP
 	 * booting is too fragile that we want to limit the
Index: linux-2.6/arch/ia64/kernel/smpboot.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/smpboot.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/ia64/kernel/smpboot.c	2005-09-22 01:04:03.000000000 +1000
@@ -394,6 +394,8 @@ smp_callin (void)
 int __devinit
 start_secondary (void *unused)
 {
+	preempt_disable();
+
 	/* Early console may use I/O ports */
 	ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase));
 	Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id());
Index: linux-2.6/arch/ppc64/kernel/smp.c
===================================================================
--- linux-2.6.orig/arch/ppc64/kernel/smp.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/ppc64/kernel/smp.c	2005-09-22 01:04:03.000000000 +1000
@@ -545,7 +545,10 @@ int __devinit __cpu_up(unsigned int cpu)
 /* Activate a secondary processor. */
 int __devinit start_secondary(void *unused)
 {
-	unsigned int cpu = smp_processor_id();
+	unsigned int cpu;
+
+	preempt_disable();
+	cpu = smp_processor_id();
 
 	atomic_inc(&init_mm.mm_count);
 	current->active_mm = &init_mm;
Index: linux-2.6/arch/sparc64/kernel/smp.c
===================================================================
--- linux-2.6.orig/arch/sparc64/kernel/smp.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/sparc64/kernel/smp.c	2005-09-22 01:04:03.000000000 +1000
@@ -147,6 +147,9 @@ void __init smp_callin(void)
 		rmb();
 
 	cpu_set(cpuid, cpu_online_map);
+
+	/* idle thread is expected to have preempt disabled */
+	preempt_disable();
 }
 
 void cpu_panic(void)
Index: linux-2.6/arch/s390/kernel/smp.c
===================================================================
--- linux-2.6.orig/arch/s390/kernel/smp.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/s390/kernel/smp.c	2005-09-22 01:04:03.000000000 +1000
@@ -531,6 +531,8 @@ extern void pfault_fini(void);
 
 int __devinit start_secondary(void *cpuvoid)
 {
+	preempt_disable();
+
         /* Setup the cpu */
         cpu_init();
         /* init per CPU timer */
Index: linux-2.6/arch/m32r/kernel/process.c
===================================================================
--- linux-2.6.orig/arch/m32r/kernel/process.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/m32r/kernel/process.c	2005-09-22 01:04:03.000000000 +1000
@@ -104,7 +104,9 @@ void cpu_idle (void)
 
 			idle();
 		}
+		preempt_enable_no_resched();
 		schedule();
+		preempt_disable();
 	}
 }
 
Index: linux-2.6/arch/frv/kernel/process.c
===================================================================
--- linux-2.6.orig/arch/frv/kernel/process.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/frv/kernel/process.c	2005-09-22 01:04:03.000000000 +1000
@@ -77,16 +77,20 @@ void (*idle)(void) = core_sleep_idle;
  */
 void cpu_idle(void)
 {
+	int cpu = smp_processor_id();
+
 	/* endless idle loop with no priority at all */
 	while (1) {
 		while (!need_resched()) {
-			irq_stat[smp_processor_id()].idle_timestamp = jiffies;
+			irq_stat[cpu].idle_timestamp = jiffies;
 
 			if (!frv_dma_inprogress && idle)
 				idle();
 		}
 
+		preempt_enable_no_resched();
 		schedule();
+		preempt_disable();
 	}
 }
 
Index: linux-2.6/arch/cris/kernel/process.c
===================================================================
--- linux-2.6.orig/arch/cris/kernel/process.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/cris/kernel/process.c	2005-09-22 01:04:03.000000000 +1000
@@ -218,7 +218,9 @@ void cpu_idle (void)
 				idle = default_idle;
 			idle();
 		}
+		preempt_enable_no_resched();
 		schedule();
+		preempt_disable();
 	}
 }
 
Index: linux-2.6/arch/mips/kernel/smp.c
===================================================================
--- linux-2.6.orig/arch/mips/kernel/smp.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/mips/kernel/smp.c	2005-09-22 01:04:03.000000000 +1000
@@ -83,7 +83,11 @@ extern ATTRIB_NORET void cpu_idle(void);
  */
 asmlinkage void start_secondary(void)
 {
-	unsigned int cpu = smp_processor_id();
+	unsigned int cpu;
+
+	preempt_disable();
+
+	cpu = smp_processor_id();
 
 	cpu_probe();
 	cpu_report();
Index: linux-2.6/arch/ppc/kernel/smp.c
===================================================================
--- linux-2.6.orig/arch/ppc/kernel/smp.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/ppc/kernel/smp.c	2005-09-22 01:04:03.000000000 +1000
@@ -339,6 +339,8 @@ int __devinit start_secondary(void *unus
 {
 	int cpu;
 
+	preempt_disable();
+
 	atomic_inc(&init_mm.mm_count);
 	current->active_mm = &init_mm;
 
Index: linux-2.6/arch/m68k/kernel/process.c
===================================================================
--- linux-2.6.orig/arch/m68k/kernel/process.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/m68k/kernel/process.c	2005-09-22 01:04:03.000000000 +1000
@@ -102,7 +102,9 @@ void cpu_idle(void)
 	while (1) {
 		while (!need_resched())
 			idle();
+		preempt_enable_no_resched();
 		schedule();
+		preempt_disable();
 	}
 }
 
Index: linux-2.6/arch/mips/kernel/process.c
===================================================================
--- linux-2.6.orig/arch/mips/kernel/process.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/mips/kernel/process.c	2005-09-22 01:04:03.000000000 +1000
@@ -58,7 +58,9 @@ ATTRIB_NORET void cpu_idle(void)
 		while (!need_resched())
 			if (cpu_wait)
 				(*cpu_wait)();
+		preempt_enable_no_resched();
 		schedule();
+		preempt_disable()
 	}
 }
 
Index: linux-2.6/arch/sh/kernel/smp.c
===================================================================
--- linux-2.6.orig/arch/sh/kernel/smp.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/sh/kernel/smp.c	2005-09-22 01:04:03.000000000 +1000
@@ -109,7 +109,11 @@ int __cpu_up(unsigned int cpu)
 
 int start_secondary(void *unused)
 {
-	unsigned int cpu = smp_processor_id();
+	unsigned int cpu;
+
+	preempt_disable();
+
+	cpu = smp_processor_id();
 
 	atomic_inc(&init_mm.mm_count);
 	current->active_mm = &init_mm;
Index: linux-2.6/arch/parisc/kernel/smp.c
===================================================================
--- linux-2.6.orig/arch/parisc/kernel/smp.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/parisc/kernel/smp.c	2005-09-22 01:04:03.000000000 +1000
@@ -462,6 +462,8 @@ void __init smp_callin(void)
 	void *istack;
 #endif
 
+	preempt_disable();
+
 	smp_cpu_init(slave_id);
 
 #if 0	/* NOT WORKING YET - see entry.S */
Index: linux-2.6/arch/m32r/kernel/smpboot.c
===================================================================
--- linux-2.6.orig/arch/m32r/kernel/smpboot.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/m32r/kernel/smpboot.c	2005-09-22 01:04:03.000000000 +1000
@@ -425,6 +425,7 @@ void __init smp_cpus_done(unsigned int m
  *==========================================================================*/
 int __init start_secondary(void *unused)
 {
+	preempt_disable();
 	cpu_init();
 	smp_callin();
 	while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
Index: linux-2.6/arch/arm26/kernel/process.c
===================================================================
--- linux-2.6.orig/arch/arm26/kernel/process.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/arm26/kernel/process.c	2005-09-22 01:04:03.000000000 +1000
@@ -74,15 +74,13 @@ __setup("hlt", hlt_setup);
 void cpu_idle(void)
 {
 	/* endless idle loop with no priority at all */
-	preempt_disable();
 	while (1) {
-		while (!need_resched()) {
-			local_irq_disable();
-			if (!need_resched() && !hlt_counter)
-				local_irq_enable();
-		}
+		while (!need_resched())
+			cpu_relax();
+		preempt_enable_no_resched();
+		schedule();
+		preempt_disable();
 	}
-	schedule();
 }
 
 static char reboot_mode = 'h';
Index: linux-2.6/arch/arm/kernel/process.c
===================================================================
--- linux-2.6.orig/arch/arm/kernel/process.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/arm/kernel/process.c	2005-09-22 01:04:03.000000000 +1000
@@ -107,13 +107,13 @@ void cpu_idle(void)
 		void (*idle)(void) = pm_idle;
 		if (!idle)
 			idle = default_idle;
-		preempt_disable();
 		leds_event(led_idle_start);
 		while (!need_resched())
 			idle();
 		leds_event(led_idle_end);
-		preempt_enable();
+		preempt_enable_no_resched();
 		schedule();
+		preempt_disable();
 	}
 }
 
Index: linux-2.6/arch/h8300/kernel/process.c
===================================================================
--- linux-2.6.orig/arch/h8300/kernel/process.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/h8300/kernel/process.c	2005-09-22 01:04:03.000000000 +1000
@@ -53,22 +53,18 @@ asmlinkage void ret_from_fork(void);
 #if !defined(CONFIG_H8300H_SIM) && !defined(CONFIG_H8S_SIM)
 void default_idle(void)
 {
-	while(1) {
-		if (!need_resched()) {
-			local_irq_enable();
-			__asm__("sleep");
-			local_irq_disable();
-		}
-		schedule();
-	}
+	local_irq_disable();
+	if (!need_resched()) {
+		local_irq_enable();
+		/* XXX: race here! What if need_resched() gets set now? */
+		__asm__("sleep");
+	} else
+		local_irq_enable();
 }
 #else
 void default_idle(void)
 {
-	while(1) {
-		if (need_resched())
-			schedule();
-	}
+	cpu_relax();
 }
 #endif
 void (*idle)(void) = default_idle;
@@ -81,7 +77,13 @@ void (*idle)(void) = default_idle;
  */
 void cpu_idle(void)
 {
-	idle();
+	while (1) {
+		while (!need_resched())
+			idle();
+		preempt_enable_no_resched();
+		schedule();
+		preempt_disable();
+	}
 }
 
 void machine_restart(char * __unused)
Index: linux-2.6/arch/xtensa/kernel/process.c
===================================================================
--- linux-2.6.orig/arch/xtensa/kernel/process.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/xtensa/kernel/process.c	2005-09-22 01:04:03.000000000 +1000
@@ -96,8 +96,9 @@ void cpu_idle(void)
 	while (1) {
 		while (!need_resched())
 			platform_idle();
-		preempt_enable();
+		preempt_enable_no_resched();
 		schedule();
+		preempt_disable();
 	}
 }
 
Index: linux-2.6/arch/v850/kernel/process.c
===================================================================
--- linux-2.6.orig/arch/v850/kernel/process.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/v850/kernel/process.c	2005-09-22 01:04:03.000000000 +1000
@@ -36,11 +36,8 @@ extern void ret_from_fork (void);
 /* The idle loop.  */
 void default_idle (void)
 {
-	while (1) {
-		while (! need_resched ())
-			asm ("halt; nop; nop; nop; nop; nop" ::: "cc");
-		schedule ();
-	}
+	while (! need_resched ())
+		asm ("halt; nop; nop; nop; nop; nop" ::: "cc");
 }
 
 void (*idle)(void) = default_idle;
@@ -54,7 +51,14 @@ void (*idle)(void) = default_idle;
 void cpu_idle (void)
 {
 	/* endless idle loop with no priority at all */
-	(*idle) ();
+	while (1) {
+		while (!need_resched())
+			(*idle) ();
+
+		preempt_enable_no_resched();
+		schedule();
+		preempt_disable();
+	}
 }
 
 /*
Index: linux-2.6/arch/ppc64/kernel/iSeries_setup.c
===================================================================
--- linux-2.6.orig/arch/ppc64/kernel/iSeries_setup.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/ppc64/kernel/iSeries_setup.c	2005-09-22 01:04:03.000000000 +1000
@@ -898,7 +898,9 @@ static int iseries_shared_idle(void)
 		if (hvlpevent_is_pending())
 			process_iSeries_events();
 
+		preempt_enable_no_resched();
 		schedule();
+		preempt_disable();
 	}
 
 	return 0;
@@ -932,7 +934,9 @@ static int iseries_dedicated_idle(void)
 		}
 
 		ppc64_runlatch_on();
+		preempt_enable_no_resched();
 		schedule();
+		preempt_disable();
 	}
 
 	return 0;
Index: linux-2.6/arch/x86_64/kernel/smpboot.c
===================================================================
--- linux-2.6.orig/arch/x86_64/kernel/smpboot.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/x86_64/kernel/smpboot.c	2005-09-22 01:04:03.000000000 +1000
@@ -473,6 +473,7 @@ void __cpuinit start_secondary(void)
 	 * booting is too fragile that we want to limit the
 	 * things done here to the most necessary things.
 	 */
+	preempt_disable();
 	cpu_init();
 	smp_callin();
 
Index: linux-2.6/arch/arm/kernel/smp.c
===================================================================
--- linux-2.6.orig/arch/arm/kernel/smp.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/arm/kernel/smp.c	2005-09-22 01:04:03.000000000 +1000
@@ -162,7 +162,10 @@ int __cpuinit __cpu_up(unsigned int cpu)
 asmlinkage void __cpuinit secondary_start_kernel(void)
 {
 	struct mm_struct *mm = &init_mm;
-	unsigned int cpu = smp_processor_id();
+	unsigned int cpu;
+
+	preempt_disable();
+	cpu = smp_processor_id();
 
 	printk("CPU%u: Booted secondary processor\n", cpu);
 
Index: linux-2.6/arch/cris/arch-v32/kernel/smp.c
===================================================================
--- linux-2.6.orig/arch/cris/arch-v32/kernel/smp.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/cris/arch-v32/kernel/smp.c	2005-09-22 01:04:03.000000000 +1000
@@ -144,6 +144,8 @@ void __init smp_callin(void)
 	int cpu = cpu_now_booting;
 	reg_intr_vect_rw_mask vect_mask = {0};
 
+	preempt_disable();
+
 	/* Initialise the idle task for this CPU */
 	atomic_inc(&init_mm.mm_count);
 	current->active_mm = &init_mm;
Index: linux-2.6/arch/i386/kernel/process.c
===================================================================
--- linux-2.6.orig/arch/i386/kernel/process.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/i386/kernel/process.c	2005-09-22 01:04:03.000000000 +1000
@@ -181,7 +181,7 @@ static inline void play_dead(void)
  */
 void cpu_idle(void)
 {
-	int cpu = raw_smp_processor_id();
+	int cpu = smp_processor_id();
 
 	/* endless idle loop with no priority at all */
 	while (1) {
@@ -203,7 +203,9 @@ void cpu_idle(void)
 			__get_cpu_var(irq_stat).idle_timestamp = jiffies;
 			idle();
 		}
+		preempt_enable_no_resched();
 		schedule();
+		preempt_disable();
 	}
 }
 
Index: linux-2.6/arch/ia64/kernel/process.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/process.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/ia64/kernel/process.c	2005-09-22 01:04:03.000000000 +1000
@@ -292,7 +292,9 @@ cpu_idle (void)
 #ifdef CONFIG_SMP
 		normal_xtp();
 #endif
+		preempt_enable_no_resched();
 		schedule();
+		preempt_disable();
 		check_pgt_cache();
 		if (cpu_is_offline(smp_processor_id()))
 			play_dead();
Index: linux-2.6/arch/parisc/kernel/process.c
===================================================================
--- linux-2.6.orig/arch/parisc/kernel/process.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/parisc/kernel/process.c	2005-09-22 01:04:03.000000000 +1000
@@ -92,7 +92,9 @@ void cpu_idle(void)
 	while (1) {
 		while (!need_resched())
 			barrier();
+		preempt_enable_no_resched();
 		schedule();
+		preempt_disable();
 		check_pgt_cache();
 	}
 }
Index: linux-2.6/arch/s390/kernel/process.c
===================================================================
--- linux-2.6.orig/arch/s390/kernel/process.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/s390/kernel/process.c	2005-09-22 01:05:06.000000000 +1000
@@ -102,7 +102,6 @@ void default_idle(void)
 	local_irq_disable();
         if (need_resched()) {
 		local_irq_enable();
-                schedule();
                 return;
         }
 
@@ -139,8 +138,14 @@ void default_idle(void)
 
 void cpu_idle(void)
 {
-	for (;;)
-		default_idle();
+	for (;;) {
+		while (!need_resched())
+			default_idle();
+
+		preempt_enable_no_resched();
+		schedule();
+		preempt_disable();
+	}
 }
 
 void show_regs(struct pt_regs *regs)
Index: linux-2.6/arch/sh/kernel/process.c
===================================================================
--- linux-2.6.orig/arch/sh/kernel/process.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/sh/kernel/process.c	2005-09-22 01:04:03.000000000 +1000
@@ -64,7 +64,9 @@ void default_idle(void)
 				cpu_sleep();
 		}
 
+		preempt_enable_no_resched();
 		schedule();
+		preempt_disable();
 	}
 }
 
Index: linux-2.6/arch/sh64/kernel/process.c
===================================================================
--- linux-2.6.orig/arch/sh64/kernel/process.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/sh64/kernel/process.c	2005-09-22 01:04:03.000000000 +1000
@@ -334,7 +334,9 @@ void default_idle(void)
 			}
 			local_irq_enable();
 		}
+		preempt_enable_no_resched();
 		schedule();
+		preempt_disable();
 	}
 }
 
Index: linux-2.6/arch/sparc/kernel/process.c
===================================================================
--- linux-2.6.orig/arch/sparc/kernel/process.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/sparc/kernel/process.c	2005-09-22 01:04:03.000000000 +1000
@@ -120,7 +120,9 @@ void cpu_idle(void)
 			(*pm_idle)();
 		}
 
+		preempt_enable_no_resched();
 		schedule();
+		preempt_disable();
 		check_pgt_cache();
 	}
 }
@@ -133,7 +135,9 @@ void cpu_idle(void)
 	/* endless idle loop with no priority at all */
 	while(1) {
 		if(need_resched()) {
+			preempt_enable_no_resched();
 			schedule();
+			preempt_disable();
 			check_pgt_cache();
 		}
 		barrier(); /* or else gcc optimizes... */
Index: linux-2.6/arch/sparc64/kernel/process.c
===================================================================
--- linux-2.6.orig/arch/sparc64/kernel/process.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/sparc64/kernel/process.c	2005-09-22 01:04:03.000000000 +1000
@@ -74,7 +74,9 @@ void cpu_idle(void)
 		while (!need_resched())
 			barrier();
 
+		preempt_enable_no_resched();
 		schedule();
+		preempt_disable();
 		check_pgt_cache();
 	}
 }
@@ -93,7 +95,9 @@ void cpu_idle(void)
 		if (need_resched()) {
 			unidle_me();
 			clear_thread_flag(TIF_POLLING_NRFLAG);
+			preempt_enable_no_resched();
 			schedule();
+			preempt_disable();
 			set_thread_flag(TIF_POLLING_NRFLAG);
 			check_pgt_cache();
 		}
Index: linux-2.6/arch/x86_64/kernel/process.c
===================================================================
--- linux-2.6.orig/arch/x86_64/kernel/process.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/x86_64/kernel/process.c	2005-09-22 01:04:03.000000000 +1000
@@ -204,7 +204,9 @@ void cpu_idle (void)
 			idle();
 		}
 
+		preempt_enable_no_resched();
 		schedule();
+		preempt_disable();
 	}
 }
 
Index: linux-2.6/arch/ppc/kernel/idle.c
===================================================================
--- linux-2.6.orig/arch/ppc/kernel/idle.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/ppc/kernel/idle.c	2005-09-22 01:04:03.000000000 +1000
@@ -52,10 +52,6 @@ void default_idle(void)
 		}
 #endif
 	}
-	if (need_resched())
-		schedule();
-	if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
-		cpu_die();
 }
 
 /*
@@ -63,11 +59,20 @@ void default_idle(void)
  */
 void cpu_idle(void)
 {
-	for (;;)
+	for (;;) {
 		if (ppc_md.idle != NULL)
 			ppc_md.idle();
 		else
 			default_idle();
+		if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
+			cpu_die();
+		if (need_resched()) {
+			preempt_enable_no_resched();
+			schedule();
+			preempt_disable();
+		}
+
+	}
 }
 
 #if defined(CONFIG_SYSCTL) && defined(CONFIG_6xx)
Index: linux-2.6/arch/ppc64/kernel/pSeries_setup.c
===================================================================
--- linux-2.6.orig/arch/ppc64/kernel/pSeries_setup.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/ppc64/kernel/pSeries_setup.c	2005-09-22 01:04:03.000000000 +1000
@@ -537,7 +537,9 @@ static int pseries_dedicated_idle(void)
 		lpaca->lppaca.idle = 0;
 		ppc64_runlatch_on();
 
+		preempt_enable_no_resched();
 		schedule();
+		preempt_disable();
 
 		if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
 			cpu_die();
@@ -581,7 +583,9 @@ static int pseries_shared_idle(void)
 		lpaca->lppaca.idle = 0;
 		ppc64_runlatch_on();
 
+		preempt_enable_no_resched();
 		schedule();
+		preempt_disable();
 
 		if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
 			cpu_die();
Index: linux-2.6/arch/ppc64/kernel/idle.c
===================================================================
--- linux-2.6.orig/arch/ppc64/kernel/idle.c	2005-09-22 01:03:51.000000000 +1000
+++ linux-2.6/arch/ppc64/kernel/idle.c	2005-09-22 01:04:03.000000000 +1000
@@ -60,7 +60,9 @@ int default_idle(void)
 		}
 
 		ppc64_runlatch_on();
+		preempt_enable_no_resched();
 		schedule();
+		preempt_disable();
 		if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
 			cpu_die();
 	}
@@ -78,7 +80,9 @@ int native_idle(void)
 
 		if (need_resched()) {
 			ppc64_runlatch_on();
+			preempt_enable_no_resched();
 			schedule();
+			preempt_disable();
 		}
 
 		if (cpu_is_offline(smp_processor_id()) &&

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2.6.14-rc1-git5] sched: disable preempt in idle tasks
  2005-09-21 15:41 [PATCH 2.6.14-rc1-git5] sched: disable preempt in idle tasks Nick Piggin
@ 2005-09-21 21:43 ` Nigel Cunningham
  2005-09-22  1:31 ` Andrew Morton
  1 sibling, 0 replies; 10+ messages in thread
From: Nigel Cunningham @ 2005-09-21 21:43 UTC (permalink / raw)
  To: Nick Piggin
  Cc: Andrew Morton, Li Shaohua, Srivatsa Vaddagiri,
	Linux Kernel Mailing List, Ian Molton

Hi Nick et al.

On Thu, 2005-09-22 at 01:41, Nick Piggin wrote:
> This patch should hopefully fix Nigel's bug.
> 
> Split out from sched-resched-opt.patch. Tested on i386 with acpi idle
> and poll idle (previous iterations tested on various other architectures).
> 
> CCed Ian because I am amazed that arm26 ever managed to reschedule
> out of the idle task without this... what am I missing?
> 
> Andrew please apply

I'll give it a whirl when I get into work and let you know how I go.

Regards,

Nigel


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2.6.14-rc1-git5] sched: disable preempt in idle tasks
  2005-09-21 15:41 [PATCH 2.6.14-rc1-git5] sched: disable preempt in idle tasks Nick Piggin
  2005-09-21 21:43 ` Nigel Cunningham
@ 2005-09-22  1:31 ` Andrew Morton
  2005-09-22  3:25   ` Nick Piggin
  1 sibling, 1 reply; 10+ messages in thread
From: Andrew Morton @ 2005-09-22  1:31 UTC (permalink / raw)
  To: Nick Piggin; +Cc: ncunningham, shaohua.li, vatsa, Linux-Kernel, spyro

Nick Piggin <nickpiggin@yahoo.com.au> wrote:
>
> This patch should hopefully fix Nigel's bug.
> 
>  Split out from sched-resched-opt.patch. Tested on i386 with acpi idle
>  and poll idle (previous iterations tested on various other architectures).

This makes the emt64 machine reboot itself, which iirc was the behaviour in
the failing patch from which this one was split out.

The machine is using acpi_processor_idle().


Wed Sep 21 16:15:07 PDT 2005                                                 
Bootdata ok (command line is ro root=/dev/sda3 console=ttyS0)                
Linux version 2.6.14-rc2-mm1 (akpm@x) (gcc version 3.4.2 20041017 (Red Hat 3.4.5
BIOS-provided physical RAM map:                                                
 BIOS-e820: 0000000000000000 - 000000000009fc00 (usable)                     
 BIOS-e820: 000000000009fc00 - 00000000000a0000 (reserved)                   
 BIOS-e820: 00000000000ebbd0 - 0000000000100000 (reserved)
 BIOS-e820: 0000000000100000 - 000000007ffd0000 (usable)  
 BIOS-e820: 000000007ffd0000 - 000000007ffdf000 (ACPI data)
 BIOS-e820: 000000007ffdf000 - 0000000080000000 (ACPI NVS) 
 BIOS-e820: 00000000e0000000 - 00000000f0000000 (reserved)
 BIOS-e820: 00000000ffc00000 - 0000000100000000 (reserved)
 BIOS-e820: 0000000100000000 - 0000000180000000 (usable)  
ACPI: PM-Timer IO Port: 0x408                           
ACPI: LAPIC (acpi_id[0x01] lapic_id[0x00] enabled)
Processor #0 15:3 APIC version 20                 
ACPI: LAPIC (acpi_id[0x02] lapic_id[0x06] enabled)
Processor #6 15:3 APIC version 20                 
ACPI: LAPIC (acpi_id[0x03] lapic_id[0x01] enabled)
Processor #1 15:3 APIC version 20                 
ACPI: LAPIC (acpi_id[0x04] lapic_id[0x07] enabled)
Processor #7 15:3 APIC version 20                 
ACPI: IOAPIC (id[0x08] address[0xfec00000] gsi_base[0])
IOAPIC[0]: apic_id 8, version 32, address 0xfec00000, GSI 0-23
ACPI: IOAPIC (id[0x09] address[0xfec81000] gsi_base[24])      
IOAPIC[1]: apic_id 9, version 32, address 0xfec81000, GSI 24-47
ACPI: IOAPIC (id[0x0a] address[0xfec81400] gsi_base[48])       
IOAPIC[2]: apic_id 10, version 32, address 0xfec81400, GSI 48-71
ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl)        
ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 high level)
Setting APIC routing to flat                               
ACPI: HPET id: 0x8086a202 base: 0xfed00000
Using ACPI (MADT) for SMP configuration information
Allocating PCI resources starting at 88000000 (gap: 80000000:60000000)
Checking aperture...                                                  
Built 1 zonelists   
Initializing CPU#0
Kernel command line: ro root=/dev/sda3 console=ttyS0
PID hash table entries: 4096 (order: 12, 131072 bytes)
time.c: Using 3.579545 MHz PM timer.                  
time.c: Detected 3400.276 MHz processor.
Console: colour VGA+ 80x25              
Dentry cache hash table entries: 524288 (order: 10, 4194304 bytes)
Inode-cache hash table entries: 262144 (order: 9, 2097152 bytes)  
Placing software IO TLB between 0x6a81000 - 0xaa81000           
Memory: 4029344k/6291456k available (3009k kernel code, 164152k reserved, 1758k)
Calibrating delay using timer specific routine.. 6810.03 BogoMIPS (lpj=13620075)
Mount-cache hash table entries: 256                                            
CPU: Trace cache: 12K uops, L1 D cache: 16K
CPU: L2 cache: 1024K                       
using mwait in idle threads.
CPU: Physical Processor ID: 0
CPU0: Thermal monitoring enabled (TM1)
mtrr: v2.0 (20020519)                 
 tbxface-0109 [02] load_tables           : ACPI Tables successfully acquired
Parsing all Control Methods:....................................................
Table [DSDT](id 0005) - 461 Objects with 50 Devices 130 Methods 11 Regions     
ACPI Namespace successfully loaded at root ffffffff806078c0               
evxfevnt-0091 [03] enable                : Transition to ACPI mode successful
Using local APIC timer interrupts.                                           
Detected 12.500 MHz APIC timer.   
setup_APIC_timer               
done            
softlockup thread 0 started up.
Booting processor 1/4 APIC 0x6 
                             


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2.6.14-rc1-git5] sched: disable preempt in idle tasks
  2005-09-22  1:31 ` Andrew Morton
@ 2005-09-22  3:25   ` Nick Piggin
  2005-09-22  9:03     ` Andi Kleen
                       ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Nick Piggin @ 2005-09-22  3:25 UTC (permalink / raw)
  To: Andrew Morton
  Cc: ncunningham, shaohua.li, vatsa, Linux-Kernel, spyro, Andi Kleen

[-- Attachment #1: Type: text/plain, Size: 654 bytes --]

Andrew Morton wrote:
> Nick Piggin <nickpiggin@yahoo.com.au> wrote:
> 
>>This patch should hopefully fix Nigel's bug.
>>
>> Split out from sched-resched-opt.patch. Tested on i386 with acpi idle
>> and poll idle (previous iterations tested on various other architectures).
> 
> 
> This makes the emt64 machine reboot itself, which iirc was the behaviour in
> the failing patch from which this one was split out.
> 
> The machine is using acpi_processor_idle().
> 

OK, thanks. That must be the preempt_disable() being called in
start_secondary(). Maybe I should have listened to the comment.

Can you try the following patch?

-- 
SUSE Labs, Novell Inc.


[-- Attachment #2: sched-no-preempt-idle-x86-64-fix.patch --]
[-- Type: text/plain, Size: 596 bytes --]

Index: linux-2.6/arch/x86_64/kernel/smpboot.c
===================================================================
--- linux-2.6.orig/arch/x86_64/kernel/smpboot.c	2005-09-22 01:04:03.000000000 +1000
+++ linux-2.6/arch/x86_64/kernel/smpboot.c	2005-09-22 13:24:11.000000000 +1000
@@ -473,8 +473,8 @@ void __cpuinit start_secondary(void)
 	 * booting is too fragile that we want to limit the
 	 * things done here to the most necessary things.
 	 */
-	preempt_disable();
 	cpu_init();
+	preempt_disable();
 	smp_callin();
 
 	/* otherwise gcc will move up the smp_processor_id before the cpu_init */

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2.6.14-rc1-git5] sched: disable preempt in idle tasks
  2005-09-22  3:25   ` Nick Piggin
@ 2005-09-22  9:03     ` Andi Kleen
  2005-09-25 23:24     ` Nigel Cunningham
  2005-10-06 23:03     ` Nigel Cunningham
  2 siblings, 0 replies; 10+ messages in thread
From: Andi Kleen @ 2005-09-22  9:03 UTC (permalink / raw)
  To: Nick Piggin
  Cc: Andrew Morton, ncunningham, shaohua.li, vatsa, Linux-Kernel,
	spyro

On Thursday 22 September 2005 05:25, Nick Piggin wrote:

>
> OK, thanks. That must be the preempt_disable() being called in
> start_secondary(). Maybe I should have listened to the comment.
>
> Can you try the following patch?

The reason it broke was that current doesn't work before cpu_init() -
and preempt_disable does just that.

-Andi

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2.6.14-rc1-git5] sched: disable preempt in idle tasks
  2005-09-22  3:25   ` Nick Piggin
  2005-09-22  9:03     ` Andi Kleen
@ 2005-09-25 23:24     ` Nigel Cunningham
  2005-10-06 23:03     ` Nigel Cunningham
  2 siblings, 0 replies; 10+ messages in thread
From: Nigel Cunningham @ 2005-09-25 23:24 UTC (permalink / raw)
  To: Nick Piggin
  Cc: Andrew Morton, shaohua.li, vatsa, Linux Kernel Mailing List,
	spyro, Andi Kleen

Hi.

On Thu, 2005-09-22 at 13:25, Nick Piggin wrote:
> Andrew Morton wrote:
> > Nick Piggin <nickpiggin@yahoo.com.au> wrote:
> > 
> >>This patch should hopefully fix Nigel's bug.
> >>
> >> Split out from sched-resched-opt.patch. Tested on i386 with acpi idle
> >> and poll idle (previous iterations tested on various other architectures).
> > 
> > 
> > This makes the emt64 machine reboot itself, which iirc was the behaviour in
> > the failing patch from which this one was split out.
> > 
> > The machine is using acpi_processor_idle().
> > 
> 
> OK, thanks. That must be the preempt_disable() being called in
> start_secondary(). Maybe I should have listened to the comment.
> 
> Can you try the following patch?


Well, I did manage to reproduce the bug again without Nick's patches. It
seems it only occurs when I really want it to suspend because I'm going
home :). I'll apply Nick's patches now and give it some testing for a
few days.

Regards,

Nigel



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2.6.14-rc1-git5] sched: disable preempt in idle tasks
  2005-09-22  3:25   ` Nick Piggin
  2005-09-22  9:03     ` Andi Kleen
  2005-09-25 23:24     ` Nigel Cunningham
@ 2005-10-06 23:03     ` Nigel Cunningham
  2 siblings, 0 replies; 10+ messages in thread
From: Nigel Cunningham @ 2005-10-06 23:03 UTC (permalink / raw)
  To: Nick Piggin
  Cc: Andrew Morton, shaohua.li, vatsa, Linux Kernel Mailing List,
	spyro, Andi Kleen

Hi.

On Thu, 2005-09-22 at 13:25, Nick Piggin wrote:
> Andrew Morton wrote:
> > Nick Piggin <nickpiggin@yahoo.com.au> wrote:
> > 
> >>This patch should hopefully fix Nigel's bug.
> >>
> >> Split out from sched-resched-opt.patch. Tested on i386 with acpi idle
> >> and poll idle (previous iterations tested on various other architectures).
> > 
> > 
> > This makes the emt64 machine reboot itself, which iirc was the behaviour in
> > the failing patch from which this one was split out.
> > 
> > The machine is using acpi_processor_idle().
> > 
> 
> OK, thanks. That must be the preempt_disable() being called in
> start_secondary(). Maybe I should have listened to the comment.
> 
> Can you try the following patch?

Ok. Well I've fun with that patch for a couple of weeks and had no
recurrences of the issue whatsoever - until I upgraded my kernel
yesterday and forgot to apply it again. In short, it seems to fix the
problem here.

Regards,

Nigel


^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH 2.6.14-rc1-git5] sched: disable preempt in idle tasks
@ 2005-11-02  2:33 Li, Shaohua
  2005-11-02  2:46 ` Nick Piggin
  0 siblings, 1 reply; 10+ messages in thread
From: Li, Shaohua @ 2005-11-02  2:33 UTC (permalink / raw)
  To: Nick Piggin, Andrew Morton, Nigel Cunningham, Srivatsa Vaddagiri,
	Linux Kernel Mailing List, Ian Molton

Hi Nick,
>This patch should hopefully fix Nigel's bug.
>
>Split out from sched-resched-opt.patch. Tested on i386 with acpi idle
>and poll idle (previous iterations tested on various other
architectures).
>
>CCed Ian because I am amazed that arm26 ever managed to reschedule
>out of the idle task without this... what am I missing?
>
>Andrew please apply
What's the status of the patch? I didn't see it in base kernel.
We found another bug related with this issue. On UP system, if a CPU
enters 
'mwait_idle', it never leaves it, as the 'mwait_idle' loop will never
end.
Disabling preempt fixes the bug. Should I submit a patch just disabling
preempt in 'mwait_idle' or wait for your patch?

Thanks,
Shaohua

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2.6.14-rc1-git5] sched: disable preempt in idle tasks
  2005-11-02  2:33 Li, Shaohua
@ 2005-11-02  2:46 ` Nick Piggin
  2005-11-02  5:04   ` Nigel Cunningham
  0 siblings, 1 reply; 10+ messages in thread
From: Nick Piggin @ 2005-11-02  2:46 UTC (permalink / raw)
  To: Li, Shaohua
  Cc: Andrew Morton, Nigel Cunningham, Srivatsa Vaddagiri,
	Linux Kernel Mailing List, Ian Molton


Hi Shaohua,

Li, Shaohua wrote:

> 
> What's the status of the patch? I didn't see it in base kernel.
> We found another bug related with this issue. On UP system, if a CPU
> enters 
> 'mwait_idle', it never leaves it, as the 'mwait_idle' loop will never
> end.
> Disabling preempt fixes the bug. Should I submit a patch just disabling
> preempt in 'mwait_idle' or wait for your patch?
> 

The patch is in Andrew's tree, and it should get merged for 2.6.15.
If you have verified that disabling preempt in mwait_idle fixes the
bug, then you may like to send that to the 2.6.14.stable guys.

Thanks,
Nick

-- 
SUSE Labs, Novell Inc.

Send instant messages to your online friends http://au.messenger.yahoo.com 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2.6.14-rc1-git5] sched: disable preempt in idle tasks
  2005-11-02  2:46 ` Nick Piggin
@ 2005-11-02  5:04   ` Nigel Cunningham
  0 siblings, 0 replies; 10+ messages in thread
From: Nigel Cunningham @ 2005-11-02  5:04 UTC (permalink / raw)
  To: Nick Piggin
  Cc: Li Shaohua, Andrew Morton, Srivatsa Vaddagiri,
	Linux Kernel Mailing List, Ian Molton

Hi Nick.

On Wed, 2005-11-02 at 13:46, Nick Piggin wrote:
> Hi Shaohua,
> 
> Li, Shaohua wrote:
> 
> > 
> > What's the status of the patch? I didn't see it in base kernel.
> > We found another bug related with this issue. On UP system, if a CPU
> > enters 
> > 'mwait_idle', it never leaves it, as the 'mwait_idle' loop will never
> > end.
> > Disabling preempt fixes the bug. Should I submit a patch just disabling
> > preempt in 'mwait_idle' or wait for your patch?
> > 
> 
> The patch is in Andrew's tree, and it should get merged for 2.6.15.
> If you have verified that disabling preempt in mwait_idle fixes the
> bug, then you may like to send that to the 2.6.14.stable guys.

I sent an email a couple of weeks ago saying that it looked like it did
the trick for me - no problems in two weeks of testing. (I would have
easily seen it within a day or two prior to this).

Regards,

Nigel

> Thanks,
> Nick
-- 



^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2005-11-02  5:07 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-09-21 15:41 [PATCH 2.6.14-rc1-git5] sched: disable preempt in idle tasks Nick Piggin
2005-09-21 21:43 ` Nigel Cunningham
2005-09-22  1:31 ` Andrew Morton
2005-09-22  3:25   ` Nick Piggin
2005-09-22  9:03     ` Andi Kleen
2005-09-25 23:24     ` Nigel Cunningham
2005-10-06 23:03     ` Nigel Cunningham
  -- strict thread matches above, loose matches on Subject: below --
2005-11-02  2:33 Li, Shaohua
2005-11-02  2:46 ` Nick Piggin
2005-11-02  5:04   ` Nigel Cunningham

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox