Skip to contentSkip to conversation

2.5: preemptive kernel on UP

PATCH In review Robert Love 6 participants 11 messages Mar 5, 2002 – Mar 6, 2002

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 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

arch/alpha/kernel/entry.S +1 -1
diff -urN linux-2.5.6-pre2/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
@@ -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
arch/i386/kernel/entry.S +1 -1
diff -urN linux-2.5.6-pre2/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
@@ -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)
arch/ppc/kernel/entry.S +1 -1
diff -urN linux-2.5.6-pre2/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S
@@ -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
arch/ppc64/kernel/entry.S +1 -1
diff -urN linux-2.5.6-pre2/arch/ppc64/kernel/entry.S linux/arch/ppc64/kernel/entry.S
@@ -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
arch/s390/kernel/entry.S +2 -2
diff -urN linux-2.5.6-pre2/arch/s390/kernel/entry.S linux/arch/s390/kernel/entry.S
@@ -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
 
arch/s390x/kernel/entry.S +1 -1
diff -urN linux-2.5.6-pre2/arch/s390x/kernel/entry.S linux/arch/s390x/kernel/entry.S
@@ -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
kernel/sched.c +1 -1
diff -urN linux-2.5.6-pre2/kernel/sched.c linux/kernel/sched.c
@@ -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);
#1 lore raw
Quoted 16 lines · Robert Love

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

arch/alpha/kernel/entry.S line 498

Quoted 5 lines
arch/alpha/kernel/entry.S +1 -1
@@ -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?

Signature · 2 lines
Russell King ([email protected])                The developer of ARM Linux
             http://www.arm.linux.org.uk/personal/aboutme.html
#2 lore raw
Quoted 11 lines · Russell King

arch/alpha/kernel/entry.S line 498

Quoted 9 lines

diff -urN linux-2.5.6-pre2/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S

arch/alpha/kernel/entry.S +1 -1
@@ -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

#3 lore raw
In reply to Robert Love
Quoted 9 lines · Robert Love
Quoted 7 lines · Russell King
Quoted 7 lines

diff -urN linux-2.5.6-pre2/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S

arch/alpha/kernel/entry.S +0 -0
@@ -495,7 +495,7 @@
 	ret	$31,($26),1
 .end alpha_switch_to
 
Quoted 6 lines
Quoted 4 lines

arch/alpha/kernel/entry.S line 498

Quoted 2 lines
arch/alpha/kernel/entry.S +1 -1
-#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

Signature · 2 lines
Russell King ([email protected])                The developer of ARM Linux
             http://www.arm.linux.org.uk/personal/aboutme.html
#4 lore raw
Quoted 1 line · Russell King

It's a #ifdef, not a #if

Better?

Robert Love

arch/alpha/kernel/entry.S +1 -1
diff -urN linux-2.5.6-pre2/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
@@ -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
arch/i386/kernel/entry.S +1 -1
diff -urN linux-2.5.6-pre2/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
@@ -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)
arch/ppc/kernel/entry.S +1 -1
diff -urN linux-2.5.6-pre2/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S
@@ -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
arch/ppc64/kernel/entry.S +1 -1
diff -urN linux-2.5.6-pre2/arch/ppc64/kernel/entry.S linux/arch/ppc64/kernel/entry.S
@@ -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
arch/s390/kernel/entry.S +2 -2
diff -urN linux-2.5.6-pre2/arch/s390/kernel/entry.S linux/arch/s390/kernel/entry.S
@@ -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
 
arch/s390x/kernel/entry.S +1 -1
diff -urN linux-2.5.6-pre2/arch/s390x/kernel/entry.S linux/arch/s390x/kernel/entry.S
@@ -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
kernel/sched.c +1 -1
diff -urN linux-2.5.6-pre2/kernel/sched.c linux/kernel/sched.c
@@ -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);
#5 lore raw
Quoted 1 line

Better?

Not really

Quoted 1 line

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

#6 lore raw
Quoted 3 lines · Alan Cox

try

#if defined(a) || defined(b)

Is that needed since the .config is defined to 1 and 0 in autoconf.h?

Quoted 2 lines

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

#7 lore raw

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Robert,

Quoted 1 line · In one message you

Patch [...] is critical for all UP+preempt users.

and in another (in the same thread) you write:

Quoted 1 line

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

#8 lore raw
In reply to Robert Love
Quoted 4 lines · Alan Cox

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

Signature · 4 lines
---------------------------------------------------------
Victor Yodaiken 
Finite State Machine Labs: The RTLinux Company.
 www.fsmlabs.com  www.rtlinux.com
#9 lore raw
In reply to Robert Love
Quoted 10 lines · Robert Love

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

Quoted 102 lines

Robert Love

diff -urN linux-2.5.6-pre2/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S

arch/alpha/kernel/entry.S Mon Mar 4 17:49:27 2002 renamed from arch/alpha/kernel/entry.S Fri Mar 1 17:21:14 2002 +1 -1
@@ -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

arch/i386/kernel/entry.S Mon Mar 4 17:48:32 2002 renamed from arch/i386/kernel/entry.S Tue Feb 19 21:10:58 2002 +1 -1
@@ -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

arch/ppc/kernel/entry.S Mon Mar 4 17:48:41 2002 renamed from arch/ppc/kernel/entry.S Tue Feb 19 21:10:59 2002 +1 -1
@@ -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

arch/ppc64/kernel/entry.S Mon Mar 4 17:52:16 2002 renamed from arch/ppc64/kernel/entry.S Tue Feb 19 21:10:53 2002 +1 -1
@@ -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

arch/s390/kernel/entry.S Mon Mar 4 17:48:12 2002 renamed from arch/s390/kernel/entry.S Tue Feb 19 21:10:57 2002 +2 -2
@@ -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

arch/s390x/kernel/entry.S Mon Mar 4 17:53:31 2002 renamed from arch/s390x/kernel/entry.S Tue Feb 19 21:10:58 2002 +1 -1
@@ -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

kernel/sched.c Mon Mar 4 17:54:00 2002 renamed from kernel/sched.c Fri Mar 1 17:21:16 2002 +1 -2
@@ -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/

Signature · 3 lines
George           [email protected]
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Real time sched: http://sourceforge.net/projects/rtsched/
#10 lore raw
Quoted 1 line · george anzinger

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