Subject: Re: alternate rough SA patch (works on SMP)
To: Stephan Uphoff <ups@stups.com>
From: Christian Limpach <chris@pin.lu>
List: tech-kern
Date: 06/29/2003 02:47:52
Quoting Stephan Uphoff <ups@stups.com>:

> Here are a few comments:
> - ltsleep and therefore also copyout can not be called with SCHED_LOCK
> held.
> - as a target for mi_switch the lwp has to be in memory (l_flag & L_INMEM)

I noticed these two since I sent the patch.  Don't we also need the L_INMEM 
tests on UP?

> - With your patch a LWP that had been blocked (block upcall received by
>    libpthread) can return later to user space without the associated
>    unblock upcall or holding the virtual processor.
>    This will confuse libpthread.

indeed, I wasn't quite aware of how things should work and my approach was to 
fix the effects and not the cause of problems.

One problem seems to be that on MP the scheduler will run an lwp we put on 
the runqueues before we get to do the SA housekeeping.  I have added per-cpu 
runqueues and now pthread/SA works without any additional patches in 
kern_sa.  There's still some issues with signal handling and occasional 
"sa_switch: Not enough stacks".

per-cpu runqueues:
There's now a runqueue for each cpu in addition to the global runqueue.  cpu-
switch runs the lwp with the highest priority.  The cpu-queue wins over the 
global queue if both have lwp's at the same priority.  
setrunnable/setrunqueue take an additional argument cpu_id where -1 selects 
the global queue and values >= 0 select that cpu.  The selected cpu is 
recorded in l_schedcpu in struct lwp for use in remrunqueue and to allow easy 
rescheduling (setrunqueue(l, l->l_schedcpu)).

- There's no code to set a process' affinity except by setting it's 
l_schedcpu from ddb/kgdb.
- Processes with SA enabled have a very strong affinity, this can probably be 
relaxed somewhat.
- I have modified cpu_switch only on i386, the code is otherwise MI except 
for one use of X86_MAXPROCS in sched.h where we need an MI MAXPROCS.

Comments?

    christian

Index: arch/i386/i386/cpu.c
===================================================================
RCS file: /cvs/netbsd/src/sys/arch/i386/i386/cpu.c,v
retrieving revision 1.14
diff -u -b -r1.14 cpu.c
--- arch/i386/i386/cpu.c	25 Apr 2003 21:54:29 -0000	1.14
+++ arch/i386/i386/cpu.c	28 Jun 2003 17:02:19 -0000
@@ -287,6 +287,8 @@
 #endif
 	ci->ci_func = caa->cpu_func;
 
+	rqinit(ci->ci_cpuid);
+
 	simple_lock_init(&ci->ci_slock);
 
 #if defined(MULTIPROCESSOR)
Index: arch/i386/i386/genassym.cf
===================================================================
RCS file: /cvs/netbsd/src/sys/arch/i386/i386/genassym.cf,v
retrieving revision 1.37
diff -u -b -r1.37 genassym.cf
--- arch/i386/i386/genassym.cf	4 May 2003 22:01:58 -0000	1.37
+++ arch/i386/i386/genassym.cf	28 Jun 2003 17:02:19 -0000
@@ -281,6 +281,8 @@
 define	CPU_INFO_IDEPTH		offsetof(struct cpu_info, ci_idepth)
 define	CPU_INFO_ISOURCES	offsetof(struct cpu_info, ci_isources)
 
+define	CPU_INFO_CPUID		offsetof(struct cpu_info, ci_cpuid)
+
 if NIOAPIC > 0
 define		IOAPIC_SC_REG		offsetof(struct ioapic_softc, sc_reg)
 define		IOAPIC_SC_DATA		offsetof(struct ioapic_softc, sc_data)
Index: arch/i386/i386/locore.S
===================================================================
RCS file: /cvs/netbsd/src/sys/arch/i386/i386/locore.S,v
retrieving revision 1.11
diff -u -b -r1.11 locore.S
--- arch/i386/i386/locore.S	26 Jun 2003 16:47:15 -0000	1.11
+++ arch/i386/i386/locore.S	28 Jun 2003 17:02:19 -0000
@@ -1705,9 +1705,19 @@
 
 	/* Look for new lwp. */
 	cli				# splhigh doesn't do a cli
