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