Subject: [nathanw_sa] cpu_preempt() and run queues
To: None <tech-kern@netbsd.org>
From: Jason R Thorpe <thorpej@wasabisystems.com>
List: tech-kern
Date: 12/29/2002 13:29:27
--r5Pyd7+fXNt84Ff3
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
With an eye towards using Greg McGarry's new context switch model,
it seemed a little silly that the first thing cpu_preempt() does
is remove the new process from its run queue.
The following patch makes the one caller of cpu_preempt() do the
remrunqueue() step first, and removes all that code from each of
the cpu_preempt() implementations. This effectively makes cpu_preempt()
semantically identical to the new function Greg added on his branch.
Note I have not yet tested this patch at all (not even compile-tested); I
will do that later. This is mostly to solicit comments for now.
--
-- Jason R. Thorpe <thorpej@wasabisystems.com>
--r5Pyd7+fXNt84Ff3
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="cpu_preempt.diffs"
Index: arch/acorn26/acorn26/Locore.c
===================================================================
RCS file: /cvsroot/src/sys/arch/acorn26/acorn26/Locore.c,v
retrieving revision 1.3.2.3
diff -c -r1.3.2.3 Locore.c
*** arch/acorn26/acorn26/Locore.c 2002/12/03 05:03:21 1.3.2.3
--- arch/acorn26/acorn26/Locore.c 2002/12/25 20:11:27
***************
*** 196,202 ****
#if 0
printf("cpu_preempt: %p -> %p", old, new);
#endif
- remrunqueue(new);
want_resched = 0;
#ifdef LOCKDEBUG
sched_unlock_idle();
--- 196,201 ----
Index: arch/alpha/alpha/locore.s
===================================================================
RCS file: /cvsroot/src/sys/arch/alpha/alpha/locore.s,v
retrieving revision 1.97.2.10
diff -c -r1.97.2.10 locore.s
*** arch/alpha/alpha/locore.s 2002/10/23 16:42:53 1.97.2.10
--- arch/alpha/alpha/locore.s 2002/12/25 20:11:57
***************
*** 953,962 ****
LDGP(pv)
/*
* do an inline savectx(), to save old context
- * Note: GET_CURLWP clobbers v0, t0, t8...t11.
*/
- GET_CURLWP
- ldq a0, 0(v0)
ldq a2, L_ADDR(a0)
/* NOTE: ksp is stored by the swpctx */
stq s0, U_PCB_CONTEXT+(0 * 8)(a2) /* store s0 - s6 */
--- 953,959 ----
***************
*** 972,1003 ****
mov a0, s0 /* save old curlwp */
mov a2, s1 /* save old U-area */
-
- cpu_preempt_queuescan:
- br pv, 1f
- 1: LDGP(pv)
- ldl t3, sched_whichqs /* look for non-empty queue */
- bne t3, 4f /* and if none, panic! */
- PANIC("cpu_preempt",Lcpu_preempt_pmsg)
-
- 4:
- ldq t5, L_BACK(a1) /* t5 = l->l_back */
- stq zero, L_BACK(a1) /* firewall: l->l_back = NULL*/
- ldq t6, L_FORW(a1) /* t6 = l->l_forw */
- stq t5, L_BACK(t6) /* t6->l_back = t5 */
- stq t6, L_FORW(t5) /* t5->l_forw = t6 */
-
- cmpeq t6, t5, t0 /* see if queue is empty */
- beq t0, 5f /* nope, it's not! */
-
- ldiq t0, 1 /* compute bit in whichqs */
- ldq t2, L_PRIORITY(a1)
- srl t2, 2, t2
- sll t0, t2, t0
- xor t3, t0, t3 /* clear bit in whichqs */
- stl t3, sched_whichqs
-
- 5:
mov a1, s2 /* save new lwp */
ldq s3, L_MD_PCBPADDR(s2) /* save new pcbpaddr */
--- 969,974 ----
Index: arch/arm/arm32/cpuswitch.S
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/arm32/cpuswitch.S,v
retrieving revision 1.3.2.24
diff -c -r1.3.2.24 cpuswitch.S
*** arch/arm/arm32/cpuswitch.S 2002/10/18 02:35:20 1.3.2.24
--- arch/arm/arm32/cpuswitch.S 2002/12/25 20:12:35
***************
*** 640,694 ****
bl _C_LABEL(sched_lock_idle)
#endif
- /* Do we have any active queues? */
- ldr r7, .Lwhichqs
- ldr r3, [r7]
-
- /* If none, panic! */
- teq r3, #0x00000000
- beq .Lpreempt_noqueues
-
mov r0, r6 /* restore old lwp */
mov r1, r5 /* restore new lwp */
/* rem: r0 = old lwp */
/* rem: r1 = new lwp */
- /* rem: r3 = whichqs */
- /* rem: r7 = &whichqs */
/* rem: interrupts are disabled */
- /* Compute the queue bit corresponding to the new lwp. */
- ldrb r4, [r1, #(L_PRIORITY)]
- mov r2, #0x00000001
- mov r4, r4, lsr #2 /* queue number */
- mov r2, r2, lsl r4 /* queue bit */
-
- /* rem: r0 = old lwp */
- /* rem: r1 = new lwp */
- /* rem: r2 = queue bit */
- /* rem: r3 = whichqs */
- /* rem: r4 = queue number */
- /* rem: r7 = &whichqs */
-
/*
- * Unlink the lwp from the queue.
- */
- ldr r5, [r1, #(L_BACK)] /* r5 = l->l_back */
- mov r6, #0x00000000
- str r6, [r1, #(L_BACK)] /* firewall: l->l_back = NULL */
- ldr r6, [r1, #(L_FORW)] /* r6 = l->l_forw */
- str r5, [r6, #(L_BACK)] /* r6->l_back = r5 */
- str r6, [r5, #(L_FORW)] /* r5->l_forw = r6 */
-
- teq r5, r6 /* see if queue is empty */
- biceq r3, r3, r2 /* clear bit if so */
- streq r3, [r7] /* store it back if so */
-
- /* rem: r2 (queue bit) now free */
- /* rem: r3 (whichqs) now free */
- /* rem: r7 (&whichqs) now free */
-
- /*
* Okay, set up registers the way cpu_switch() wants them,
* and jump into the middle of it (where we bring up the
* new process).
--- 640,653 ----
***************
*** 702,715 ****
mov r1, r0 /* r1 = old lwp */
#endif
b .Lswitch_resume
-
- .Lpreempt_noqueues:
- add r0, pc, #.Lpreemptpanic - . - 8
- bl _C_LABEL(panic)
-
- .Lpreemptpanic:
- .asciz "cpu_preempt: whichqs empty"
- .align 0
/*
* void switch_exit(struct lwp *l, struct lwp *l0);
--- 661,666 ----
Index: arch/i386/i386/locore.S
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/locore.S,v
retrieving revision 1.1.2.4
diff -c -r1.1.2.4 locore.S
*** arch/i386/i386/locore.S 2002/12/19 00:33:48 1.1.2.4
--- arch/i386/i386/locore.S 2002/12/25 20:15:08
***************
*** 1976,1989 ****
popl %ebx
ret
- #ifdef DIAGNOSTIC
- NENTRY(preempt_error)
- pushl $1f
- call _C_LABEL(panic)
- /* NOTREACHED */
- 1: .asciz "cpu_preempt"
- #endif /* DIAGNOSTIC */
-
/*
* void cpu_preempt(struct lwp *current, struct lwp *next)
* Switch to the specified nexxt LWP.
--- 1976,1981 ----
***************
*** 2003,2009 ****
1:
#endif /* DEBUG */
! movl CPUVAR(CURLWP),%esi
movl 20(%esp),%edi # next
/*
--- 1995,2001 ----
1:
#endif /* DEBUG */
! movl CPUVAR(CURLWP),%esi /* XXX get from args on stack */
movl 20(%esp),%edi # next
/*
***************
*** 2012,2046 ****
* the correct queue if it happens to get called from the spllower()
* below and changes the priority. (See corresponding comment in
* usrret()).
*/
movl $0,CPUVAR(CURLWP)
- preempt_dequeue:
/*
* We're running at splhigh(), but it's otherwise okay to take
* interrupts here.
*/
sti
- movzbl L_PRIORITY(%edi),%eax
- #ifdef DIAGNOSTIC
- shrl $2,%eax
- btl %eax,_C_LABEL(sched_whichqs)
- jnc _C_LABEL(preempt_error)
- #endif /* DIAGNOSTIC */
- movl L_BACK(%edi),%edx # unlink process
- movl $0,L_BACK(%edi) # zap reverse link to indicate off list
- movl L_FORW(%edi),%ecx
- movl %ecx,L_FORW(%edx)
- movl %edx,L_BACK(%ecx)
- cmpl %ecx,%edx # q still has something?
- jne 3f
- #ifndef DIAGNOSTIC
- shrl $2,%eax
- #endif
- btrl %eax,_C_LABEL(sched_whichqs) # no; clear bit
-
- 3:
/* Jump into the middle of cpu_switch */
xorl %eax,%eax
jmp switch_resume
--- 2004,2020 ----
* the correct queue if it happens to get called from the spllower()
* below and changes the priority. (See corresponding comment in
* usrret()).
+ *
+ * XXX Is this necessary? We know we won't go idle.
*/
movl $0,CPUVAR(CURLWP)
/*
* We're running at splhigh(), but it's otherwise okay to take
* interrupts here.
*/
sti
/* Jump into the middle of cpu_switch */
xorl %eax,%eax
jmp switch_resume
Index: arch/m68k/m68k/switch_subr.s
===================================================================
RCS file: /cvsroot/src/sys/arch/m68k/m68k/Attic/switch_subr.s,v
retrieving revision 1.1.2.8
diff -c -r1.1.2.8 switch_subr.s
*** arch/m68k/m68k/switch_subr.s 2002/09/18 00:02:03 1.1.2.8
--- arch/m68k/m68k/switch_subr.s 2002/12/25 20:15:43
***************
*** 443,468 ****
* Switch to the specific next LWP.
*/
ENTRY(cpu_preempt)
! movl %sp@(4),%a0 | fetch `current' lwp
! movl %a0@(L_ADDR),%a1
! movw %sr,%a1@(PCB_PS) | save sr before changing ipl
clrl _C_LABEL(curlwp)
movl %sp@(8),%a0 | fetch `next' lwp
- movb %a0@(L_PRIORITY),%d0
-
- /* Unlink `next' from queue */
- movl %a0@(L_BACK),%a1
- movl %a0@(L_FORW),%a0
- movl %a0,%a1@(L_FORW)
- movl %a1,%a0@(L_BACK)
- cmpal %a0,%a1 | anyone left on queue?
- jne 1f | yes, skip
- movl _C_LABEL(sched_whichqs),%d1
- lsrb #2,%d0
- bclr %d0,%d1 | no, clear bit
- movl %d1,_C_LABEL(sched_whichqs)
- 1: movl %sp@(4),%a1 | fetch `current' lwp again
- movl %sp@(8),%a0 | fetch `next' lwp again
jbra Lcpu_switch_common
--- 443,453 ----
* Switch to the specific next LWP.
*/
ENTRY(cpu_preempt)
! movl %sp@(4),%a1 | fetch `current' lwp
! movl %a1@(L_ADDR),%a0
! movw %sr,%a0@(PCB_PS) | save sr before changing ipl
clrl _C_LABEL(curlwp)
movl %sp@(8),%a0 | fetch `next' lwp
jbra Lcpu_switch_common
Index: arch/mips/mips/locore.S
===================================================================
RCS file: /cvsroot/src/sys/arch/mips/mips/locore.S,v
retrieving revision 1.126.2.16
diff -c -r1.126.2.16 locore.S
*** arch/mips/mips/locore.S 2002/11/11 22:00:42 1.126.2.16
--- arch/mips/mips/locore.S 2002/12/25 20:16:10
***************
*** 444,452 ****
move s0, a0 # s0 = old proc
move s7, a1 # s7 = newproc
- jal _C_LABEL(remrunqueue)
- move a0, a1 # Remove newproc from queue
-
#if defined(LOCKDEBUG)
/*
* Done mucking with the run queues, release the
--- 444,449 ----
Index: arch/powerpc/powerpc/locore_subr.S
===================================================================
RCS file: /cvsroot/src/sys/arch/powerpc/powerpc/locore_subr.S,v
retrieving revision 1.2.10.8
diff -c -r1.2.10.8 locore_subr.S
*** arch/powerpc/powerpc/locore_subr.S 2002/12/19 19:58:16 1.2.10.8
--- arch/powerpc/powerpc/locore_subr.S 2002/12/25 20:17:02
***************
*** 505,534 ****
#endif
/* Find a new process */
! mr 31,29
lwz 29,8(1)
addi 1,1,16
-
- lwz 4,L_BACK(31) /* r4 = newlwp->l_back */
- lwz 3,L_FORW(31) /* r3 = newlwp->l_forw */
- stw 4,L_BACK(3) /* r3->l_back = r4 */
- stw 3,L_FORW(4) /* r4->l_forw = r3 */
-
- cmpl 0,4,3 /* queue empty? */
- bne switch_preempt_common
-
- /* so now r31 is newlwp and r3/r4 are scratch again */
-
- lis 8,_C_LABEL(sched_whichqs)@ha
- lwz 9,_C_LABEL(sched_whichqs)@l(8)
-
- lbz 3,L_PRIORITY(31)
- li 4,2
- srw 3,3,4 /* r3 = newlwp->l_priority / 4 */
- lis 4,0x8000
- srw 3,4,3 /* r3 = 0x80000000 >> r3 */
- andc 9,9,3 /* sched_whichqs &= ~r3 */
- stw 9,_C_LABEL(sched_whichqs)@l(8) /* mark it empty */
/* Stack normal, r31 is newlwp, r30 is oldlwp */
b switch_preempt_common
--- 505,513 ----
#endif
/* Find a new process */
! mr 31,29 /* XXX what is this? */
lwz 29,8(1)
addi 1,1,16
/* Stack normal, r31 is newlwp, r30 is oldlwp */
b switch_preempt_common
Index: arch/sh3/sh3/locore_subr.S
===================================================================
RCS file: /cvsroot/src/sys/arch/sh3/sh3/locore_subr.S,v
retrieving revision 1.10.6.4
diff -c -r1.10.6.4 locore_subr.S
*** arch/sh3/sh3/locore_subr.S 2002/08/10 15:49:29 1.10.6.4
--- arch/sh3/sh3/locore_subr.S 2002/12/25 20:17:26
***************
*** 155,181 ****
mov.l r15, @-r1
/*
! * Don't need the outgoing LWP anymore. Stash the incoming
! * LWP into a callee-saved register.
! */
! mov r5, r8
!
! /* Unlink the new LWP from its run queue. */
! mov.l _L.remrunqueue, r0
! jsr @r0
! mov r8, r4
!
! /*
! * Put the incoming proc in r4 and jump into the middle
* of cpu_switch(), and let it do the work to restore the
* incoming LWP's context.
*/
bra _L.doswitch
! mov r8, r4
.align 2
_L.SFp: .long (L_MD_PCB)
- _L.remrunqueue: .long _C_LABEL(remrunqueue)
#ifdef SH3
/*
--- 155,169 ----
mov.l r15, @-r1
/*
! * Put the incoming LWP in r4 and jump into the middle
* of cpu_switch(), and let it do the work to restore the
* incoming LWP's context.
*/
bra _L.doswitch
! mov r5, r4
.align 2
_L.SFp: .long (L_MD_PCB)
#ifdef SH3
/*
Index: arch/sparc/sparc/locore.s
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc/sparc/locore.s,v
retrieving revision 1.148.4.14
diff -c -r1.148.4.14 locore.s
*** arch/sparc/sparc/locore.s 2002/12/11 06:12:13 1.148.4.14
--- arch/sparc/sparc/locore.s 2002/12/25 20:18:45
***************
*** 4813,4825 ****
sll %o4, 3, %o0
add %o0, %o5, %o5
ld [%o5], %g3 ! p = q->ph_link;
-
- cpu_switch0:
- /*
- * Here code in common with cpu_preempt() starts.
- * cpu_preempt() sets %g3 to p, and %o5 to p->p_back,
- * so the following will unlink p from the switch_qs list.
- */
cmp %g3, %o5 ! if (p == q)
be Lsw_panic_rq ! panic("switch rq");
EMPTY
--- 4813,4818 ----
***************
*** 4834,4839 ****
--- 4827,4833 ----
andn %o3, %o1, %o3
st %o3, [%g2 + %lo(_C_LABEL(sched_whichqs))]
1:
+ cpu_switch0:
/*
* PHASE TWO: NEW REGISTER USAGE:
* %g1 = oldpsr (excluding ipl bits)
***************
*** 5019,5025 ****
*/
mov %o0, %g4 ! lastproc = arg1;
mov %o1, %g3 ! newproc = arg2;
- sethi %hi(_C_LABEL(sched_whichqs)), %g2 ! set up addr regs
sethi %hi(cpcb), %g6
ld [%g6 + %lo(cpcb)], %o0
std %o6, [%o0 + PCB_SP] ! cpcb->pcb_<sp,pc> = <sp,pc>;
--- 5013,5018 ----
***************
*** 5028,5041 ****
andn %g1, PSR_PIL, %g1 ! oldpsr &= ~PSR_PIL;
sethi %hi(curlwp), %g7
st %g0, [%g7 + %lo(curlwp)] ! curlwp = NULL;
-
- /*
- * now set up %o4 (which) and %o5 (p->p_back), and continue with
- * common code in cpu_switch().
- */
- ld [%g3 + L_PRIORITY], %o4
- srl %o4, 2, %o4
- ld [%g3 + 4], %o5 ! %o5 = p->p_back
b,a cpu_switch0
/*
--- 5021,5026 ----
Index: arch/sparc64/sparc64/locore.s
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/locore.s,v
retrieving revision 1.139.4.14
diff -c -r1.139.4.14 locore.s
*** arch/sparc64/sparc64/locore.s 2002/10/18 02:40:08 1.139.4.14
--- arch/sparc64/sparc64/locore.s 2002/12/25 20:23:10
***************
*** 8122,8128 ****
/*
* REGISTER USAGE AT THIS POINT:
* %l1 = tmp 0
- * %l2 = %hi(_C_LABEL(whichqs))
* %l3 = p
* %l4 = lastproc
* %l5 = cpcb
--- 8122,8127 ----
***************
*** 8131,8139 ****
* %o0 = tmp 1
* %o1 = tmp 2
* %o2 = tmp 3
- * %o3 = whichqs
- * %o4 = which
- * %o5 = q
*/
flushw
rdpr %pstate, %o1 ! oldpstate = %pstate;
--- 8130,8135 ----
***************
*** 8141,8186 ****
sethi %hi(CPCB), %l6
mov %i1, %l3 ! new lwp -> %l3
- sethi %hi(_C_LABEL(sched_whichqs)), %l2 ! set up addr regs
- ldub [%l3 + L_PRIORITY], %o4 ! load which
-
sethi %hi(CURLWP), %l7
LDPTR [%l6 + %lo(CPCB)], %l5
!
! srl %o4, 2, %o4 ! convert pri -> queue number
stx %o7, [%l5 + PCB_PC] ! cpcb->pcb_pc = pc;
!
mov %i0, %l4 ! lastproc = curlwp; (hope he's right)
sth %o1, [%l5 + PCB_PSTATE] ! cpcb->pcb_pstate = oldpstate;
STPTR %g0, [%l7 + %lo(CURLWP)] ! curlwp = NULL;
-
- ld [%l2 + %lo(_C_LABEL(sched_whichqs))], %o3
-
- sll %o4, PTRSHFT+1, %o0
- LDPTR [%l3 + L_BACK], %o5
-
- cmp %l3, %o5 ! if (p == q)
- be,pn %icc, Lsw_panic_rq ! panic("switch rq");
- EMPTY
- LDPTR [%l3], %o0 ! tmp0 = p->p_forw;
- STPTR %o0, [%o5] ! q->ph_link = tmp0;
- STPTR %o5, [%o0 + PTRSZ] ! tmp0->p_back = q;
-
- set _C_LABEL(sched_qs), %o5 ! q = &qs[which];
- sll %o4, PTRSHFT+1, %o0
- add %o0, %o5, %o5
- ldx [%o5], %o0
-
- cmp %o0, %o5 ! if (tmp0 == q)
- bne 1f
- EMPTY
- mov 1, %o1 ! whichqs &= ~(1 << which);
- sll %o1, %o4, %o1
- andn %o3, %o1, %o3
- st %o3, [%l2 + %lo(_C_LABEL(sched_whichqs))]
- 1:
ba,pt %icc, cpu_loadproc
nop
--- 8137,8152 ----
sethi %hi(CPCB), %l6
mov %i1, %l3 ! new lwp -> %l3
sethi %hi(CURLWP), %l7
LDPTR [%l6 + %lo(CPCB)], %l5
!
stx %o7, [%l5 + PCB_PC] ! cpcb->pcb_pc = pc;
!
mov %i0, %l4 ! lastproc = curlwp; (hope he's right)
sth %o1, [%l5 + PCB_PSTATE] ! cpcb->pcb_pstate = oldpstate;
STPTR %g0, [%l7 + %lo(CURLWP)] ! curlwp = NULL;
ba,pt %icc, cpu_loadproc
nop
Index: kern/kern_synch.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_synch.c,v
retrieving revision 1.101.2.27
diff -c -r1.101.2.27 kern_synch.c
*** kern/kern_synch.c 2002/12/04 22:40:41 1.101.2.27
--- kern/kern_synch.c 2002/12/25 20:23:55
***************
*** 917,922 ****
--- 917,923 ----
if (newl == NULL) {
retval = cpu_switch(l, NULL);
} else {
+ remrunqueue(newl);
cpu_preempt(l, newl);
retval = 0;
}
--r5Pyd7+fXNt84Ff3--