+#if !defined(MULTIPROCESSOR)
 	movl	_C_LABEL(sched_whichqs),%ecx
 	bsfl	%ecx,%ebx		# find a full q
 	jnz	switch_dequeue
+#else
+	movl	CPUVAR(CPUID),%eax
+	incl	%eax			# select cpu q => eax = cpuid + 1
+
+	movl	_C_LABEL(sched_whichqs),%ecx
+	orl	_C_LABEL(sched_whichqs)(,%eax,4),%ecx
+	bsfl	%ecx,%ebx
+	jnz	switch_dequeue		# cpu q empty, global q empty
+#endif
 
 	/*
 	 * idling:	save old context.
@@ -1784,8 +1794,18 @@
 	sti
 	call	_C_LABEL(uvm_pageidlezero)
 	cli
+
+#if defined(MULTIPROCESSOR)
+	movl	CPUVAR(CPUID),%eax
+	incl	%eax
+#endif
+    
 	cmpl	$0,_C_LABEL(sched_whichqs)
 	jnz	idle_exit
+#if defined(MULTIPROCESSOR)
+	cmpl	$0,_C_LABEL(sched_whichqs)(,%eax,4)
+	jnz	idle_exit
+#endif
 idle_loop:
 	/* Try to zero some pages. */
 	movl	_C_LABEL(uvm)+UVM_PAGE_IDLE_ZERO,%ecx
@@ -1796,24 +1816,57 @@
 NENTRY(mpidle)
 idle_start:	
 	cli
+
+#if defined(MULTIPROCESSOR)
+	movl	CPUVAR(CPUID),%eax
+	incl	%eax
+#endif
+    
 	cmpl	$0,_C_LABEL(sched_whichqs)
+#if defined(MULTIPROCESSOR)
+	jnz	idle_exit
+	cmpl	$0,_C_LABEL(sched_whichqs)(,%eax,4)
+#endif
 	jz	idle_loop
 idle_exit:	
 	movl	$IPL_HIGH,CPUVAR(ILEVEL)		# splhigh
 #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)	
 	call	_C_LABEL(sched_lock_idle)
 #endif
+#if !defined(MULTIPROCESSOR)
 	movl	_C_LABEL(sched_whichqs),%ecx
 	bsfl	%ecx,%ebx
 	jz	idle_unlock
+#else
+    	movl	CPUVAR(CPUID),%eax  # XXX
+	incl	%eax		    # XXX   # select cpu q => eax = cpuid + 1
+
+	movl	_C_LABEL(sched_whichqs),%ecx
+	orl	_C_LABEL(sched_whichqs)(,%eax,4),%ecx
+	bsfl	%ecx,%ebx
+	jz	idle_unlock		# cpu q empty, global q empty
+#endif
 
 switch_dequeue:		
+#if defined(MULTIPROCESSOR)
+	movl	_C_LABEL(sched_whichqs)(,%eax,4),%ecx
+	btl	%ebx,%ecx
+	jc	1f
+    	xorl	%eax,%eax		# select global q => clear eax
+1:
+#endif
 	/* 
 	 * we're running at splhigh(), but it's otherwise okay to take
 	 * interrupts here. 
 	 */
 	sti
+#if !defined(MULTIPROCESSOR)
 	leal	_C_LABEL(sched_qs)(,%ebx,8),%eax # select q
+#else
+	leal	_C_LABEL(sched_whichqs)(,%eax,4),%ecx
+	movl	_C_LABEL(sched_qs)(,%eax,4),%eax
+	leal	(%eax,%ebx,8),%eax
+#endif
 
 	movl	L_FORW(%eax),%edi	# unlink from front of process q
 #ifdef	DIAGNOSTIC
@@ -1827,8 +1880,14 @@
 	cmpl	%edx,%eax		# q empty?
 	jne	3f
 
+#if !defined(MULTIPROCESSOR)
 	btrl	%ebx,%ecx		# yes, clear to indicate empty
 	movl	%ecx,_C_LABEL(sched_whichqs) # update q status
+#else
+	movl	(%ecx),%eax
+	btrl	%ebx,%eax		# yes, clear to indicate empty
+	movl	%eax,(%ecx)		# update q status
+#endif
 
 3:	/* We just did it. */
 	xorl	%eax,%eax
