2002-03-05 00:12:01

by Robert Love

[permalink] [raw]
Subject: [PATCH] 2.5: preemptive kernel on UP

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);


2002-03-05 00:44:01

by Russell King

[permalink] [raw]
Subject: Re: [PATCH] 2.5: preemptive kernel on UP

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

2002-03-05 00:51:54

by Robert Love

[permalink] [raw]
Subject: Re: [PATCH] 2.5: preemptive kernel on UP

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

2002-03-05 00:53:44

by Russell King

[permalink] [raw]
Subject: Re: [PATCH] 2.5: preemptive kernel on UP

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

2002-03-05 00:58:55

by Robert Love

[permalink] [raw]
Subject: Re: [PATCH] 2.5: preemptive kernel on UP

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);

2002-03-05 01:40:48

by Alan

[permalink] [raw]
Subject: Re: [PATCH] 2.5: preemptive kernel on UP

> 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 ....

2002-03-05 01:44:10

by Robert Love

[permalink] [raw]
Subject: Re: [PATCH] 2.5: preemptive kernel on UP

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

2002-03-05 01:56:30

by Victor Yodaiken

[permalink] [raw]
Subject: Re: [PATCH] 2.5: preemptive kernel on UP

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

2002-03-05 04:41:04

by Ben Clifford

[permalink] [raw]
Subject: Re: [PATCH] 2.5: preemptive kernel on UP

-----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-----

2002-03-06 19:18:56

by George Anzinger

[permalink] [raw]
Subject: Re: [PATCH] 2.5: preemptive kernel on UP

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/

2002-03-06 20:21:52

by Robert Love

[permalink] [raw]
Subject: Re: [PATCH] 2.5: preemptive kernel on UP

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