During 2.5.5-pre, an optimization was made that removed schedule_tail
from UP kernels. This causes the initial preempt_count of a new task,
which starts at 1, to never decrement to zero and thus never become
preemptible.
Thanks to everyone who pointed out the lousy performance - it took
awhile to find but it should be fixed now. Please comment if not.
Patch is against 2.5.6-pre2 and is critical for all UP+preempt users.
Robert Love
diff -urN linux-2.5.6-pre2/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- linux-2.5.6-pre2/arch/alpha/kernel/entry.S Fri Mar 1 17:21:14 2002
+++ linux/arch/alpha/kernel/entry.S Mon Mar 4 17:49:27 2002
@@ -495,7 +495,7 @@
ret $31,($26),1
.end alpha_switch_to
-#ifdef CONFIG_SMP
+#ifdef CONFIG_SMP || CONFIG_PREEMPT
.globl ret_from_fork
.align 3
.ent ret_from_fork
diff -urN linux-2.5.6-pre2/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- linux-2.5.6-pre2/arch/i386/kernel/entry.S Tue Feb 19 21:10:58 2002
+++ linux/arch/i386/kernel/entry.S Mon Mar 4 17:48:32 2002
@@ -195,7 +195,7 @@
ENTRY(ret_from_fork)
-#if CONFIG_SMP
+#if CONFIG_SMP || CONFIG_PREEMPT
call SYMBOL_NAME(schedule_tail)
#endif
GET_THREAD_INFO(%ebx)
diff -urN linux-2.5.6-pre2/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S
--- linux-2.5.6-pre2/arch/ppc/kernel/entry.S Tue Feb 19 21:10:59 2002
+++ linux/arch/ppc/kernel/entry.S Mon Mar 4 17:48:41 2002
@@ -343,7 +343,7 @@
.globl ret_from_fork
ret_from_fork:
-#ifdef CONFIG_SMP
+#ifdef CONFIG_SMP || CONFIG_PREEMPT
bl schedule_tail
#endif
rlwinm r3,r1,0,0,18
diff -urN linux-2.5.6-pre2/arch/ppc64/kernel/entry.S linux/arch/ppc64/kernel/entry.S
--- linux-2.5.6-pre2/arch/ppc64/kernel/entry.S Tue Feb 19 21:10:53 2002
+++ linux/arch/ppc64/kernel/entry.S Mon Mar 4 17:52:16 2002
@@ -311,7 +311,7 @@
blr
_GLOBAL(ret_from_fork)
-#ifdef CONFIG_SMP
+#ifdef CONFIG_SMP || CONFIG_PREEMPT
bl .schedule_tail
#endif
clrrdi r4,r1,THREAD_SHIFT
diff -urN linux-2.5.6-pre2/arch/s390/kernel/entry.S linux/arch/s390/kernel/entry.S
--- linux-2.5.6-pre2/arch/s390/kernel/entry.S Tue Feb 19 21:10:57 2002
+++ linux/arch/s390/kernel/entry.S Mon Mar 4 17:48:12 2002
@@ -295,7 +295,7 @@
stosm 24(%r15),0x03 # reenable interrupts
sr %r0,%r0 # child returns 0
st %r0,SP_R2(%r15) # store return value (change R2 on stack)
-#ifdef CONFIG_SMP
+#ifdef CONFIG_SMP || CONFIG_PREEMPT
l %r1,BASED(.Lschedtail)
la %r14,BASED(sysc_return)
br %r1 # call schedule_tail, return to sysc_return
@@ -896,7 +896,7 @@
#error .Ltrace: .long syscall_trace
.Lvfork: .long sys_vfork
-#ifdef CONFIG_SMP
+#ifdef CONFIG_SMP || CONFIG_PREEMPT
.Lschedtail: .long schedule_tail
#endif
diff -urN linux-2.5.6-pre2/arch/s390x/kernel/entry.S linux/arch/s390x/kernel/entry.S
--- linux-2.5.6-pre2/arch/s390x/kernel/entry.S Tue Feb 19 21:10:58 2002
+++ linux/arch/s390x/kernel/entry.S Mon Mar 4 17:53:31 2002
@@ -280,7 +280,7 @@
GET_CURRENT # load pointer to task_struct to R9
stosm 48(%r15),0x03 # reenable interrupts
xc SP_R2(8,%r15),SP_R2(%r15) # child returns 0
-#ifdef CONFIG_SMP
+#ifdef CONFIG_SMP || CONFIG_PREEMPT
larl %r14,sysc_return
jg schedule_tail # return to sysc_return
#else
diff -urN linux-2.5.6-pre2/kernel/sched.c linux/kernel/sched.c
--- linux-2.5.6-pre2/kernel/sched.c Fri Mar 1 17:21:16 2002
+++ linux/kernel/sched.c Mon Mar 4 17:54:00 2002
@@ -397,7 +397,7 @@
p->sleep_avg) / (EXIT_WEIGHT + 1);
}
-#if CONFIG_SMP
+#if CONFIG_SMP || CONFIG_PREEMPT
asmlinkage void schedule_tail(void)
{
spin_unlock_irq(&this_rq()->lock);
On Mon, Mar 04, 2002 at 07:11:23PM -0500, Robert Love wrote:
> During 2.5.5-pre, an optimization was made that removed schedule_tail
> from UP kernels. This causes the initial preempt_count of a new task,
> which starts at 1, to never decrement to zero and thus never become
> preemptible.
>
> Thanks to everyone who pointed out the lousy performance - it took
> awhile to find but it should be fixed now. Please comment if not.
>
> Patch is against 2.5.6-pre2 and is critical for all UP+preempt users.
>
> Robert Love
>
> diff -urN linux-2.5.6-pre2/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
> --- linux-2.5.6-pre2/arch/alpha/kernel/entry.S Fri Mar 1 17:21:14 2002
> +++ linux/arch/alpha/kernel/entry.S Mon Mar 4 17:49:27 2002
> @@ -495,7 +495,7 @@
> ret $31,($26),1
> .end alpha_switch_to
>
> -#ifdef CONFIG_SMP
> +#ifdef CONFIG_SMP || CONFIG_PREEMPT
Surely you really don't mean this?
--
Russell King ([email protected]) The developer of ARM Linux
http://www.arm.linux.org.uk/personal/aboutme.html
On Mon, 2002-03-04 at 19:43, Russell King wrote:
> > diff -urN linux-2.5.6-pre2/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
> > --- linux-2.5.6-pre2/arch/alpha/kernel/entry.S Fri Mar 1 17:21:14 2002
> > +++ linux/arch/alpha/kernel/entry.S Mon Mar 4 17:49:27 2002
> > @@ -495,7 +495,7 @@
> > ret $31,($26),1
> > .end alpha_switch_to
> >
> > -#ifdef CONFIG_SMP
> > +#ifdef CONFIG_SMP || CONFIG_PREEMPT
>
> Surely you really don't mean this?
Yes, why? We need to call schedule_tail ...
Robert Love
On Mon, Mar 04, 2002 at 07:51:33PM -0500, Robert Love wrote:
> On Mon, 2002-03-04 at 19:43, Russell King wrote:
>
> > > diff -urN linux-2.5.6-pre2/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
> > > --- linux-2.5.6-pre2/arch/alpha/kernel/entry.S Fri Mar 1 17:21:14 2002
> > > +++ linux/arch/alpha/kernel/entry.S Mon Mar 4 17:49:27 2002
> > > @@ -495,7 +495,7 @@
> > > ret $31,($26),1
> > > .end alpha_switch_to
> > >
> > > -#ifdef CONFIG_SMP
> > > +#ifdef CONFIG_SMP || CONFIG_PREEMPT
> >
> > Surely you really don't mean this?
>
> Yes, why? We need to call schedule_tail ...
It's a #ifdef, not a #if
Does this compiler message give you a better idea:
warning: extra tokens at end of #ifdef directive
--
Russell King ([email protected]) The developer of ARM Linux
http://www.arm.linux.org.uk/personal/aboutme.html
On Mon, 2002-03-04 at 19:53, Russell King wrote:
> It's a #ifdef, not a #if
Better?
Robert Love
diff -urN linux-2.5.6-pre2/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- linux-2.5.6-pre2/arch/alpha/kernel/entry.S Fri Mar 1 17:21:14 2002
+++ linux/arch/alpha/kernel/entry.S Mon Mar 4 17:49:27 2002
@@ -495,7 +495,7 @@
ret $31,($26),1
.end alpha_switch_to
-#ifdef CONFIG_SMP
+#if CONFIG_SMP || CONFIG_PREEMPT
.globl ret_from_fork
.align 3
.ent ret_from_fork
diff -urN linux-2.5.6-pre2/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- linux-2.5.6-pre2/arch/i386/kernel/entry.S Tue Feb 19 21:10:58 2002
+++ linux/arch/i386/kernel/entry.S Mon Mar 4 17:48:32 2002
@@ -195,7 +195,7 @@
ENTRY(ret_from_fork)
-#if CONFIG_SMP
+#if CONFIG_SMP || CONFIG_PREEMPT
call SYMBOL_NAME(schedule_tail)
#endif
GET_THREAD_INFO(%ebx)
diff -urN linux-2.5.6-pre2/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S
--- linux-2.5.6-pre2/arch/ppc/kernel/entry.S Tue Feb 19 21:10:59 2002
+++ linux/arch/ppc/kernel/entry.S Mon Mar 4 17:48:41 2002
@@ -343,7 +343,7 @@
.globl ret_from_fork
ret_from_fork:
-#ifdef CONFIG_SMP
+#if CONFIG_SMP || CONFIG_PREEMPT
bl schedule_tail
#endif
rlwinm r3,r1,0,0,18
diff -urN linux-2.5.6-pre2/arch/ppc64/kernel/entry.S linux/arch/ppc64/kernel/entry.S
--- linux-2.5.6-pre2/arch/ppc64/kernel/entry.S Tue Feb 19 21:10:53 2002
+++ linux/arch/ppc64/kernel/entry.S Mon Mar 4 17:52:16 2002
@@ -311,7 +311,7 @@
blr
_GLOBAL(ret_from_fork)
-#ifdef CONFIG_SMP
+#if CONFIG_SMP || CONFIG_PREEMPT
bl .schedule_tail
#endif
clrrdi r4,r1,THREAD_SHIFT
diff -urN linux-2.5.6-pre2/arch/s390/kernel/entry.S linux/arch/s390/kernel/entry.S
--- linux-2.5.6-pre2/arch/s390/kernel/entry.S Tue Feb 19 21:10:57 2002
+++ linux/arch/s390/kernel/entry.S Mon Mar 4 17:48:12 2002
@@ -295,7 +295,7 @@
stosm 24(%r15),0x03 # reenable interrupts
sr %r0,%r0 # child returns 0
st %r0,SP_R2(%r15) # store return value (change R2 on stack)
-#ifdef CONFIG_SMP
+#if CONFIG_SMP || CONFIG_PREEMPT
l %r1,BASED(.Lschedtail)
la %r14,BASED(sysc_return)
br %r1 # call schedule_tail, return to sysc_return
@@ -896,7 +896,7 @@
#error .Ltrace: .long syscall_trace
.Lvfork: .long sys_vfork
-#ifdef CONFIG_SMP
+#if CONFIG_SMP || CONFIG_PREEMPT
.Lschedtail: .long schedule_tail
#endif
diff -urN linux-2.5.6-pre2/arch/s390x/kernel/entry.S linux/arch/s390x/kernel/entry.S
--- linux-2.5.6-pre2/arch/s390x/kernel/entry.S Tue Feb 19 21:10:58 2002
+++ linux/arch/s390x/kernel/entry.S Mon Mar 4 17:53:31 2002
@@ -280,7 +280,7 @@
GET_CURRENT # load pointer to task_struct to R9
stosm 48(%r15),0x03 # reenable interrupts
xc SP_R2(8,%r15),SP_R2(%r15) # child returns 0
-#ifdef CONFIG_SMP
+#if CONFIG_SMP || CONFIG_PREEMPT
larl %r14,sysc_return
jg schedule_tail # return to sysc_return
#else
diff -urN linux-2.5.6-pre2/kernel/sched.c linux/kernel/sched.c
--- linux-2.5.6-pre2/kernel/sched.c Fri Mar 1 17:21:16 2002
+++ linux/kernel/sched.c Mon Mar 4 17:54:00 2002
@@ -397,7 +397,7 @@
p->sleep_avg) / (EXIT_WEIGHT + 1);
}
-#if CONFIG_SMP
+#if CONFIG_SMP || CONFIG_PREEMPT
asmlinkage void schedule_tail(void)
{
spin_unlock_irq(&this_rq()->lock);
> Better?
Not really
> +#if CONFIG_SMP || CONFIG_PREEMPT
#if [expression]
try
#if defined(a) || defined(b)
Interesting that the difference pre-empt makes is so large you didnt notice
you hadn't re-enabled it ;)
Alan
--
"Nothing would please me more than being able to hire ten programmers
and deluge the hobby market with good software." -- Bill Gates 1976
We are still waiting ....
On Mon, 2002-03-04 at 20:55, Alan Cox wrote:
> try
>
> #if defined(a) || defined(b)
Is that needed since the .config is defined to 1 and 0 in autoconf.h?
> Interesting that the difference pre-empt makes is so large you didnt notice
> you hadn't re-enabled it ;)
The above fix isn't needed for i386 ... and I noticed the problem in the
first place because performance was odd.
Robert Love
On Tue, Mar 05, 2002 at 01:55:05AM +0000, Alan Cox wrote:
> "Nothing would please me more than being able to hire ten programmers
> and deluge the hobby market with good software." -- Bill Gates 1976
>
> We are still waiting ....
After Bill, the deluge.
--
---------------------------------------------------------
Victor Yodaiken
Finite State Machine Labs: The RTLinux Company.
http://www.fsmlabs.com http://www.rtlinux.com
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Robert,
In one message you wrote:
> Patch [...] is critical for all UP+preempt users.
and in another (in the same thread) you write:
> The above fix isn't needed for i386
I don't understand what to do in the UP i386 case - apply or not apply?
I suspect I'm misunderstanding what you mean by "the above fix".
Ben
- --
Ben Clifford [email protected] GPG: 30F06950
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org
iD8DBQE8hEw+sYXoezDwaVARAmByAJ4iW2lVfJO61hRoAYmwige/7fyY3ACfS7Lk
ytnH2rCLgTvKgchWtt3cvVw=
=tb/c
-----END PGP SIGNATURE-----
Robert Love wrote:
>
> During 2.5.5-pre, an optimization was made that removed schedule_tail
> from UP kernels. This causes the initial preempt_count of a new task,
> which starts at 1, to never decrement to zero and thus never become
> preemptible.
>
> Thanks to everyone who pointed out the lousy performance - it took
> awhile to find but it should be fixed now. Please comment if not.
>
> Patch is against 2.5.6-pre2 and is critical for all UP+preempt users.
With out a lot of looking, wouldn't it be easier to just change fork?
-g
>
> Robert Love
>
> diff -urN linux-2.5.6-pre2/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
> --- linux-2.5.6-pre2/arch/alpha/kernel/entry.S Fri Mar 1 17:21:14 2002
> +++ linux/arch/alpha/kernel/entry.S Mon Mar 4 17:49:27 2002
> @@ -495,7 +495,7 @@
> ret $31,($26),1
> .end alpha_switch_to
>
> -#ifdef CONFIG_SMP
> +#ifdef CONFIG_SMP || CONFIG_PREEMPT
> .globl ret_from_fork
> .align 3
> .ent ret_from_fork
> diff -urN linux-2.5.6-pre2/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
> --- linux-2.5.6-pre2/arch/i386/kernel/entry.S Tue Feb 19 21:10:58 2002
> +++ linux/arch/i386/kernel/entry.S Mon Mar 4 17:48:32 2002
> @@ -195,7 +195,7 @@
>
>
> ENTRY(ret_from_fork)
> -#if CONFIG_SMP
> +#if CONFIG_SMP || CONFIG_PREEMPT
> call SYMBOL_NAME(schedule_tail)
> #endif
> GET_THREAD_INFO(%ebx)
> diff -urN linux-2.5.6-pre2/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S
> --- linux-2.5.6-pre2/arch/ppc/kernel/entry.S Tue Feb 19 21:10:59 2002
> +++ linux/arch/ppc/kernel/entry.S Mon Mar 4 17:48:41 2002
> @@ -343,7 +343,7 @@
>
> .globl ret_from_fork
> ret_from_fork:
> -#ifdef CONFIG_SMP
> +#ifdef CONFIG_SMP || CONFIG_PREEMPT
> bl schedule_tail
> #endif
> rlwinm r3,r1,0,0,18
> diff -urN linux-2.5.6-pre2/arch/ppc64/kernel/entry.S linux/arch/ppc64/kernel/entry.S
> --- linux-2.5.6-pre2/arch/ppc64/kernel/entry.S Tue Feb 19 21:10:53 2002
> +++ linux/arch/ppc64/kernel/entry.S Mon Mar 4 17:52:16 2002
> @@ -311,7 +311,7 @@
> blr
>
> _GLOBAL(ret_from_fork)
> -#ifdef CONFIG_SMP
> +#ifdef CONFIG_SMP || CONFIG_PREEMPT
> bl .schedule_tail
> #endif
> clrrdi r4,r1,THREAD_SHIFT
> diff -urN linux-2.5.6-pre2/arch/s390/kernel/entry.S linux/arch/s390/kernel/entry.S
> --- linux-2.5.6-pre2/arch/s390/kernel/entry.S Tue Feb 19 21:10:57 2002
> +++ linux/arch/s390/kernel/entry.S Mon Mar 4 17:48:12 2002
> @@ -295,7 +295,7 @@
> stosm 24(%r15),0x03 # reenable interrupts
> sr %r0,%r0 # child returns 0
> st %r0,SP_R2(%r15) # store return value (change R2 on stack)
> -#ifdef CONFIG_SMP
> +#ifdef CONFIG_SMP || CONFIG_PREEMPT
> l %r1,BASED(.Lschedtail)
> la %r14,BASED(sysc_return)
> br %r1 # call schedule_tail, return to sysc_return
> @@ -896,7 +896,7 @@
> #error .Ltrace: .long syscall_trace
> .Lvfork: .long sys_vfork
>
> -#ifdef CONFIG_SMP
> +#ifdef CONFIG_SMP || CONFIG_PREEMPT
> .Lschedtail: .long schedule_tail
> #endif
>
> diff -urN linux-2.5.6-pre2/arch/s390x/kernel/entry.S linux/arch/s390x/kernel/entry.S
> --- linux-2.5.6-pre2/arch/s390x/kernel/entry.S Tue Feb 19 21:10:58 2002
> +++ linux/arch/s390x/kernel/entry.S Mon Mar 4 17:53:31 2002
> @@ -280,7 +280,7 @@
> GET_CURRENT # load pointer to task_struct to R9
> stosm 48(%r15),0x03 # reenable interrupts
> xc SP_R2(8,%r15),SP_R2(%r15) # child returns 0
> -#ifdef CONFIG_SMP
> +#ifdef CONFIG_SMP || CONFIG_PREEMPT
> larl %r14,sysc_return
> jg schedule_tail # return to sysc_return
> #else
> diff -urN linux-2.5.6-pre2/kernel/sched.c linux/kernel/sched.c
> --- linux-2.5.6-pre2/kernel/sched.c Fri Mar 1 17:21:16 2002
> +++ linux/kernel/sched.c Mon Mar 4 17:54:00 2002
> @@ -397,7 +397,7 @@
> p->sleep_avg) / (EXIT_WEIGHT + 1);
> }
>
> -#if CONFIG_SMP
> +#if CONFIG_SMP || CONFIG_PREEMPT
> asmlinkage void schedule_tail(void)
> {
> spin_unlock_irq(&this_rq()->lock);
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
--
George [email protected]
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Real time sched: http://sourceforge.net/projects/rtsched/
On Wed, 2002-03-06 at 14:17, george anzinger wrote:
> With out a lot of looking, wouldn't it be easier to just change fork?
Don't we need to unlock the rq regardless of what fork does?
Also, the alternative would be to set preempt_count to 0 if
CONFIG_PREEMPT and 1 if CONFIG_PREEMPT && CONFIG_SMP. I figured Linus
would balk at that sort #if/#else in do_fork. And, even then, is it
safe to start the task with a preempt_count of 0?
Robert Love