Index: arch/i386/i386/pmap.c
===================================================================
RCS file: /cvs/netbsd/src/sys/arch/i386/i386/pmap.c,v
retrieving revision 1.155
diff -u -b -r1.155 pmap.c
--- arch/i386/i386/pmap.c	23 Jun 2003 11:01:20 -0000	1.155
+++ arch/i386/i386/pmap.c	28 Jun 2003 17:02:19 -0000
@@ -2070,7 +2070,7 @@
 	*zpte = (pa & PG_FRAME) | PG_V | PG_RW;		/* map in */
 	pmap_update_pg((vaddr_t)zerova);		/* flush TLB */
 	for (i = 0, ptr = (int *) zerova; i < PAGE_SIZE / sizeof(int); i++) {
-		if (sched_whichqs != 0) {
+		if (RQ_NOTEMPTY()) {
 
 			/*
 			 * A process has become ready.  Abort now,
Index: compat/mach/mach_thread.c
===================================================================
RCS file: /cvs/netbsd/src/sys/compat/mach/mach_thread.c,v
retrieving revision 1.18
diff -u -b -r1.18 mach_thread.c
--- compat/mach/mach_thread.c	30 Jan 2003 19:14:19 -0000	1.18
+++ compat/mach/mach_thread.c	28 Jun 2003 17:36:00 -0000
@@ -164,7 +164,7 @@
 	SCHED_LOCK(s);
 	mctc.mctc_lwp->l_private = 0;
 	mctc.mctc_lwp->l_stat = LSRUN;
-	setrunqueue(mctc.mctc_lwp);
+	setrunqueue(mctc.mctc_lwp, mctc.mctc_lwp->l_schedcpu);
 	SCHED_UNLOCK(s);
 	simple_lock(&p->p_lwplock);
 	p->p_nrlwps++;
Index: kern/init_main.c
===================================================================
RCS file: /cvs/netbsd/src/sys/kern/init_main.c,v
retrieving revision 1.218
diff -u -b -r1.218 init_main.c
--- kern/init_main.c	19 Mar 2003 11:36:32 -0000	1.218
+++ kern/init_main.c	28 Jun 2003 17:02:19 -0000
@@ -338,7 +338,7 @@
 	 */
 	(void)chgproccnt(0, 1);
 
-	rqinit();
+	rqinit(-1);
 
 	/* Configure virtual memory system, set vm rlimits. */
 	uvm_init_limits(p);
Index: kern/kern_exit.c
===================================================================
RCS file: /cvs/netbsd/src/sys/kern/kern_exit.c,v
retrieving revision 1.115
diff -u -b -r1.115 kern_exit.c
--- kern/kern_exit.c	19 Mar 2003 11:36:33 -0000	1.115
+++ kern/kern_exit.c	28 Jun 2003 17:34:53 -0000
@@ -448,7 +448,8 @@
 		SCHED_LOCK(s);
 		while ((l2 = sa_getcachelwp(p)) != 0) {
 			l2->l_priority = l2->l_usrpri;
-			setrunnable(l2);
+			setrunnable(l2, l2->l_cpu ? l2->l_cpu->ci_cpuid :
+			    l2->l_schedcpu);
 			DPRINTF(("%d ", l2->l_lid));
 		}
 		DPRINTF(("\n"));
@@ -465,7 +466,8 @@
 		if ((l2->l_stat == LSSLEEP && (l2->l_flag & L_SINTR)) ||
 		    l2->l_stat == LSSUSPENDED) {
 			SCHED_LOCK(s);
-			setrunnable(l2);
+			setrunnable(l2, l2->l_cpu ? l2->l_cpu->ci_cpuid :
+			    l2->l_schedcpu);
 			SCHED_UNLOCK(s);
 			DPRINTF(("exit_lwps: Made %d.%d runnable\n",
 			    p->p_pid, l2->l_lid));
Index: kern/kern_fork.c
===================================================================
RCS file: /cvs/netbsd/src/sys/kern/kern_fork.c,v
retrieving revision 1.107
diff -u -b -r1.107 kern_fork.c
--- kern/kern_fork.c	19 Mar 2003 11:36:33 -0000	1.107
+++ kern/kern_fork.c	28 Jun 2003 17:02:19 -0000
@@ -433,7 +433,7 @@
 	} else {
 		p2->p_stat = SACTIVE;
 		l2->l_stat = LSRUN;
-		setrunqueue(l2);
+		setrunqueue(l2, -1);
 	}
 	SCHED_UNLOCK(s);
 
Index: kern/kern_lwp.c
===================================================================
RCS file: /cvs/netbsd/src/sys/kern/kern_lwp.c,v
retrieving revision 1.8
diff -u -b -r1.8 kern_lwp.c
--- kern/kern_lwp.c	23 Jun 2003 11:02:05 -0000	1.8
+++ kern/kern_lwp.c	28 Jun 2003 19:40:51 -0000
@@ -105,7 +105,7 @@
 	if ((SCARG(uap, flags) & LWP_SUSPENDED) == 0) {
 		SCHED_LOCK(s);
 		l2->l_stat = LSRUN;
-		setrunqueue(l2);
+		setrunqueue(l2, -1);
 		SCHED_UNLOCK(s);
 		simple_lock(&p->p_lwplock);
 		p->p_nrlwps++;
@@ -278,7 +278,8 @@
 	if (l->l_wchan == 0) {
 		/* LWP was runnable before being suspended. */
 		SCHED_LOCK(s);
-		setrunnable(l);
+		setrunnable(l, (l->l_cpu && (l->l_flag & L_SA)) ?
+		    l->l_cpu->ci_cpuid : l->l_schedcpu);
 		SCHED_UNLOCK(s);
 	} else {
 		/* LWP was sleeping before being suspended. */
@@ -295,6 +296,7 @@
 	lwpid_t target_lid;
 	struct lwp *t;
 	struct proc *p;
+	int s;
 
 	p = l->l_proc;
 	target_lid = SCARG(uap, target);
@@ -312,7 +314,10 @@
 	if ((t->l_flag & L_SINTR) == 0)
 		return (EBUSY);
 
-	setrunnable(t);
+	SCHED_LOCK(s);
+	setrunnable(t, (t->l_cpu && (t->l_flag & L_SA)) ?
+	    t->l_cpu->ci_cpuid : l->l_schedcpu);
+	SCHED_UNLOCK(s);
 
 	return 0;
 }
@@ -469,6 +474,8 @@
 	 */
 	l2->l_cpu = NULL;
 #endif /* ! MULTIPROCESSOR */
+
+	l2->l_schedcpu = -1;
 
 	l2->l_flag = inmem ? L_INMEM : 0;
 	l2->l_flag |= (flags & LWP_DETACHED) ? L_DETACHED : 0;
Index: kern/kern_sa.c
===================================================================
RCS file: /cvs/netbsd/src/sys/kern/kern_sa.c,v
retrieving revision 1.16
diff -u -b -r1.16 kern_sa.c
--- kern/kern_sa.c	28 May 2003 22:17:20 -0000	1.16
+++ kern/kern_sa.c	28 Jun 2003 17:03:13 -0000
@@ -547,7 +547,7 @@
 
 		l->l_flag |= L_SA_BLOCKING;
 		l2->l_priority = l2->l_usrpri;
-		setrunnable(l2);
+		setrunnable(l2, cpu_number());
 		PRELE(l2); /* Remove the artificial hold-count */
 
 		KDASSERT(l2 != l);
@@ -589,7 +589,7 @@
 		cpu_setfunc(l2, sa_yieldcall, l2);
 
 		l2->l_priority = l2->l_usrpri;
-		setrunnable(l2);
+		setrunnable(l2, cpu_number());
 		PRELE(l2); /* Remove the artificial hold-count */
 	}
 
Index: kern/kern_sig.c
===================================================================
RCS file: /cvs/netbsd/src/sys/kern/kern_sig.c,v
retrieving revision 1.141
diff -u -b -r1.141 kern_sig.c
--- kern/kern_sig.c	20 May 2003 17:42:51 -0000	1.141
+++ kern/kern_sig.c	28 Jun 2003 17:40:28 -0000
@@ -1059,7 +1059,8 @@
 	if (l->l_priority > PUSER)
 		l->l_priority = PUSER;
  run:
-	setrunnable(l);		/* XXXSMP: recurse? */
+	setrunnable(l, (l->l_cpu && (l->l_flag & L_SA)) ?
+	    l->l_cpu->ci_cpuid : l->l_schedcpu); /* XXXSMP: recurse? */
  out:
 	/* XXXSMP: works, but icky */
 	if (dolock)
@@ -1428,7 +1429,8 @@
 				cantake = 1;
 			}
 		} else {
-			setrunnable(l);
+			setrunnable(l, (l->l_cpu && (l->l_flag & L_SA)) ?
+			    l->l_cpu->ci_cpuid : l->l_schedcpu);
 			lr = NULL;
 			cantake = 1;
 		}
Index: kern/kern_synch.c
===================================================================
RCS file: /cvs/netbsd/src/sys/kern/kern_synch.c,v
retrieving revision 1.130
diff -u -b -r1.130 kern_synch.c
--- kern/kern_synch.c	26 Jun 2003 02:09:27 -0000	1.130
+++ kern/kern_synch.c	28 Jun 2003 19:37:31 -0000
@@ -101,6 +101,7 @@
 #include <sys/sched.h>
 #include <sys/sa.h>
 #include <sys/savar.h>
+#include <sys/malloc.h>
 
 #include <uvm/uvm_extern.h>
 
@@ -116,8 +117,17 @@
 /*
  * The global scheduler state.
  */
+#if !defined(MULTIPROCESSOR)
 struct prochd sched_qs[RUNQUE_NQS];	/* run queues */
 __volatile u_int32_t sched_whichqs;	/* bitmap of non-empty queues */
+#define _cpuindex(x) (x)
+#else
+struct prochd *sched_qs[1+X86_MAXPROCS];	/* run queues */
+__volatile u_int32_t sched_whichqs[1+X86_MAXPROCS];	/* bitmap of non-empty queues */
+MALLOC_DEFINE(M_RQ, "runqueue", "runqueue");
+#define _cpuindex(x) (x)[cpu_id + 1]
+#endif
+
 struct slpque sched_slpque[SLPQUE_TABLESIZE]; /* sleep queues */
 
 struct simplelock sched_lock = SIMPLELOCK_INITIALIZER;
@@ -310,7 +320,7 @@
 				    (l->l_priority / PPQ) != (l->l_usrpri / PPQ)) {
 					remrunqueue(l);
 					l->l_priority = l->l_usrpri;
-					setrunqueue(l);
+					setrunqueue(l, l->l_schedcpu);
 				} else
 					l->l_priority = l->l_usrpri;
 			}
