149594Sbostic /*- 263176Sbostic * Copyright (c) 1982, 1986, 1990, 1991, 1993 363176Sbostic * The Regents of the University of California. All rights reserved. 449594Sbostic * All rights reserved. 523376Smckusick * 649594Sbostic * %sccs.include.redist.c% 749594Sbostic * 8*64636Sbostic * @(#)kern_synch.c 8.5 (Berkeley) 09/23/93 923376Smckusick */ 1033Sbill 1156517Sbostic #include <sys/param.h> 1256517Sbostic #include <sys/systm.h> 1356517Sbostic #include <sys/proc.h> 1456517Sbostic #include <sys/kernel.h> 1556517Sbostic #include <sys/buf.h> 1656517Sbostic #include <sys/signalvar.h> 1756517Sbostic #include <sys/resourcevar.h> 1856517Sbostic #include <sys/vmmeter.h> 1952498Smarc #ifdef KTRACE 2056517Sbostic #include <sys/ktrace.h> 2152498Smarc #endif 229756Ssam 2356517Sbostic #include <machine/cpu.h> 2445742Smckusick 2564413Sbostic u_char curpriority; /* usrpri of curproc */ 2652686Ssklower int lbolt; /* once a second sleep address */ 2749226Skarels 288102Sroot /* 298102Sroot * Force switch among equal priority processes every 100ms. 308102Sroot */ 3154788Storek /* ARGSUSED */ 3254788Storek void 3354788Storek roundrobin(arg) 3454788Storek void *arg; 358102Sroot { 368102Sroot 3747544Skarels need_resched(); 3864413Sbostic timeout(roundrobin, NULL, hz / 10); 398102Sroot } 408102Sroot 4132908Smckusick /* 4264590Sbostic * Constants for digital decay and forget: 4364590Sbostic * 90% of (p_estcpu) usage in 5 * loadav time 4432908Smckusick * 95% of (p_pctcpu) usage in 60 seconds (load insensitive) 4532908Smckusick * Note that, as ps(1) mentions, this can let percentages 4632908Smckusick * total over 100% (I've seen 137.9% for 3 processes). 4732908Smckusick * 4864590Sbostic * Note that hardclock updates p_estcpu and p_cpticks independently. 4932908Smckusick * 5064590Sbostic * We wish to decay away 90% of p_estcpu in (5 * loadavg) seconds. 5132908Smckusick * That is, the system wants to compute a value of decay such 5232908Smckusick * that the following for loop: 5332908Smckusick * for (i = 0; i < (5 * loadavg); i++) 5464590Sbostic * p_estcpu *= decay; 5532908Smckusick * will compute 5664590Sbostic * p_estcpu *= 0.1; 5732908Smckusick * for all values of loadavg: 5832908Smckusick * 5932908Smckusick * Mathematically this loop can be expressed by saying: 6032908Smckusick * decay ** (5 * loadavg) ~= .1 6132908Smckusick * 6232908Smckusick * The system computes decay as: 6332908Smckusick * decay = (2 * loadavg) / (2 * loadavg + 1) 6432908Smckusick * 6532908Smckusick * We wish to prove that the system's computation of decay 6632908Smckusick * will always fulfill the equation: 6732908Smckusick * decay ** (5 * loadavg) ~= .1 6832908Smckusick * 6932908Smckusick * If we compute b as: 7032908Smckusick * b = 2 * loadavg 7132908Smckusick * then 7232908Smckusick * decay = b / (b + 1) 7332908Smckusick * 7432908Smckusick * We now need to prove two things: 7532908Smckusick * 1) Given factor ** (5 * loadavg) ~= .1, prove factor == b/(b+1) 7632908Smckusick * 2) Given b/(b+1) ** power ~= .1, prove power == (5 * loadavg) 7732908Smckusick * 7832908Smckusick * Facts: 7932908Smckusick * For x close to zero, exp(x) =~ 1 + x, since 8032908Smckusick * exp(x) = 0! + x**1/1! + x**2/2! + ... . 8132908Smckusick * therefore exp(-1/b) =~ 1 - (1/b) = (b-1)/b. 8232908Smckusick * For x close to zero, ln(1+x) =~ x, since 8332908Smckusick * ln(1+x) = x - x**2/2 + x**3/3 - ... -1 < x < 1 8432908Smckusick * therefore ln(b/(b+1)) = ln(1 - 1/(b+1)) =~ -1/(b+1). 8532908Smckusick * ln(.1) =~ -2.30 8632908Smckusick * 8732908Smckusick * Proof of (1): 8832908Smckusick * Solve (factor)**(power) =~ .1 given power (5*loadav): 8932908Smckusick * solving for factor, 9032908Smckusick * ln(factor) =~ (-2.30/5*loadav), or 9147544Skarels * factor =~ exp(-1/((5/2.30)*loadav)) =~ exp(-1/(2*loadav)) = 9232908Smckusick * exp(-1/b) =~ (b-1)/b =~ b/(b+1). QED 9332908Smckusick * 9432908Smckusick * Proof of (2): 9532908Smckusick * Solve (factor)**(power) =~ .1 given factor == (b/(b+1)): 9632908Smckusick * solving for power, 9732908Smckusick * power*ln(b/(b+1)) =~ -2.30, or 9832908Smckusick * power =~ 2.3 * (b + 1) = 4.6*loadav + 2.3 =~ 5*loadav. QED 9932908Smckusick * 10032908Smckusick * Actual power values for the implemented algorithm are as follows: 10132908Smckusick * loadav: 1 2 3 4 10232908Smckusick * power: 5.68 10.32 14.94 19.55 10332908Smckusick */ 10417541Skarels 10538164Smckusick /* calculations for digital decay to forget 90% of usage in 5*loadav sec */ 10647544Skarels #define loadfactor(loadav) (2 * (loadav)) 10747544Skarels #define decay_cpu(loadfac, cpu) (((loadfac) * (cpu)) / ((loadfac) + FSCALE)) 1088102Sroot 10938164Smckusick /* decay 95% of `p_pctcpu' in 60 seconds; see CCPU_SHIFT before changing */ 11038164Smckusick fixpt_t ccpu = 0.95122942450071400909 * FSCALE; /* exp(-1/20) */ 11138164Smckusick 1128102Sroot /* 11338164Smckusick * If `ccpu' is not equal to `exp(-1/20)' and you still want to use the 11438164Smckusick * faster/more-accurate formula, you'll have to estimate CCPU_SHIFT below 11538164Smckusick * and possibly adjust FSHIFT in "param.h" so that (FSHIFT >= CCPU_SHIFT). 11638164Smckusick * 11738164Smckusick * To estimate CCPU_SHIFT for exp(-1/20), the following formula was used: 11838164Smckusick * 1 - exp(-1/20) ~= 0.0487 ~= 0.0488 == 1 (fixed pt, *11* bits). 11938164Smckusick * 12038164Smckusick * If you dont want to bother with the faster/more-accurate formula, you 12138164Smckusick * can set CCPU_SHIFT to (FSHIFT + 1) which will use a slower/less-accurate 12238164Smckusick * (more general) method of calculating the %age of CPU used by a process. 12338164Smckusick */ 12438164Smckusick #define CCPU_SHIFT 11 12538164Smckusick 12638164Smckusick /* 12764413Sbostic * Recompute process priorities, every hz ticks. 1288102Sroot */ 12954788Storek /* ARGSUSED */ 13054788Storek void 13154788Storek schedcpu(arg) 13254788Storek void *arg; 1338102Sroot { 13452667Smckusick register fixpt_t loadfac = loadfactor(averunnable.ldavg[0]); 1358102Sroot register struct proc *p; 13647544Skarels register int s; 13747544Skarels register unsigned int newcpu; 1388102Sroot 1398102Sroot wakeup((caddr_t)&lbolt); 14064590Sbostic for (p = (struct proc *)allproc; p != NULL; p = p->p_next) { 14147544Skarels /* 14247544Skarels * Increment time in/out of memory and sleep time 14347544Skarels * (if sleeping). We ignore overflow; with 16-bit int's 14447544Skarels * (remember them?) overflow takes 45 days. 14547544Skarels */ 14664590Sbostic p->p_swtime++; 14747544Skarels if (p->p_stat == SSLEEP || p->p_stat == SSTOP) 14847544Skarels p->p_slptime++; 14938164Smckusick p->p_pctcpu = (p->p_pctcpu * ccpu) >> FSHIFT; 15017541Skarels /* 15117541Skarels * If the process has slept the entire second, 15217541Skarels * stop recalculating its priority until it wakes up. 15317541Skarels */ 15438164Smckusick if (p->p_slptime > 1) 15517541Skarels continue; 15656895Storek s = splstatclock(); /* prevent state changes */ 15717541Skarels /* 15817541Skarels * p_pctcpu is only for ps. 15917541Skarels */ 16038164Smckusick #if (FSHIFT >= CCPU_SHIFT) 16138164Smckusick p->p_pctcpu += (hz == 100)? 16238164Smckusick ((fixpt_t) p->p_cpticks) << (FSHIFT - CCPU_SHIFT): 16338164Smckusick 100 * (((fixpt_t) p->p_cpticks) 16438164Smckusick << (FSHIFT - CCPU_SHIFT)) / hz; 16538164Smckusick #else 16638164Smckusick p->p_pctcpu += ((FSCALE - ccpu) * 16738164Smckusick (p->p_cpticks * FSCALE / hz)) >> FSHIFT; 16838164Smckusick #endif 1698102Sroot p->p_cpticks = 0; 17064590Sbostic newcpu = (u_int) decay_cpu(loadfac, p->p_estcpu) + p->p_nice; 17164590Sbostic p->p_estcpu = min(newcpu, UCHAR_MAX); 17264413Sbostic resetpriority(p); 17364590Sbostic if (p->p_priority >= PUSER) { 17447544Skarels #define PPQ (128 / NQS) /* priorities per queue */ 17549095Skarels if ((p != curproc) && 1768102Sroot p->p_stat == SRUN && 17764590Sbostic (p->p_flag & P_INMEM) && 17864590Sbostic (p->p_priority / PPQ) != (p->p_usrpri / PPQ)) { 1798102Sroot remrq(p); 18064590Sbostic p->p_priority = p->p_usrpri; 18164533Sbostic setrunqueue(p); 1828102Sroot } else 18364590Sbostic p->p_priority = p->p_usrpri; 1848102Sroot } 1858102Sroot splx(s); 1868102Sroot } 1878102Sroot vmmeter(); 1888102Sroot if (bclnlist != NULL) 18947544Skarels wakeup((caddr_t)pageproc); 19054788Storek timeout(schedcpu, (void *)0, hz); 1918102Sroot } 1928102Sroot 19317541Skarels /* 19417541Skarels * Recalculate the priority of a process after it has slept for a while. 19564590Sbostic * For all load averages >= 1 and max p_estcpu of 255, sleeping for at 19664590Sbostic * least six times the loadfactor will decay p_estcpu to zero. 19717541Skarels */ 19854788Storek void 19917541Skarels updatepri(p) 20017541Skarels register struct proc *p; 20117541Skarels { 20264590Sbostic register unsigned int newcpu = p->p_estcpu; 20352667Smckusick register fixpt_t loadfac = loadfactor(averunnable.ldavg[0]); 20417541Skarels 20547544Skarels if (p->p_slptime > 5 * loadfac) 20664590Sbostic p->p_estcpu = 0; 20747544Skarels else { 20847544Skarels p->p_slptime--; /* the first time was done in schedcpu */ 20947544Skarels while (newcpu && --p->p_slptime) 21047544Skarels newcpu = (int) decay_cpu(loadfac, newcpu); 21164590Sbostic p->p_estcpu = min(newcpu, UCHAR_MAX); 21247544Skarels } 21364413Sbostic resetpriority(p); 21417541Skarels } 21517541Skarels 216*64636Sbostic /* 217*64636Sbostic * We're only looking at 7 bits of the address; everything is 218*64636Sbostic * aligned to 4, lots of things are aligned to greater powers 219*64636Sbostic * of 2. Shift right by 8, i.e. drop the bottom 256 worth. 220*64636Sbostic */ 221*64636Sbostic #define TABLESIZE 128 222*64636Sbostic #define LOOKUP(x) (((int)(x) >> 8) & (TABLESIZE - 1)) 22321099Smckusick struct slpque { 22421099Smckusick struct proc *sq_head; 22521099Smckusick struct proc **sq_tailp; 22664590Sbostic } slpque[TABLESIZE]; 22733Sbill 22833Sbill /* 22945671Skarels * During autoconfiguration or after a panic, a sleep will simply 23045671Skarels * lower the priority briefly to allow interrupts, then return. 23145671Skarels * The priority to be used (safepri) is machine-dependent, thus this 23245671Skarels * value is initialized and maintained in the machine-dependent layers. 23345671Skarels * This priority will typically be 0, or the lowest priority 23445671Skarels * that is safe for use on the interrupt stack; it can be made 23545671Skarels * higher to block network software interrupts after panics. 23645671Skarels */ 23745671Skarels int safepri; 23845671Skarels 23945671Skarels /* 24064413Sbostic * General sleep call. Suspends the current process until a wakeup is 24164413Sbostic * performed on the specified identifier. The process will then be made 24264413Sbostic * runnable with the specified priority. Sleeps at most timo/hz seconds 24364413Sbostic * (0 means no timeout). If pri includes PCATCH flag, signals are checked 24464413Sbostic * before and after sleeping, else signals are not checked. Returns 0 if 24564413Sbostic * awakened, EWOULDBLOCK if the timeout expires. If PCATCH is set and a 24664413Sbostic * signal needs to be delivered, ERESTART is returned if the current system 24764413Sbostic * call should be restarted if possible, and EINTR is returned if the system 24864413Sbostic * call should be interrupted by the signal (return EINTR). 24933Sbill */ 25054788Storek int 25164413Sbostic tsleep(ident, priority, wmesg, timo) 25264413Sbostic void *ident; 25364413Sbostic int priority, timo; 25440710Smarc char *wmesg; 25540710Smarc { 25649095Skarels register struct proc *p = curproc; 25740710Smarc register struct slpque *qp; 25840710Smarc register s; 25964413Sbostic int sig, catch = priority & PCATCH; 26040710Smarc extern int cold; 26154788Storek void endtsleep __P((void *)); 26240710Smarc 26352498Smarc #ifdef KTRACE 26452498Smarc if (KTRPOINT(p, KTR_CSW)) 26552498Smarc ktrcsw(p->p_tracep, 1, 0); 26652498Smarc #endif 26740710Smarc s = splhigh(); 26840710Smarc if (cold || panicstr) { 26940710Smarc /* 27040710Smarc * After a panic, or during autoconfiguration, 27140710Smarc * just give interrupts a chance, then just return; 27240710Smarc * don't run any other procs or panic below, 27340710Smarc * in case this is the idle process and already asleep. 27440710Smarc */ 27545671Skarels splx(safepri); 27640710Smarc splx(s); 27740710Smarc return (0); 27840710Smarc } 27940710Smarc #ifdef DIAGNOSTIC 28064590Sbostic if (ident == NULL || p->p_stat != SRUN || p->p_back) 28140711Skarels panic("tsleep"); 28240710Smarc #endif 28364413Sbostic p->p_wchan = ident; 28447544Skarels p->p_wmesg = wmesg; 28547544Skarels p->p_slptime = 0; 28664590Sbostic p->p_priority = priority & PRIMASK; 28764590Sbostic qp = &slpque[LOOKUP(ident)]; 28840710Smarc if (qp->sq_head == 0) 28947544Skarels qp->sq_head = p; 29040710Smarc else 29147544Skarels *qp->sq_tailp = p; 29264590Sbostic *(qp->sq_tailp = &p->p_forw) = 0; 29345671Skarels if (timo) 29454788Storek timeout(endtsleep, (void *)p, timo); 29540710Smarc /* 29647544Skarels * We put ourselves on the sleep queue and start our timeout 29747544Skarels * before calling CURSIG, as we could stop there, and a wakeup 29847544Skarels * or a SIGCONT (or both) could occur while we were stopped. 29945671Skarels * A SIGCONT would cause us to be marked as SSLEEP 30045671Skarels * without resuming us, thus we must be ready for sleep 30145671Skarels * when CURSIG is called. If the wakeup happens while we're 30247544Skarels * stopped, p->p_wchan will be 0 upon return from CURSIG. 30340710Smarc */ 30440711Skarels if (catch) { 30564590Sbostic p->p_flag |= P_SINTR; 30647544Skarels if (sig = CURSIG(p)) { 30747544Skarels if (p->p_wchan) 30847544Skarels unsleep(p); 30947544Skarels p->p_stat = SRUN; 31045671Skarels goto resume; 31140711Skarels } 31247544Skarels if (p->p_wchan == 0) { 31345671Skarels catch = 0; 31445671Skarels goto resume; 31540711Skarels } 31652499Storek } else 31752499Storek sig = 0; 31847544Skarels p->p_stat = SSLEEP; 31947544Skarels p->p_stats->p_ru.ru_nvcsw++; 32064590Sbostic mi_switch(); 32145671Skarels resume: 32264413Sbostic curpriority = p->p_usrpri; 32340710Smarc splx(s); 32464590Sbostic p->p_flag &= ~P_SINTR; 32564590Sbostic if (p->p_flag & P_TIMEOUT) { 32664590Sbostic p->p_flag &= ~P_TIMEOUT; 32752499Storek if (sig == 0) { 32852498Smarc #ifdef KTRACE 32952498Smarc if (KTRPOINT(p, KTR_CSW)) 33052498Smarc ktrcsw(p->p_tracep, 0, 0); 33152498Smarc #endif 33245671Skarels return (EWOULDBLOCK); 33352498Smarc } 33445671Skarels } else if (timo) 33554788Storek untimeout(endtsleep, (void *)p); 33647544Skarels if (catch && (sig != 0 || (sig = CURSIG(p)))) { 33752498Smarc #ifdef KTRACE 33852498Smarc if (KTRPOINT(p, KTR_CSW)) 33952498Smarc ktrcsw(p->p_tracep, 0, 0); 34052498Smarc #endif 34147544Skarels if (p->p_sigacts->ps_sigintr & sigmask(sig)) 34240711Skarels return (EINTR); 34340711Skarels return (ERESTART); 34440711Skarels } 34552498Smarc #ifdef KTRACE 34652498Smarc if (KTRPOINT(p, KTR_CSW)) 34752498Smarc ktrcsw(p->p_tracep, 0, 0); 34852498Smarc #endif 34940710Smarc return (0); 35040710Smarc } 35140710Smarc 35240710Smarc /* 35340710Smarc * Implement timeout for tsleep. 35440710Smarc * If process hasn't been awakened (wchan non-zero), 35540710Smarc * set timeout flag and undo the sleep. If proc 35640710Smarc * is stopped, just unsleep so it will remain stopped. 35740710Smarc */ 35854788Storek void 35954788Storek endtsleep(arg) 36054788Storek void *arg; 36154788Storek { 36240710Smarc register struct proc *p; 36354788Storek int s; 36440710Smarc 36554788Storek p = (struct proc *)arg; 36654788Storek s = splhigh(); 36740710Smarc if (p->p_wchan) { 36840710Smarc if (p->p_stat == SSLEEP) 36964533Sbostic setrunnable(p); 37040710Smarc else 37140710Smarc unsleep(p); 37264590Sbostic p->p_flag |= P_TIMEOUT; 37340710Smarc } 37440710Smarc splx(s); 37540710Smarc } 37640710Smarc 37740711Skarels /* 37840711Skarels * Short-term, non-interruptable sleep. 37940711Skarels */ 38054788Storek void 38164413Sbostic sleep(ident, priority) 38264413Sbostic void *ident; 38364413Sbostic int priority; 38433Sbill { 38549095Skarels register struct proc *p = curproc; 38621099Smckusick register struct slpque *qp; 387207Sbill register s; 38830532Skarels extern int cold; 38933Sbill 39040711Skarels #ifdef DIAGNOSTIC 39164413Sbostic if (priority > PZERO) { 39264413Sbostic printf("sleep called with priority %d > PZERO, wchan: %x\n", 39364413Sbostic priority, ident); 39440711Skarels panic("old sleep"); 39540711Skarels } 39640711Skarels #endif 39717541Skarels s = splhigh(); 39830532Skarels if (cold || panicstr) { 39918363Skarels /* 40030532Skarels * After a panic, or during autoconfiguration, 40130532Skarels * just give interrupts a chance, then just return; 40230532Skarels * don't run any other procs or panic below, 40330532Skarels * in case this is the idle process and already asleep. 40418363Skarels */ 40545671Skarels splx(safepri); 40618363Skarels splx(s); 40718363Skarels return; 40818363Skarels } 40940710Smarc #ifdef DIAGNOSTIC 41064590Sbostic if (ident == NULL || p->p_stat != SRUN || p->p_back) 41133Sbill panic("sleep"); 41240710Smarc #endif 41364413Sbostic p->p_wchan = ident; 41447544Skarels p->p_wmesg = NULL; 41547544Skarels p->p_slptime = 0; 41664590Sbostic p->p_priority = priority; 41764590Sbostic qp = &slpque[LOOKUP(ident)]; 41821099Smckusick if (qp->sq_head == 0) 41947544Skarels qp->sq_head = p; 42021099Smckusick else 42147544Skarels *qp->sq_tailp = p; 42264590Sbostic *(qp->sq_tailp = &p->p_forw) = 0; 42347544Skarels p->p_stat = SSLEEP; 42447544Skarels p->p_stats->p_ru.ru_nvcsw++; 42552498Smarc #ifdef KTRACE 42652498Smarc if (KTRPOINT(p, KTR_CSW)) 42752498Smarc ktrcsw(p->p_tracep, 1, 0); 42852498Smarc #endif 42964590Sbostic mi_switch(); 43052498Smarc #ifdef KTRACE 43152498Smarc if (KTRPOINT(p, KTR_CSW)) 43252498Smarc ktrcsw(p->p_tracep, 0, 0); 43352498Smarc #endif 43464413Sbostic curpriority = p->p_usrpri; 43533Sbill splx(s); 43633Sbill } 43733Sbill 43833Sbill /* 439181Sbill * Remove a process from its wait queue 440181Sbill */ 44154788Storek void 442181Sbill unsleep(p) 4434826Swnj register struct proc *p; 444181Sbill { 44521099Smckusick register struct slpque *qp; 446181Sbill register struct proc **hp; 44721099Smckusick int s; 448181Sbill 44917541Skarels s = splhigh(); 450181Sbill if (p->p_wchan) { 45164590Sbostic hp = &(qp = &slpque[LOOKUP(p->p_wchan)])->sq_head; 452181Sbill while (*hp != p) 45364590Sbostic hp = &(*hp)->p_forw; 45464590Sbostic *hp = p->p_forw; 45564590Sbostic if (qp->sq_tailp == &p->p_forw) 45621099Smckusick qp->sq_tailp = hp; 457181Sbill p->p_wchan = 0; 458181Sbill } 459181Sbill splx(s); 460181Sbill } 461181Sbill 462181Sbill /* 46364413Sbostic * Make all processes sleeping on the specified identifier runnable. 46433Sbill */ 46554788Storek void 46664413Sbostic wakeup(ident) 46764413Sbostic register void *ident; 46833Sbill { 46921099Smckusick register struct slpque *qp; 47021099Smckusick register struct proc *p, **q; 47133Sbill int s; 47233Sbill 47317541Skarels s = splhigh(); 47464590Sbostic qp = &slpque[LOOKUP(ident)]; 47533Sbill restart: 47621099Smckusick for (q = &qp->sq_head; p = *q; ) { 47740710Smarc #ifdef DIAGNOSTIC 47864590Sbostic if (p->p_back || p->p_stat != SSLEEP && p->p_stat != SSTOP) 47933Sbill panic("wakeup"); 48040710Smarc #endif 48164413Sbostic if (p->p_wchan == ident) { 48233Sbill p->p_wchan = 0; 48364590Sbostic *q = p->p_forw; 48464590Sbostic if (qp->sq_tailp == &p->p_forw) 48521099Smckusick qp->sq_tailp = q; 486181Sbill if (p->p_stat == SSLEEP) { 48764533Sbostic /* OPTIMIZED EXPANSION OF setrunnable(p); */ 48821763Skarels if (p->p_slptime > 1) 48921763Skarels updatepri(p); 49047544Skarels p->p_slptime = 0; 491181Sbill p->p_stat = SRUN; 49264590Sbostic if (p->p_flag & P_INMEM) 49364533Sbostic setrunqueue(p); 49416795Skarels /* 49564413Sbostic * Since curpriority is a user priority, 49664590Sbostic * p->p_priority is always better than 49764590Sbostic * curpriority. 49816795Skarels */ 49964590Sbostic if ((p->p_flag & P_INMEM) == 0) 50047544Skarels wakeup((caddr_t)&proc0); 50147544Skarels else 50247544Skarels need_resched(); 503181Sbill /* END INLINE EXPANSION */ 504187Sbill goto restart; 50533Sbill } 506187Sbill } else 50764590Sbostic q = &p->p_forw; 50833Sbill } 50933Sbill splx(s); 51033Sbill } 51133Sbill 51233Sbill /* 51364590Sbostic * The machine independent parts of mi_switch(). 51454788Storek * Must be called at splstatclock() or higher. 51554788Storek */ 51654788Storek void 51764590Sbostic mi_switch() 51854788Storek { 51954788Storek register struct proc *p = curproc; /* XXX */ 52054788Storek register struct rlimit *rlim; 52154788Storek register long s, u; 52254788Storek struct timeval tv; 52354788Storek 52454788Storek /* 52554788Storek * Compute the amount of time during which the current 52654788Storek * process was running, and add that to its total so far. 52754788Storek */ 52854788Storek microtime(&tv); 52954788Storek u = p->p_rtime.tv_usec + (tv.tv_usec - runtime.tv_usec); 53054788Storek s = p->p_rtime.tv_sec + (tv.tv_sec - runtime.tv_sec); 53154788Storek if (u < 0) { 53254788Storek u += 1000000; 53354788Storek s--; 53454788Storek } else if (u >= 1000000) { 53554788Storek u -= 1000000; 53654788Storek s++; 53754788Storek } 53854788Storek p->p_rtime.tv_usec = u; 53954788Storek p->p_rtime.tv_sec = s; 54054788Storek 54154788Storek /* 54254788Storek * Check if the process exceeds its cpu resource allocation. 54354788Storek * If over max, kill it. In any case, if it has run for more 54454788Storek * than 10 minutes, reduce priority to give others a chance. 54554788Storek */ 54654788Storek rlim = &p->p_rlimit[RLIMIT_CPU]; 54754788Storek if (s >= rlim->rlim_cur) { 54854788Storek if (s >= rlim->rlim_max) 54954788Storek psignal(p, SIGKILL); 55054788Storek else { 55154788Storek psignal(p, SIGXCPU); 55254788Storek if (rlim->rlim_cur < rlim->rlim_max) 55354788Storek rlim->rlim_cur += 5; 55454788Storek } 55554788Storek } 55654788Storek if (s > 10 * 60 && p->p_ucred->cr_uid && p->p_nice == NZERO) { 55754788Storek p->p_nice = NZERO + 4; 55864413Sbostic resetpriority(p); 55954788Storek } 56054788Storek 56154788Storek /* 56254788Storek * Pick a new current process and record its start time. 56354788Storek */ 56454788Storek cnt.v_swtch++; 56564590Sbostic cpu_switch(p); 56654788Storek microtime(&runtime); 56754788Storek } 56854788Storek 56954788Storek /* 57033Sbill * Initialize the (doubly-linked) run queues 57133Sbill * to be empty. 57233Sbill */ 57333Sbill rqinit() 57433Sbill { 57533Sbill register int i; 57633Sbill 57733Sbill for (i = 0; i < NQS; i++) 57833Sbill qs[i].ph_link = qs[i].ph_rlink = (struct proc *)&qs[i]; 57933Sbill } 58033Sbill 58133Sbill /* 58247544Skarels * Change process state to be runnable, 58347544Skarels * placing it on the run queue if it is in memory, 58447544Skarels * and awakening the swapper if it isn't in memory. 58533Sbill */ 58654788Storek void 58764533Sbostic setrunnable(p) 5884826Swnj register struct proc *p; 58933Sbill { 5904826Swnj register int s; 59133Sbill 59217541Skarels s = splhigh(); 59333Sbill switch (p->p_stat) { 59433Sbill case 0: 59533Sbill case SRUN: 59633Sbill case SZOMB: 59733Sbill default: 59864533Sbostic panic("setrunnable"); 599207Sbill case SSTOP: 60033Sbill case SSLEEP: 601181Sbill unsleep(p); /* e.g. when sending signals */ 60233Sbill break; 60333Sbill 60433Sbill case SIDL: 60533Sbill break; 60633Sbill } 60733Sbill p->p_stat = SRUN; 60864590Sbostic if (p->p_flag & P_INMEM) 60964533Sbostic setrunqueue(p); 61033Sbill splx(s); 61130232Skarels if (p->p_slptime > 1) 61230232Skarels updatepri(p); 61347544Skarels p->p_slptime = 0; 61464590Sbostic if ((p->p_flag & P_INMEM) == 0) 61547544Skarels wakeup((caddr_t)&proc0); 61664590Sbostic else if (p->p_priority < curpriority) 61747544Skarels need_resched(); 61833Sbill } 61933Sbill 62033Sbill /* 62164413Sbostic * Compute the priority of a process when running in user mode. 62264413Sbostic * Arrange to reschedule if the resulting priority is better 62364413Sbostic * than that of the current process. 62433Sbill */ 62554788Storek void 62664413Sbostic resetpriority(p) 62747544Skarels register struct proc *p; 62833Sbill { 62964413Sbostic register unsigned int newpriority; 63033Sbill 63164590Sbostic newpriority = PUSER + p->p_estcpu / 4 + 2 * p->p_nice; 63264413Sbostic newpriority = min(newpriority, MAXPRI); 63364413Sbostic p->p_usrpri = newpriority; 63464413Sbostic if (newpriority < curpriority) 63547544Skarels need_resched(); 63633Sbill } 637