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