@@ -570,7 +580,8 @@
 	SCHED_LOCK(s);
 	if (l->l_wchan) {
 		if (l->l_stat == LSSLEEP)
-			setrunnable(l);
+			setrunnable(l, (l->l_cpu && (l->l_flag & L_SA)) ?
+			    l->l_cpu->ci_cpuid : l->l_schedcpu);
 		else
 			unsleep(l);
 		l->l_flag |= L_TIMEOUT;
@@ -622,9 +633,11 @@
 	 * XXXSMP See affinity comment in resched_proc().
 	 */
 	if (l->l_flag & L_INMEM) {
-		setrunqueue(l);
-		if (l->l_flag & L_SA)
+		if (l->l_flag & L_SA) {
 			l->l_proc->p_sa->sa_woken = l;
+			setrunqueue(l, l->l_cpu->ci_cpuid);
+		} else
+			setrunqueue(l, l->l_schedcpu);
 		KASSERT(l->l_cpu != NULL);
 		need_resched(l->l_cpu);
 	} else
@@ -773,7 +786,7 @@
 	SCHED_LOCK(s);
 	l->l_priority = l->l_usrpri;
 	l->l_stat = LSRUN;
-	setrunqueue(l);
+	setrunqueue(l, l->l_schedcpu);
 	l->l_proc->p_stats->p_ru.ru_nvcsw++;
 	mi_switch(l, NULL);
 	SCHED_ASSERT_UNLOCKED();
@@ -802,7 +815,7 @@
 	SCHED_LOCK(s);
 	l->l_priority = l->l_usrpri;
 	l->l_stat = LSRUN;
-	setrunqueue(l);
+	setrunqueue(l, l->l_schedcpu);
 	l->l_proc->p_stats->p_ru.ru_nivcsw++;
 	r = mi_switch(l, NULL);
 	SCHED_ASSERT_UNLOCKED();
@@ -972,13 +985,20 @@
  * to be empty.
  */
 void
-rqinit()
+rqinit(int cpu_id)
 {
 	int i;
 
-	for (i = 0; i < RUNQUE_NQS; i++)
-		sched_qs[i].ph_link = sched_qs[i].ph_rlink =
-		    (struct lwp *)&sched_qs[i];
+#if defined(MULTIPROCESSOR)
+	_cpuindex(sched_qs) = malloc(sizeof(struct prochd) * RUNQUE_NQS,
+	    M_RQ, M_WAITOK);
+#endif
+
+	for (i = 0; i < RUNQUE_NQS; i++) {
+		_cpuindex(sched_qs)[i].ph_link = _cpuindex(sched_qs)[i].ph_rlink =
+			(struct lwp *)&_cpuindex(sched_qs)[i];
+	}
+	_cpuindex(sched_whichqs) = 0;
 }
 
 static __inline void
@@ -1019,7 +1039,7 @@
  * and awakening the swapper if it isn't in memory.
  */
 void
-setrunnable(struct lwp *l)
+setrunnable(struct lwp *l, int cpu_id)
 {
 	struct proc *p = l->l_proc;
 
@@ -1054,8 +1074,9 @@
 	l->l_stat = LSRUN;
 	p->p_nrlwps++;
 
-	if (l->l_flag & L_INMEM)
-		setrunqueue(l);
+	if ((l->l_flag & L_INMEM)) {
+		setrunqueue(l, cpu_id);
+	}
 
 	if (l->l_slptime > 1)
 		updatepri(l);
@@ -1184,35 +1205,41 @@
  */
 
 void
-setrunqueue(struct lwp *l)
+setrunqueue(struct lwp *l, int cpu_id)
 {
 	struct prochd *rq;
 	struct lwp *prev;
 	int whichq;
 
+	SCHED_ASSERT_LOCKED();
+
 #ifdef DIAGNOSTIC
 	if (l->l_back != NULL || l->l_wchan != NULL || l->l_stat != LSRUN)
 		panic("setrunqueue");
 #endif
 	whichq = l->l_priority / 4;
-	sched_whichqs |= (1 << whichq);
-	rq = &sched_qs[whichq];
+	_cpuindex(sched_whichqs) |= (1 << whichq);
+	rq = &_cpuindex(sched_qs)[whichq];
 	prev = rq->ph_rlink;
 	l->l_forw = (struct lwp *)rq;
 	rq->ph_rlink = l;
 	prev->l_forw = l;
 	l->l_back = prev;
+	l->l_schedcpu = cpu_id;
 }
 
 void
 remrunqueue(struct lwp *l)
 {
 	struct lwp *prev, *next;
-	int whichq;
+	int whichq, cpu_id;
+
+	SCHED_ASSERT_LOCKED();
 
 	whichq = l->l_priority / 4;
+	cpu_id = l->l_schedcpu;
 #ifdef DIAGNOSTIC
-	if (((sched_whichqs & (1 << whichq)) == 0))
+	if (((_cpuindex(sched_whichqs) & (1 << whichq)) == 0))
 		panic("remrunqueue");
 #endif
 	prev = l->l_back;
@@ -1221,7 +1248,7 @@
 	prev->l_forw = next;
 	next->l_back = prev;
 	if (prev == next)
-		sched_whichqs &= ~(1 << whichq);
+		_cpuindex(sched_whichqs) &= ~(1 << whichq);
 }
 
 #endif
Index: kern/kern_time.c
===================================================================
RCS file: /cvs/netbsd/src/sys/kern/kern_time.c,v
retrieving revision 1.70
diff -u -b -r1.70 kern_time.c
--- kern/kern_time.c	28 May 2003 22:27:57 -0000	1.70
+++ kern/kern_time.c	28 Jun 2003 17:35:27 -0000
@@ -1217,7 +1217,9 @@
 			 */
 		        if ((sa->sa_idle) && (p->p_stat != SSTOP)) {
 				SCHED_LOCK(s);
-				setrunnable(sa->sa_idle);
+				setrunnable(sa->sa_idle, sa->sa_idle->l_cpu ?
+				    sa->sa_idle->l_cpu->ci_cpuid :
+				    sa->sa_idle->l_schedcpu);
 				SCHED_UNLOCK(s);
 			}
 			pt->pt_poverruns = pt->pt_overruns;
Index: kern/sys_generic.c
===================================================================
RCS file: /cvs/netbsd/src/sys/kern/sys_generic.c,v
retrieving revision 1.74
diff -u -b -r1.74 sys_generic.c
--- kern/sys_generic.c	28 May 2003 20:02:59 -0000	1.74
+++ kern/sys_generic.c	28 Jun 2003 17:30:49 -0000
@@ -1018,7 +1018,8 @@
 			SCHED_LOCK(s);
 			if (l->l_wchan == (caddr_t)&selwait) {
 				if (l->l_stat == LSSLEEP)
-					setrunnable(l);
+					setrunnable(l, (l->l_cpu && (l->l_flag & L_SA)) ?
+					    l->l_cpu->ci_cpuid : l->l_schedcpu);
 				else
 					unsleep(l);
 			} else if (l->l_flag & L_SELECT)
Index: kern/sys_process.c
===================================================================
RCS file: /cvs/netbsd/src/sys/kern/sys_process.c,v
retrieving revision 1.81
diff -u -b -r1.81 sys_process.c
--- kern/sys_process.c	20 May 2003 18:16:09 -0000	1.81
+++ kern/sys_process.c	28 Jun 2003 17:39:29 -0000
@@ -390,7 +390,8 @@
 			 * get it moving.
 			 */
 			if (lr && (t->p_xstat != 0))
-			    setrunnable(lr);
+			    setrunnable(lr, (lr->l_cpu && (lr->l_flag & L_SA)) ?
+				lr->l_cpu->ci_cpuid : lr->l_schedcpu);
 			SCHED_UNLOCK(s);
 		} else {
 			if (SCARG(uap, data) != 0)
Index: miscfs/procfs/procfs_ctl.c
===================================================================
RCS file: /cvs/netbsd/src/sys/miscfs/procfs/procfs_ctl.c,v
retrieving revision 1.24
diff -u -b -r1.24 procfs_ctl.c
--- miscfs/procfs/procfs_ctl.c	18 Jan 2003 09:18:06 -0000	1.24
+++ miscfs/procfs/procfs_ctl.c	28 Jun 2003 17:37:05 -0000
@@ -268,7 +268,8 @@
 		if (l->l_stat == LSSTOP) {
 			p->p_xstat = sig;
 			SCHED_LOCK(s);
-			setrunnable(l);
+			setrunnable(l, (l->l_cpu && (l->l_flag & L_SA)) ?
+			    l->l_cpu->ci_cpuid : l->l_schedcpu);
 			SCHED_UNLOCK(s);
 		} else {
 			if (sig != 0)
Index: sys/lwp.h
===================================================================
RCS file: /cvs/netbsd/src/sys/sys/lwp.h,v
retrieving revision 1.6
diff -u -b -r1.6 lwp.h
--- sys/lwp.h	4 Feb 2003 13:41:48 -0000	1.6
+++ sys/lwp.h	28 Jun 2003 17:27:19 -0000
@@ -63,6 +63,7 @@
 	int	l_flag;
 	int	l_stat;
 	lwpid_t	l_lid;		/* LWP identifier; local to process. */
+	int	l_schedcpu;
 
 #define l_startzero l_swtime
 	u_int	l_swtime;	/* Time swapped in or out. */
@@ -150,9 +151,9 @@
 void	remrunqueue (struct lwp *);
 #endif
 void	resetpriority (struct lwp *);
-void	setrunnable (struct lwp *);
+void	setrunnable (struct lwp *, int);
 #ifndef setrunqueue
-void	setrunqueue (struct lwp *);
+void	setrunqueue (struct lwp *, int);
 #endif
 #ifndef nextrunqueue
 struct lwp *nextrunqueue(void);
Index: sys/proc.h
===================================================================
RCS file: /cvs/netbsd/src/sys/sys/proc.h,v
retrieving revision 1.164
diff -u -b -r1.164 proc.h
--- sys/proc.h	3 Jun 2003 18:50:59 -0000	1.164
+++ sys/proc.h	28 Jun 2003 17:02:19 -0000
@@ -432,7 +432,7 @@
 void	exit_lwps(struct lwp *l);
 int	fork1(struct lwp *, int, int, void *, size_t,
 	    void (*)(void *), void *, register_t *, struct proc **);
-void	rqinit(void);
+void	rqinit(int);
 int	groupmember(gid_t, const struct ucred *);
 int	pgid_in_session(struct proc *, pid_t);
 #ifndef cpu_idle
Index: sys/sched.h
===================================================================
RCS file: /cvs/netbsd/src/sys/sys/sched.h,v
retrieving revision 1.17
diff -u -b -r1.17 sched.h
--- sys/sched.h	28 Apr 2003 23:16:29 -0000	1.17
+++ sys/sched.h	28 Jun 2003 19:36:44 -0000
@@ -197,9 +197,14 @@
  * simply give them meaningful names; the globals are actually declared
  * in kern/kern_synch.c.
  */
+#if !defined(MULTIPROCESSOR)
 extern struct prochd sched_qs[];
-extern struct slpque sched_slpque[];
 extern __volatile u_int32_t sched_whichqs;
+#else
+extern struct prochd *sched_qs[];
+extern __volatile u_int32_t sched_whichqs[];
+#endif
+extern struct slpque sched_slpque[];
 
 #define	SLPQUE(ident)	(&sched_slpque[SLPQUE_LOOKUP(ident)])
 
@@ -264,6 +269,12 @@
 #define	SCHED_UNLOCK(s)			splx(s)
 
 #endif /* MULTIPROCESSOR || LOCKDEBUG */
+
+#if defined(MULTIPROCESSOR)
+#define RQ_NOTEMPTY() ((sched_whichqs[0] != 0) || (sched_whichqs[cpu_number() + 1] != 0))
+#else
+#define RQ_NOTEMPTY() (sched_whichqs != 0)
+#endif
 
 #endif	/* _KERNEL */
 #endif	/* _SYS_SCHED_H_ */
Index: uvm/uvm_glue.c
===================================================================
RCS file: /cvs/netbsd/src/sys/uvm/uvm_glue.c,v
retrieving revision 1.64
diff -u -b -r1.64 uvm_glue.c
--- uvm/uvm_glue.c	14 Feb 2003 16:25:12 -0000	1.64
+++ uvm/uvm_glue.c	28 Jun 2003 17:31:51 -0000
@@ -471,7 +471,7 @@
 	cpu_swapin(l);
 	SCHED_LOCK(s);
 	if (l->l_stat == LSRUN)
-		setrunqueue(l);
+		setrunqueue(l, l->l_schedcpu);
 	l->l_flag |= L_INMEM;
 	SCHED_UNLOCK(s);
 	l->l_swtime = 0;
Index: uvm/uvm_page.c
===================================================================
RCS file: /cvs/netbsd/src/sys/uvm/uvm_page.c,v
retrieving revision 1.89
diff -u -b -r1.89 uvm_page.c
--- uvm/uvm_page.c	1 Jun 2003 09:26:10 -0000	1.89
+++ uvm/uvm_page.c	28 Jun 2003 17:02:19 -0000
@@ -1429,7 +1429,7 @@
 	s = uvm_lock_fpageq();
 	firstbucket = nextbucket;
 	do {
-		if (sched_whichqs != 0) {
+		if (RQ_NOTEMPTY()) {
 			uvm_unlock_fpageq(s);
 			return;
 		}
@@ -1442,7 +1442,7 @@
 			pgfl = &uvm.page_free[free_list];
 			while ((pg = TAILQ_FIRST(&pgfl->pgfl_buckets[
 			    nextbucket].pgfl_queues[PGFL_UNKNOWN])) != NULL) {
-				if (sched_whichqs != 0) {
+				if (RQ_NOTEMPTY()) {
 					uvm_unlock_fpageq(s);
 					return;
 				}


-- 
Christian Limpach <chris@pin.lu>