xref: /csrg-svn/sys/kern/kern_synch.c (revision 40710)
123376Smckusick /*
229096Smckusick  * Copyright (c) 1982, 1986 Regents of the University of California.
323376Smckusick  * All rights reserved.  The Berkeley software License Agreement
423376Smckusick  * specifies the terms and conditions for redistribution.
523376Smckusick  *
6*40710Smarc  *	@(#)kern_synch.c	7.10 (Berkeley) 04/03/90
723376Smckusick  */
833Sbill 
937495Smckusick #include "machine/pte.h"
1037495Smckusick #include "machine/psl.h"
1137495Smckusick #include "machine/mtpr.h"
129756Ssam 
1317093Sbloom #include "param.h"
1417093Sbloom #include "systm.h"
1517093Sbloom #include "user.h"
1617093Sbloom #include "proc.h"
1717093Sbloom #include "vm.h"
1817093Sbloom #include "kernel.h"
1917093Sbloom #include "buf.h"
20*40710Smarc #include "tsleep.h"
219756Ssam 
228102Sroot /*
238102Sroot  * Force switch among equal priority processes every 100ms.
248102Sroot  */
258102Sroot roundrobin()
268102Sroot {
278102Sroot 
288102Sroot 	runrun++;
298102Sroot 	aston();
308624Sroot 	timeout(roundrobin, (caddr_t)0, hz / 10);
318102Sroot }
328102Sroot 
3332908Smckusick /*
3432908Smckusick  * constants for digital decay and forget
3532908Smckusick  *	90% of (p_cpu) usage in 5*loadav time
3632908Smckusick  *	95% of (p_pctcpu) usage in 60 seconds (load insensitive)
3732908Smckusick  *          Note that, as ps(1) mentions, this can let percentages
3832908Smckusick  *          total over 100% (I've seen 137.9% for 3 processes).
3932908Smckusick  *
4032908Smckusick  * Note that hardclock updates p_cpu and p_cpticks independently.
4132908Smckusick  *
4232908Smckusick  * We wish to decay away 90% of p_cpu in (5 * loadavg) seconds.
4332908Smckusick  * That is, the system wants to compute a value of decay such
4432908Smckusick  * that the following for loop:
4532908Smckusick  * 	for (i = 0; i < (5 * loadavg); i++)
4632908Smckusick  * 		p_cpu *= decay;
4732908Smckusick  * will compute
4832908Smckusick  * 	p_cpu *= 0.1;
4932908Smckusick  * for all values of loadavg:
5032908Smckusick  *
5132908Smckusick  * Mathematically this loop can be expressed by saying:
5232908Smckusick  * 	decay ** (5 * loadavg) ~= .1
5332908Smckusick  *
5432908Smckusick  * The system computes decay as:
5532908Smckusick  * 	decay = (2 * loadavg) / (2 * loadavg + 1)
5632908Smckusick  *
5732908Smckusick  * We wish to prove that the system's computation of decay
5832908Smckusick  * will always fulfill the equation:
5932908Smckusick  * 	decay ** (5 * loadavg) ~= .1
6032908Smckusick  *
6132908Smckusick  * If we compute b as:
6232908Smckusick  * 	b = 2 * loadavg
6332908Smckusick  * then
6432908Smckusick  * 	decay = b / (b + 1)
6532908Smckusick  *
6632908Smckusick  * We now need to prove two things:
6732908Smckusick  *	1) Given factor ** (5 * loadavg) ~= .1, prove factor == b/(b+1)
6832908Smckusick  *	2) Given b/(b+1) ** power ~= .1, prove power == (5 * loadavg)
6932908Smckusick  *
7032908Smckusick  * Facts:
7132908Smckusick  *         For x close to zero, exp(x) =~ 1 + x, since
7232908Smckusick  *              exp(x) = 0! + x**1/1! + x**2/2! + ... .
7332908Smckusick  *              therefore exp(-1/b) =~ 1 - (1/b) = (b-1)/b.
7432908Smckusick  *         For x close to zero, ln(1+x) =~ x, since
7532908Smckusick  *              ln(1+x) = x - x**2/2 + x**3/3 - ...     -1 < x < 1
7632908Smckusick  *              therefore ln(b/(b+1)) = ln(1 - 1/(b+1)) =~ -1/(b+1).
7732908Smckusick  *         ln(.1) =~ -2.30
7832908Smckusick  *
7932908Smckusick  * Proof of (1):
8032908Smckusick  *    Solve (factor)**(power) =~ .1 given power (5*loadav):
8132908Smckusick  *	solving for factor,
8232908Smckusick  *      ln(factor) =~ (-2.30/5*loadav), or
8332908Smckusick  *      factor =~ exp(-1/((5/2.30)*loadav) =~ exp(-1/(2*loadav)) =
8432908Smckusick  *          exp(-1/b) =~ (b-1)/b =~ b/(b+1).                    QED
8532908Smckusick  *
8632908Smckusick  * Proof of (2):
8732908Smckusick  *    Solve (factor)**(power) =~ .1 given factor == (b/(b+1)):
8832908Smckusick  *	solving for power,
8932908Smckusick  *      power*ln(b/(b+1)) =~ -2.30, or
9032908Smckusick  *      power =~ 2.3 * (b + 1) = 4.6*loadav + 2.3 =~ 5*loadav.  QED
9132908Smckusick  *
9232908Smckusick  * Actual power values for the implemented algorithm are as follows:
9332908Smckusick  *      loadav: 1       2       3       4
9432908Smckusick  *      power:  5.68    10.32   14.94   19.55
9532908Smckusick  */
9617541Skarels 
9738164Smckusick /* calculations for digital decay to forget 90% of usage in 5*loadav sec */
9838164Smckusick #define	get_b(loadav)		(2 * (loadav))
9938164Smckusick #define	get_pcpu(b, cpu)	(((b) * ((cpu) & 0377)) / ((b) + FSCALE))
1008102Sroot 
10138164Smckusick /* decay 95% of `p_pctcpu' in 60 seconds; see CCPU_SHIFT before changing */
10238164Smckusick fixpt_t	ccpu = 0.95122942450071400909 * FSCALE;		/* exp(-1/20) */
10338164Smckusick 
1048102Sroot /*
10538164Smckusick  * If `ccpu' is not equal to `exp(-1/20)' and you still want to use the
10638164Smckusick  * faster/more-accurate formula, you'll have to estimate CCPU_SHIFT below
10738164Smckusick  * and possibly adjust FSHIFT in "param.h" so that (FSHIFT >= CCPU_SHIFT).
10838164Smckusick  *
10938164Smckusick  * To estimate CCPU_SHIFT for exp(-1/20), the following formula was used:
11038164Smckusick  *	1 - exp(-1/20) ~= 0.0487 ~= 0.0488 == 1 (fixed pt, *11* bits).
11138164Smckusick  *
11238164Smckusick  * If you dont want to bother with the faster/more-accurate formula, you
11338164Smckusick  * can set CCPU_SHIFT to (FSHIFT + 1) which will use a slower/less-accurate
11438164Smckusick  * (more general) method of calculating the %age of CPU used by a process.
11538164Smckusick  */
11638164Smckusick #define	CCPU_SHIFT	11
11738164Smckusick 
11838164Smckusick /*
1198102Sroot  * Recompute process priorities, once a second
1208102Sroot  */
1218102Sroot schedcpu()
1228102Sroot {
12338164Smckusick 	register fixpt_t b = get_b(averunnable[0]);
1248102Sroot 	register struct proc *p;
1258102Sroot 	register int s, a;
1268102Sroot 
1278102Sroot 	wakeup((caddr_t)&lbolt);
12816532Skarels 	for (p = allproc; p != NULL; p = p->p_nxt) {
1298102Sroot 		if (p->p_time != 127)
1308102Sroot 			p->p_time++;
1318102Sroot 		if (p->p_stat==SSLEEP || p->p_stat==SSTOP)
1328102Sroot 			if (p->p_slptime != 127)
1338102Sroot 				p->p_slptime++;
13438164Smckusick 		p->p_pctcpu = (p->p_pctcpu * ccpu) >> FSHIFT;
13517541Skarels 		/*
13617541Skarels 		 * If the process has slept the entire second,
13717541Skarels 		 * stop recalculating its priority until it wakes up.
13817541Skarels 		 */
13938164Smckusick 		if (p->p_slptime > 1)
14017541Skarels 			continue;
14117541Skarels 		/*
14217541Skarels 		 * p_pctcpu is only for ps.
14317541Skarels 		 */
14438164Smckusick #if	(FSHIFT >= CCPU_SHIFT)
14538164Smckusick 		p->p_pctcpu += (hz == 100)?
14638164Smckusick 			((fixpt_t) p->p_cpticks) << (FSHIFT - CCPU_SHIFT):
14738164Smckusick                 	100 * (((fixpt_t) p->p_cpticks)
14838164Smckusick 				<< (FSHIFT - CCPU_SHIFT)) / hz;
14938164Smckusick #else
15038164Smckusick 		p->p_pctcpu += ((FSCALE - ccpu) *
15138164Smckusick 			(p->p_cpticks * FSCALE / hz)) >> FSHIFT;
15238164Smckusick #endif
1538102Sroot 		p->p_cpticks = 0;
15438164Smckusick 		a = (int) get_pcpu(b, p->p_cpu) + p->p_nice;
1558102Sroot 		if (a < 0)
1568102Sroot 			a = 0;
1578102Sroot 		if (a > 255)
1588102Sroot 			a = 255;
1598102Sroot 		p->p_cpu = a;
1608102Sroot 		(void) setpri(p);
16117541Skarels 		s = splhigh();	/* prevent state changes */
1628102Sroot 		if (p->p_pri >= PUSER) {
16316795Skarels #define	PPQ	(128 / NQS)
1648102Sroot 			if ((p != u.u_procp || noproc) &&
1658102Sroot 			    p->p_stat == SRUN &&
1668102Sroot 			    (p->p_flag & SLOAD) &&
16716795Skarels 			    (p->p_pri / PPQ) != (p->p_usrpri / PPQ)) {
1688102Sroot 				remrq(p);
1698102Sroot 				p->p_pri = p->p_usrpri;
1708102Sroot 				setrq(p);
1718102Sroot 			} else
1728102Sroot 				p->p_pri = p->p_usrpri;
1738102Sroot 		}
1748102Sroot 		splx(s);
1758102Sroot 	}
1768102Sroot 	vmmeter();
1778102Sroot 	if (runin!=0) {
1788102Sroot 		runin = 0;
1798102Sroot 		wakeup((caddr_t)&runin);
1808102Sroot 	}
1818102Sroot 	if (bclnlist != NULL)
1828102Sroot 		wakeup((caddr_t)&proc[2]);
1838624Sroot 	timeout(schedcpu, (caddr_t)0, hz);
1848102Sroot }
1858102Sroot 
18617541Skarels /*
18717541Skarels  * Recalculate the priority of a process after it has slept for a while.
18817541Skarels  */
18917541Skarels updatepri(p)
19017541Skarels 	register struct proc *p;
19117541Skarels {
19217541Skarels 	register int a = p->p_cpu & 0377;
19338164Smckusick 	register fixpt_t b = get_b(averunnable[0]);
19417541Skarels 
19517541Skarels 	p->p_slptime--;		/* the first time was done in schedcpu */
19617541Skarels 	while (a && --p->p_slptime)
19738164Smckusick 		a = (int) get_pcpu(b, a) /* + p->p_nice */;
19830232Skarels 	p->p_slptime = 0;
19917541Skarels 	if (a < 0)
20017541Skarels 		a = 0;
20117541Skarels 	if (a > 255)
20217541Skarels 		a = 255;
20317541Skarels 	p->p_cpu = a;
20417541Skarels 	(void) setpri(p);
20517541Skarels }
20617541Skarels 
20733Sbill #define SQSIZE 0100	/* Must be power of 2 */
20833Sbill #define HASH(x)	(( (int) x >> 5) & (SQSIZE-1))
20921099Smckusick struct slpque {
21021099Smckusick 	struct proc *sq_head;
21121099Smckusick 	struct proc **sq_tailp;
21221099Smckusick } slpque[SQSIZE];
21333Sbill 
21433Sbill /*
215*40710Smarc  * XXX - redo comments once interface is set
216*40710Smarc  *
21733Sbill  * Give up the processor till a wakeup occurs
21833Sbill  * on chan, at which time the process
21933Sbill  * enters the scheduling queue at priority pri.
22033Sbill  * The most important effect of pri is that when
22133Sbill  * pri<=PZERO a signal cannot disturb the sleep;
22233Sbill  * if pri>PZERO signals will be processed.
22333Sbill  * Callers of this routine must be prepared for
22433Sbill  * premature return, and check that the reason for
22533Sbill  * sleeping has gone away.
22633Sbill  */
227*40710Smarc 
228*40710Smarc /*
229*40710Smarc  * interruptable sleep with longjmp processing.
230*40710Smarc  * TEMPORARY UNTIL ALL CALLERS ARE TAUGHT TO UNWIND
231*40710Smarc  */
232*40710Smarc tsleep(chan, pri, wmesg, timeout)
233*40710Smarc 	caddr_t chan;
234*40710Smarc 	int pri;
235*40710Smarc 	char *wmesg;
236*40710Smarc 	int timeout;
237*40710Smarc {
238*40710Smarc 	if (pri <= PZERO)
239*40710Smarc 		panic("tsleep: pri <= PZERO");
240*40710Smarc 	if (isleep(chan, pri, wmesg, timeout) == EINTR)
241*40710Smarc 		longjmp(&u.u_qsave);
242*40710Smarc }
243*40710Smarc 
244*40710Smarc /*
245*40710Smarc  * Interruptable sleep.
246*40710Smarc  * Sleeps on chan for time of at most timo/hz seconds (0 means no timeout).
247*40710Smarc  * Returns 0 if awakened, EINTR if a signal needs to be delivered,
248*40710Smarc  * or EWOULDBLOCK if the timeout expires.
249*40710Smarc  */
250*40710Smarc isleep(chan, pri, wmesg, timo)
251*40710Smarc 	caddr_t chan;
252*40710Smarc 	int pri;
253*40710Smarc 	char *wmesg;
254*40710Smarc 	int timo;
255*40710Smarc {
256*40710Smarc 	register struct proc *rp;
257*40710Smarc 	register struct slpque *qp;
258*40710Smarc 	register s;
259*40710Smarc 	extern int cold;
260*40710Smarc 	int endtsleep();
261*40710Smarc 
262*40710Smarc 	rp = u.u_procp;
263*40710Smarc 	s = splhigh();
264*40710Smarc 	if (cold || panicstr) {
265*40710Smarc 		/*
266*40710Smarc 		 * After a panic, or during autoconfiguration,
267*40710Smarc 		 * just give interrupts a chance, then just return;
268*40710Smarc 		 * don't run any other procs or panic below,
269*40710Smarc 		 * in case this is the idle process and already asleep.
270*40710Smarc 		 * The splnet should be spl0 if the network was being used
271*40710Smarc 		 * by the filesystem, but for now avoid network interrupts
272*40710Smarc 		 * that might cause another panic.
273*40710Smarc 		 */
274*40710Smarc 		(void) splnet();
275*40710Smarc 		splx(s);
276*40710Smarc 		return (0);
277*40710Smarc 	}
278*40710Smarc #ifdef DIAGNOSTIC
279*40710Smarc 	if (chan==0 || rp->p_stat != SRUN || rp->p_rlink)
280*40710Smarc 		panic("isleep");
281*40710Smarc #endif
282*40710Smarc 	rp->p_wchan = chan;
283*40710Smarc 	rp->p_wmesg = wmesg;
284*40710Smarc 	rp->p_slptime = 0;
285*40710Smarc 	rp->p_pri = pri;
286*40710Smarc 	qp = &slpque[HASH(chan)];
287*40710Smarc 	if (qp->sq_head == 0)
288*40710Smarc 		qp->sq_head = rp;
289*40710Smarc 	else
290*40710Smarc 		*qp->sq_tailp = rp;
291*40710Smarc 	*(qp->sq_tailp = &rp->p_link) = 0;
292*40710Smarc 	/*
293*40710Smarc 	 * If we stop in issig(), wakeup may already have happened
294*40710Smarc 	 * when we return (rp->p_wchan will then be 0).
295*40710Smarc 	 */
296*40710Smarc 	if (CURSIG(rp)) {
297*40710Smarc 		if (rp->p_wchan)
298*40710Smarc 			unsleep(rp);
299*40710Smarc 		rp->p_stat = SRUN;
300*40710Smarc 		splx(s);
301*40710Smarc 		return (EINTR);
302*40710Smarc 	}
303*40710Smarc 	if (rp->p_wchan == 0) {
304*40710Smarc 		splx(s);
305*40710Smarc 		return (0);
306*40710Smarc 	}
307*40710Smarc 	rp->p_stat = SSLEEP;
308*40710Smarc 	if (timo)
309*40710Smarc 		timeout(endtsleep, (caddr_t)rp, timo);
310*40710Smarc 	(void) spl0();
311*40710Smarc 	u.u_ru.ru_nvcsw++;
312*40710Smarc 	swtch();
313*40710Smarc 	curpri = rp->p_usrpri;
314*40710Smarc 	splx(s);
315*40710Smarc 	if (rp->p_flag & STIMO) {
316*40710Smarc 		rp->p_flag &= ~STIMO;
317*40710Smarc 		return (EWOULDBLOCK);
318*40710Smarc 	}
319*40710Smarc 	if (timo)
320*40710Smarc 		untimeout(endtsleep, (caddr_t)rp);
321*40710Smarc 	if (CURSIG(rp))
322*40710Smarc 		return (EINTR);
323*40710Smarc 	return (0);
324*40710Smarc }
325*40710Smarc 
326*40710Smarc /*
327*40710Smarc  * Implement timeout for tsleep.
328*40710Smarc  * If process hasn't been awakened (wchan non-zero),
329*40710Smarc  * set timeout flag and undo the sleep.  If proc
330*40710Smarc  * is stopped, just unsleep so it will remain stopped.
331*40710Smarc  */
332*40710Smarc endtsleep(p)
333*40710Smarc 	register struct proc *p;
334*40710Smarc {
335*40710Smarc 	int s = splhigh();
336*40710Smarc 
337*40710Smarc 	if (p->p_wchan) {
338*40710Smarc 		if (p->p_stat == SSLEEP)
339*40710Smarc 			setrun(p);
340*40710Smarc 		else
341*40710Smarc 			unsleep(p);
342*40710Smarc 		p->p_flag |= STIMO;
343*40710Smarc 	}
344*40710Smarc 	splx(s);
345*40710Smarc }
346*40710Smarc 
347*40710Smarc int sleepdebug = 1;	/* XXX */
348*40710Smarc 
34933Sbill sleep(chan, pri)
3508033Sroot 	caddr_t chan;
3518033Sroot 	int pri;
35233Sbill {
35321099Smckusick 	register struct proc *rp;
35421099Smckusick 	register struct slpque *qp;
355207Sbill 	register s;
35630532Skarels 	extern int cold;
35733Sbill 
35833Sbill 	rp = u.u_procp;
35917541Skarels 	s = splhigh();
36030532Skarels 	if (cold || panicstr) {
36118363Skarels 		/*
36230532Skarels 		 * After a panic, or during autoconfiguration,
36330532Skarels 		 * just give interrupts a chance, then just return;
36430532Skarels 		 * don't run any other procs or panic below,
36530532Skarels 		 * in case this is the idle process and already asleep.
36618363Skarels 		 * The splnet should be spl0 if the network was being used
36718363Skarels 		 * by the filesystem, but for now avoid network interrupts
36818363Skarels 		 * that might cause another panic.
36918363Skarels 		 */
37018363Skarels 		(void) splnet();
37118363Skarels 		splx(s);
37218363Skarels 		return;
37318363Skarels 	}
374*40710Smarc #ifdef DIAGNOSTIC
37518363Skarels 	if (chan==0 || rp->p_stat != SRUN || rp->p_rlink)
37633Sbill 		panic("sleep");
377*40710Smarc #endif
37833Sbill 	rp->p_wchan = chan;
379*40710Smarc 	rp->p_wmesg = NULL;
38033Sbill 	rp->p_slptime = 0;
38133Sbill 	rp->p_pri = pri;
38221099Smckusick 	qp = &slpque[HASH(chan)];
38321099Smckusick 	if (qp->sq_head == 0)
38421099Smckusick 		qp->sq_head = rp;
38521099Smckusick 	else
38621099Smckusick 		*qp->sq_tailp = rp;
38721099Smckusick 	*(qp->sq_tailp = &rp->p_link) = 0;
3884826Swnj 	if (pri > PZERO) {
389*40710Smarc 		if (sleepdebug)
390*40710Smarc 			printf("sleep called with pri > PZERO, wchan: %x\n",
391*40710Smarc 				chan);
39221763Skarels 		/*
39321763Skarels 		 * If we stop in issig(), wakeup may already have happened
39421763Skarels 		 * when we return (rp->p_wchan will then be 0).
39521763Skarels 		 */
396*40710Smarc 		if (CURSIG(rp)) {
397187Sbill 			if (rp->p_wchan)
398187Sbill 				unsleep(rp);
39933Sbill 			rp->p_stat = SRUN;
400131Sbill 			(void) spl0();
40133Sbill 			goto psig;
40233Sbill 		}
403187Sbill 		if (rp->p_wchan == 0)
404187Sbill 			goto out;
405187Sbill 		rp->p_stat = SSLEEP;
406131Sbill 		(void) spl0();
4078033Sroot 		u.u_ru.ru_nvcsw++;
40833Sbill 		swtch();
409*40710Smarc 		if (CURSIG(rp))
41033Sbill 			goto psig;
41133Sbill 	} else {
412207Sbill 		rp->p_stat = SSLEEP;
413131Sbill 		(void) spl0();
4148033Sroot 		u.u_ru.ru_nvcsw++;
41533Sbill 		swtch();
41633Sbill 	}
41716795Skarels 	curpri = rp->p_usrpri;
418187Sbill out:
41933Sbill 	splx(s);
42033Sbill 	return;
42133Sbill 
42233Sbill 	/*
42333Sbill 	 * If priority was low (>PZERO) and
4244826Swnj 	 * there has been a signal, execute non-local goto through
4258113Sroot 	 * u.u_qsave, aborting the system call in progress (see trap.c)
42633Sbill 	 */
42733Sbill psig:
4288113Sroot 	longjmp(&u.u_qsave);
42933Sbill 	/*NOTREACHED*/
43033Sbill }
43133Sbill 
43233Sbill /*
433181Sbill  * Remove a process from its wait queue
434181Sbill  */
435181Sbill unsleep(p)
4364826Swnj 	register struct proc *p;
437181Sbill {
43821099Smckusick 	register struct slpque *qp;
439181Sbill 	register struct proc **hp;
44021099Smckusick 	int s;
441181Sbill 
44217541Skarels 	s = splhigh();
443181Sbill 	if (p->p_wchan) {
44421099Smckusick 		hp = &(qp = &slpque[HASH(p->p_wchan)])->sq_head;
445181Sbill 		while (*hp != p)
446181Sbill 			hp = &(*hp)->p_link;
447181Sbill 		*hp = p->p_link;
44821099Smckusick 		if (qp->sq_tailp == &p->p_link)
44921099Smckusick 			qp->sq_tailp = hp;
450181Sbill 		p->p_wchan = 0;
451181Sbill 	}
452181Sbill 	splx(s);
453181Sbill }
454181Sbill 
455181Sbill /*
45633Sbill  * Wake up all processes sleeping on chan.
45733Sbill  */
45833Sbill wakeup(chan)
4594826Swnj 	register caddr_t chan;
46033Sbill {
46121099Smckusick 	register struct slpque *qp;
46221099Smckusick 	register struct proc *p, **q;
46333Sbill 	int s;
46433Sbill 
46517541Skarels 	s = splhigh();
46621099Smckusick 	qp = &slpque[HASH(chan)];
46733Sbill restart:
46821099Smckusick 	for (q = &qp->sq_head; p = *q; ) {
469*40710Smarc #ifdef DIAGNOSTIC
470181Sbill 		if (p->p_rlink || p->p_stat != SSLEEP && p->p_stat != SSTOP)
47133Sbill 			panic("wakeup");
472*40710Smarc #endif
473207Sbill 		if (p->p_wchan==chan) {
47433Sbill 			p->p_wchan = 0;
475187Sbill 			*q = p->p_link;
47621099Smckusick 			if (qp->sq_tailp == &p->p_link)
47721099Smckusick 				qp->sq_tailp = q;
478181Sbill 			if (p->p_stat == SSLEEP) {
479181Sbill 				/* OPTIMIZED INLINE EXPANSION OF setrun(p) */
48021763Skarels 				if (p->p_slptime > 1)
48121763Skarels 					updatepri(p);
482181Sbill 				p->p_stat = SRUN;
4832702Swnj 				if (p->p_flag & SLOAD)
484181Sbill 					setrq(p);
48516795Skarels 				/*
48616795Skarels 				 * Since curpri is a usrpri,
48716795Skarels 				 * p->p_pri is always better than curpri.
48816795Skarels 				 */
48916795Skarels 				runrun++;
49016795Skarels 				aston();
4913545Swnj 				if ((p->p_flag&SLOAD) == 0) {
4923545Swnj 					if (runout != 0) {
4933545Swnj 						runout = 0;
4943545Swnj 						wakeup((caddr_t)&runout);
4953545Swnj 					}
4963545Swnj 					wantin++;
497181Sbill 				}
498181Sbill 				/* END INLINE EXPANSION */
499187Sbill 				goto restart;
50033Sbill 			}
501187Sbill 		} else
502187Sbill 			q = &p->p_link;
50333Sbill 	}
50433Sbill 	splx(s);
50533Sbill }
50633Sbill 
50733Sbill /*
50833Sbill  * Initialize the (doubly-linked) run queues
50933Sbill  * to be empty.
51033Sbill  */
51133Sbill rqinit()
51233Sbill {
51333Sbill 	register int i;
51433Sbill 
51533Sbill 	for (i = 0; i < NQS; i++)
51633Sbill 		qs[i].ph_link = qs[i].ph_rlink = (struct proc *)&qs[i];
51733Sbill }
51833Sbill 
51933Sbill /*
52033Sbill  * Set the process running;
52133Sbill  * arrange for it to be swapped in if necessary.
52233Sbill  */
52333Sbill setrun(p)
5244826Swnj 	register struct proc *p;
52533Sbill {
5264826Swnj 	register int s;
52733Sbill 
52817541Skarels 	s = splhigh();
52933Sbill 	switch (p->p_stat) {
53033Sbill 
53133Sbill 	case 0:
53233Sbill 	case SWAIT:
53333Sbill 	case SRUN:
53433Sbill 	case SZOMB:
53533Sbill 	default:
53633Sbill 		panic("setrun");
53733Sbill 
538207Sbill 	case SSTOP:
53933Sbill 	case SSLEEP:
540181Sbill 		unsleep(p);		/* e.g. when sending signals */
54133Sbill 		break;
54233Sbill 
54333Sbill 	case SIDL:
54433Sbill 		break;
54533Sbill 	}
54633Sbill 	p->p_stat = SRUN;
54733Sbill 	if (p->p_flag & SLOAD)
54833Sbill 		setrq(p);
54933Sbill 	splx(s);
55030232Skarels 	if (p->p_slptime > 1)
55130232Skarels 		updatepri(p);
5524826Swnj 	if (p->p_pri < curpri) {
55333Sbill 		runrun++;
5542443Swnj 		aston();
5552443Swnj 	}
5563545Swnj 	if ((p->p_flag&SLOAD) == 0) {
5574826Swnj 		if (runout != 0) {
5583545Swnj 			runout = 0;
5593545Swnj 			wakeup((caddr_t)&runout);
5603545Swnj 		}
5613545Swnj 		wantin++;
56233Sbill 	}
56333Sbill }
56433Sbill 
56533Sbill /*
56633Sbill  * Set user priority.
56733Sbill  * The rescheduling flag (runrun)
56833Sbill  * is set if the priority is better
56933Sbill  * than the currently running process.
57033Sbill  */
57133Sbill setpri(pp)
5724826Swnj 	register struct proc *pp;
57333Sbill {
5744826Swnj 	register int p;
57533Sbill 
5763875Swnj 	p = (pp->p_cpu & 0377)/4;
57717541Skarels 	p += PUSER + 2 * pp->p_nice;
5783530Swnj 	if (pp->p_rssize > pp->p_maxrss && freemem < desfree)
5793530Swnj 		p += 2*4;	/* effectively, nice(4) */
5804826Swnj 	if (p > 127)
58133Sbill 		p = 127;
5824826Swnj 	if (p < curpri) {
58333Sbill 		runrun++;
5842453Swnj 		aston();
5852453Swnj 	}
58633Sbill 	pp->p_usrpri = p;
5874826Swnj 	return (p);
58833Sbill }
589