149594Sbostic /*- 263176Sbostic * Copyright (c) 1982, 1986, 1990, 1991, 1993 363176Sbostic * The Regents of the University of California. All rights reserved. 4*65771Sbostic * (c) UNIX System Laboratories, Inc. 5*65771Sbostic * All or some portions of this file are derived from material licensed 6*65771Sbostic * to the University of California by American Telephone and Telegraph 7*65771Sbostic * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8*65771Sbostic * the permission of UNIX System Laboratories, Inc. 923376Smckusick * 1049594Sbostic * %sccs.include.redist.c% 1149594Sbostic * 12*65771Sbostic * @(#)kern_synch.c 8.6 (Berkeley) 01/21/94 1323376Smckusick */ 1433Sbill 1556517Sbostic #include <sys/param.h> 1656517Sbostic #include <sys/systm.h> 1756517Sbostic #include <sys/proc.h> 1856517Sbostic #include <sys/kernel.h> 1956517Sbostic #include <sys/buf.h> 2056517Sbostic #include <sys/signalvar.h> 2156517Sbostic #include <sys/resourcevar.h> 2256517Sbostic #include <sys/vmmeter.h> 2352498Smarc #ifdef KTRACE 2456517Sbostic #include <sys/ktrace.h> 2552498Smarc #endif 269756Ssam 2756517Sbostic #include <machine/cpu.h> 2845742Smckusick 2964413Sbostic u_char curpriority; /* usrpri of curproc */ 3052686Ssklower int lbolt; /* once a second sleep address */ 3149226Skarels 328102Sroot /* 338102Sroot * Force switch among equal priority processes every 100ms. 348102Sroot */ 3554788Storek /* ARGSUSED */ 3654788Storek void 3754788Storek roundrobin(arg) 3854788Storek void *arg; 398102Sroot { 408102Sroot 4147544Skarels need_resched(); 4264413Sbostic timeout(roundrobin, NULL, hz / 10); 438102Sroot } 448102Sroot 4532908Smckusick /* 4664590Sbostic * Constants for digital decay and forget: 4764590Sbostic * 90% of (p_estcpu) usage in 5 * loadav time 4832908Smckusick * 95% of (p_pctcpu) usage in 60 seconds (load insensitive) 4932908Smckusick * Note that, as ps(1) mentions, this can let percentages 5032908Smckusick * total over 100% (I've seen 137.9% for 3 processes). 5132908Smckusick * 5264590Sbostic * Note that hardclock updates p_estcpu and p_cpticks independently. 5332908Smckusick * 5464590Sbostic * We wish to decay away 90% of p_estcpu in (5 * loadavg) seconds. 5532908Smckusick * That is, the system wants to compute a value of decay such 5632908Smckusick * that the following for loop: 5732908Smckusick * for (i = 0; i < (5 * loadavg); i++) 5864590Sbostic * p_estcpu *= decay; 5932908Smckusick * will compute 6064590Sbostic * p_estcpu *= 0.1; 6132908Smckusick * for all values of loadavg: 6232908Smckusick * 6332908Smckusick * Mathematically this loop can be expressed by saying: 6432908Smckusick * decay ** (5 * loadavg) ~= .1 6532908Smckusick * 6632908Smckusick * The system computes decay as: 6732908Smckusick * decay = (2 * loadavg) / (2 * loadavg + 1) 6832908Smckusick * 6932908Smckusick * We wish to prove that the system's computation of decay 7032908Smckusick * will always fulfill the equation: 7132908Smckusick * decay ** (5 * loadavg) ~= .1 7232908Smckusick * 7332908Smckusick * If we compute b as: 7432908Smckusick * b = 2 * loadavg 7532908Smckusick * then 7632908Smckusick * decay = b / (b + 1) 7732908Smckusick * 7832908Smckusick * We now need to prove two things: 7932908Smckusick * 1) Given factor ** (5 * loadavg) ~= .1, prove factor == b/(b+1) 8032908Smckusick * 2) Given b/(b+1) ** power ~= .1, prove power == (5 * loadavg) 8132908Smckusick * 8232908Smckusick * Facts: 8332908Smckusick * For x close to zero, exp(x) =~ 1 + x, since 8432908Smckusick * exp(x) = 0! + x**1/1! + x**2/2! + ... . 8532908Smckusick * therefore exp(-1/b) =~ 1 - (1/b) = (b-1)/b. 8632908Smckusick * For x close to zero, ln(1+x) =~ x, since 8732908Smckusick * ln(1+x) = x - x**2/2 + x**3/3 - ... -1 < x < 1 8832908Smckusick * therefore ln(b/(b+1)) = ln(1 - 1/(b+1)) =~ -1/(b+1). 8932908Smckusick * ln(.1) =~ -2.30 9032908Smckusick * 9132908Smckusick * Proof of (1): 9232908Smckusick * Solve (factor)**(power) =~ .1 given power (5*loadav): 9332908Smckusick * solving for factor, 9432908Smckusick * ln(factor) =~ (-2.30/5*loadav), or 9547544Skarels * factor =~ exp(-1/((5/2.30)*loadav)) =~ exp(-1/(2*loadav)) = 9632908Smckusick * exp(-1/b) =~ (b-1)/b =~ b/(b+1). QED 9732908Smckusick * 9832908Smckusick * Proof of (2): 9932908Smckusick * Solve (factor)**(power) =~ .1 given factor == (b/(b+1)): 10032908Smckusick * solving for power, 10132908Smckusick * power*ln(b/(b+1)) =~ -2.30, or 10232908Smckusick * power =~ 2.3 * (b + 1) = 4.6*loadav + 2.3 =~ 5*loadav. QED 10332908Smckusick * 10432908Smckusick * Actual power values for the implemented algorithm are as follows: 10532908Smckusick * loadav: 1 2 3 4 10632908Smckusick * power: 5.68 10.32 14.94 19.55 10732908Smckusick */ 10817541Skarels 10938164Smckusick /* calculations for digital decay to forget 90% of usage in 5*loadav sec */ 11047544Skarels #define loadfactor(loadav) (2 * (loadav)) 11147544Skarels #define decay_cpu(loadfac, cpu) (((loadfac) * (cpu)) / ((loadfac) + FSCALE)) 1128102Sroot 11338164Smckusick /* decay 95% of `p_pctcpu' in 60 seconds; see CCPU_SHIFT before changing */ 11438164Smckusick fixpt_t ccpu = 0.95122942450071400909 * FSCALE; /* exp(-1/20) */ 11538164Smckusick 1168102Sroot /* 11738164Smckusick * If `ccpu' is not equal to `exp(-1/20)' and you still want to use the 11838164Smckusick * faster/more-accurate formula, you'll have to estimate CCPU_SHIFT below 11938164Smckusick * and possibly adjust FSHIFT in "param.h" so that (FSHIFT >= CCPU_SHIFT). 12038164Smckusick * 12138164Smckusick * To estimate CCPU_SHIFT for exp(-1/20), the following formula was used: 12238164Smckusick * 1 - exp(-1/20) ~= 0.0487 ~= 0.0488 == 1 (fixed pt, *11* bits). 12338164Smckusick * 12438164Smckusick * If you dont want to bother with the faster/more-accurate formula, you 12538164Smckusick * can set CCPU_SHIFT to (FSHIFT + 1) which will use a slower/less-accurate 12638164Smckusick * (more general) method of calculating the %age of CPU used by a process. 12738164Smckusick */ 12838164Smckusick #define CCPU_SHIFT 11 12938164Smckusick 13038164Smckusick /* 13164413Sbostic * Recompute process priorities, every hz ticks. 1328102Sroot */ 13354788Storek /* ARGSUSED */ 13454788Storek void 13554788Storek schedcpu(arg) 13654788Storek void *arg; 1378102Sroot { 13852667Smckusick register fixpt_t loadfac = loadfactor(averunnable.ldavg[0]); 1398102Sroot register struct proc *p; 14047544Skarels register int s; 14147544Skarels register unsigned int newcpu; 1428102Sroot 1438102Sroot wakeup((caddr_t)&lbolt); 14464590Sbostic for (p = (struct proc *)allproc; p != NULL; p = p->p_next) { 14547544Skarels /* 14647544Skarels * Increment time in/out of memory and sleep time 14747544Skarels * (if sleeping). We ignore overflow; with 16-bit int's 14847544Skarels * (remember them?) overflow takes 45 days. 14947544Skarels */ 15064590Sbostic p->p_swtime++; 15147544Skarels if (p->p_stat == SSLEEP || p->p_stat == SSTOP) 15247544Skarels p->p_slptime++; 15338164Smckusick p->p_pctcpu = (p->p_pctcpu * ccpu) >> FSHIFT; 15417541Skarels /* 15517541Skarels * If the process has slept the entire second, 15617541Skarels * stop recalculating its priority until it wakes up. 15717541Skarels */ 15838164Smckusick if (p->p_slptime > 1) 15917541Skarels continue; 16056895Storek s = splstatclock(); /* prevent state changes */ 16117541Skarels /* 16217541Skarels * p_pctcpu is only for ps. 16317541Skarels */ 16438164Smckusick #if (FSHIFT >= CCPU_SHIFT) 16538164Smckusick p->p_pctcpu += (hz == 100)? 16638164Smckusick ((fixpt_t) p->p_cpticks) << (FSHIFT - CCPU_SHIFT): 16738164Smckusick 100 * (((fixpt_t) p->p_cpticks) 16838164Smckusick << (FSHIFT - CCPU_SHIFT)) / hz; 16938164Smckusick #else 17038164Smckusick p->p_pctcpu += ((FSCALE - ccpu) * 17138164Smckusick (p->p_cpticks * FSCALE / hz)) >> FSHIFT; 17238164Smckusick #endif 1738102Sroot p->p_cpticks = 0; 17464590Sbostic newcpu = (u_int) decay_cpu(loadfac, p->p_estcpu) + p->p_nice; 17564590Sbostic p->p_estcpu = min(newcpu, UCHAR_MAX); 17664413Sbostic resetpriority(p); 17764590Sbostic if (p->p_priority >= PUSER) { 17847544Skarels #define PPQ (128 / NQS) /* priorities per queue */ 17949095Skarels if ((p != curproc) && 1808102Sroot p->p_stat == SRUN && 18164590Sbostic (p->p_flag & P_INMEM) && 18264590Sbostic (p->p_priority / PPQ) != (p->p_usrpri / PPQ)) { 1838102Sroot remrq(p); 18464590Sbostic p->p_priority = p->p_usrpri; 18564533Sbostic setrunqueue(p); 1868102Sroot } else 18764590Sbostic p->p_priority = p->p_usrpri; 1888102Sroot } 1898102Sroot splx(s); 1908102Sroot } 1918102Sroot vmmeter(); 1928102Sroot if (bclnlist != NULL) 19347544Skarels wakeup((caddr_t)pageproc); 19454788Storek timeout(schedcpu, (void *)0, hz); 1958102Sroot } 1968102Sroot 19717541Skarels /* 19817541Skarels * Recalculate the priority of a process after it has slept for a while. 19964590Sbostic * For all load averages >= 1 and max p_estcpu of 255, sleeping for at 20064590Sbostic * least six times the loadfactor will decay p_estcpu to zero. 20117541Skarels */ 20254788Storek void 20317541Skarels updatepri(p) 20417541Skarels register struct proc *p; 20517541Skarels { 20664590Sbostic register unsigned int newcpu = p->p_estcpu; 20752667Smckusick register fixpt_t loadfac = loadfactor(averunnable.ldavg[0]); 20817541Skarels 20947544Skarels if (p->p_slptime > 5 * loadfac) 21064590Sbostic p->p_estcpu = 0; 21147544Skarels else { 21247544Skarels p->p_slptime--; /* the first time was done in schedcpu */ 21347544Skarels while (newcpu && --p->p_slptime) 21447544Skarels newcpu = (int) decay_cpu(loadfac, newcpu); 21564590Sbostic p->p_estcpu = min(newcpu, UCHAR_MAX); 21647544Skarels } 21764413Sbostic resetpriority(p); 21817541Skarels } 21917541Skarels 22064636Sbostic /* 22164636Sbostic * We're only looking at 7 bits of the address; everything is 22264636Sbostic * aligned to 4, lots of things are aligned to greater powers 22364636Sbostic * of 2. Shift right by 8, i.e. drop the bottom 256 worth. 22464636Sbostic */ 22564636Sbostic #define TABLESIZE 128 22664636Sbostic #define LOOKUP(x) (((int)(x) >> 8) & (TABLESIZE - 1)) 22721099Smckusick struct slpque { 22821099Smckusick struct proc *sq_head; 22921099Smckusick struct proc **sq_tailp; 23064590Sbostic } slpque[TABLESIZE]; 23133Sbill 23233Sbill /* 23345671Skarels * During autoconfiguration or after a panic, a sleep will simply 23445671Skarels * lower the priority briefly to allow interrupts, then return. 23545671Skarels * The priority to be used (safepri) is machine-dependent, thus this 23645671Skarels * value is initialized and maintained in the machine-dependent layers. 23745671Skarels * This priority will typically be 0, or the lowest priority 23845671Skarels * that is safe for use on the interrupt stack; it can be made 23945671Skarels * higher to block network software interrupts after panics. 24045671Skarels */ 24145671Skarels int safepri; 24245671Skarels 24345671Skarels /* 24464413Sbostic * General sleep call. Suspends the current process until a wakeup is 24564413Sbostic * performed on the specified identifier. The process will then be made 24664413Sbostic * runnable with the specified priority. Sleeps at most timo/hz seconds 24764413Sbostic * (0 means no timeout). If pri includes PCATCH flag, signals are checked 24864413Sbostic * before and after sleeping, else signals are not checked. Returns 0 if 24964413Sbostic * awakened, EWOULDBLOCK if the timeout expires. If PCATCH is set and a 25064413Sbostic * signal needs to be delivered, ERESTART is returned if the current system 25164413Sbostic * call should be restarted if possible, and EINTR is returned if the system 25264413Sbostic * call should be interrupted by the signal (return EINTR). 25333Sbill */ 25454788Storek int 25564413Sbostic tsleep(ident, priority, wmesg, timo) 25664413Sbostic void *ident; 25764413Sbostic int priority, timo; 25840710Smarc char *wmesg; 25940710Smarc { 26049095Skarels register struct proc *p = curproc; 26140710Smarc register struct slpque *qp; 26240710Smarc register s; 26364413Sbostic int sig, catch = priority & PCATCH; 26440710Smarc extern int cold; 26554788Storek void endtsleep __P((void *)); 26640710Smarc 26752498Smarc #ifdef KTRACE 26852498Smarc if (KTRPOINT(p, KTR_CSW)) 26952498Smarc ktrcsw(p->p_tracep, 1, 0); 27052498Smarc #endif 27140710Smarc s = splhigh(); 27240710Smarc if (cold || panicstr) { 27340710Smarc /* 27440710Smarc * After a panic, or during autoconfiguration, 27540710Smarc * just give interrupts a chance, then just return; 27640710Smarc * don't run any other procs or panic below, 27740710Smarc * in case this is the idle process and already asleep. 27840710Smarc */ 27945671Skarels splx(safepri); 28040710Smarc splx(s); 28140710Smarc return (0); 28240710Smarc } 28340710Smarc #ifdef DIAGNOSTIC 28464590Sbostic if (ident == NULL || p->p_stat != SRUN || p->p_back) 28540711Skarels panic("tsleep"); 28640710Smarc #endif 28764413Sbostic p->p_wchan = ident; 28847544Skarels p->p_wmesg = wmesg; 28947544Skarels p->p_slptime = 0; 29064590Sbostic p->p_priority = priority & PRIMASK; 29164590Sbostic qp = &slpque[LOOKUP(ident)]; 29240710Smarc if (qp->sq_head == 0) 29347544Skarels qp->sq_head = p; 29440710Smarc else 29547544Skarels *qp->sq_tailp = p; 29664590Sbostic *(qp->sq_tailp = &p->p_forw) = 0; 29745671Skarels if (timo) 29854788Storek timeout(endtsleep, (void *)p, timo); 29940710Smarc /* 30047544Skarels * We put ourselves on the sleep queue and start our timeout 30147544Skarels * before calling CURSIG, as we could stop there, and a wakeup 30247544Skarels * or a SIGCONT (or both) could occur while we were stopped. 30345671Skarels * A SIGCONT would cause us to be marked as SSLEEP 30445671Skarels * without resuming us, thus we must be ready for sleep 30545671Skarels * when CURSIG is called. If the wakeup happens while we're 30647544Skarels * stopped, p->p_wchan will be 0 upon return from CURSIG. 30740710Smarc */ 30840711Skarels if (catch) { 30964590Sbostic p->p_flag |= P_SINTR; 31047544Skarels if (sig = CURSIG(p)) { 31147544Skarels if (p->p_wchan) 31247544Skarels unsleep(p); 31347544Skarels p->p_stat = SRUN; 31445671Skarels goto resume; 31540711Skarels } 31647544Skarels if (p->p_wchan == 0) { 31745671Skarels catch = 0; 31845671Skarels goto resume; 31940711Skarels } 32052499Storek } else 32152499Storek sig = 0; 32247544Skarels p->p_stat = SSLEEP; 32347544Skarels p->p_stats->p_ru.ru_nvcsw++; 32464590Sbostic mi_switch(); 32545671Skarels resume: 32664413Sbostic curpriority = p->p_usrpri; 32740710Smarc splx(s); 32864590Sbostic p->p_flag &= ~P_SINTR; 32964590Sbostic if (p->p_flag & P_TIMEOUT) { 33064590Sbostic p->p_flag &= ~P_TIMEOUT; 33152499Storek if (sig == 0) { 33252498Smarc #ifdef KTRACE 33352498Smarc if (KTRPOINT(p, KTR_CSW)) 33452498Smarc ktrcsw(p->p_tracep, 0, 0); 33552498Smarc #endif 33645671Skarels return (EWOULDBLOCK); 33752498Smarc } 33845671Skarels } else if (timo) 33954788Storek untimeout(endtsleep, (void *)p); 34047544Skarels if (catch && (sig != 0 || (sig = CURSIG(p)))) { 34152498Smarc #ifdef KTRACE 34252498Smarc if (KTRPOINT(p, KTR_CSW)) 34352498Smarc ktrcsw(p->p_tracep, 0, 0); 34452498Smarc #endif 34547544Skarels if (p->p_sigacts->ps_sigintr & sigmask(sig)) 34640711Skarels return (EINTR); 34740711Skarels return (ERESTART); 34840711Skarels } 34952498Smarc #ifdef KTRACE 35052498Smarc if (KTRPOINT(p, KTR_CSW)) 35152498Smarc ktrcsw(p->p_tracep, 0, 0); 35252498Smarc #endif 35340710Smarc return (0); 35440710Smarc } 35540710Smarc 35640710Smarc /* 35740710Smarc * Implement timeout for tsleep. 35840710Smarc * If process hasn't been awakened (wchan non-zero), 35940710Smarc * set timeout flag and undo the sleep. If proc 36040710Smarc * is stopped, just unsleep so it will remain stopped. 36140710Smarc */ 36254788Storek void 36354788Storek endtsleep(arg) 36454788Storek void *arg; 36554788Storek { 36640710Smarc register struct proc *p; 36754788Storek int s; 36840710Smarc 36954788Storek p = (struct proc *)arg; 37054788Storek s = splhigh(); 37140710Smarc if (p->p_wchan) { 37240710Smarc if (p->p_stat == SSLEEP) 37364533Sbostic setrunnable(p); 37440710Smarc else 37540710Smarc unsleep(p); 37664590Sbostic p->p_flag |= P_TIMEOUT; 37740710Smarc } 37840710Smarc splx(s); 37940710Smarc } 38040710Smarc 38140711Skarels /* 38240711Skarels * Short-term, non-interruptable sleep. 38340711Skarels */ 38454788Storek void 38564413Sbostic sleep(ident, priority) 38664413Sbostic void *ident; 38764413Sbostic int priority; 38833Sbill { 38949095Skarels register struct proc *p = curproc; 39021099Smckusick register struct slpque *qp; 391207Sbill register s; 39230532Skarels extern int cold; 39333Sbill 39440711Skarels #ifdef DIAGNOSTIC 39564413Sbostic if (priority > PZERO) { 39664413Sbostic printf("sleep called with priority %d > PZERO, wchan: %x\n", 39764413Sbostic priority, ident); 39840711Skarels panic("old sleep"); 39940711Skarels } 40040711Skarels #endif 40117541Skarels s = splhigh(); 40230532Skarels if (cold || panicstr) { 40318363Skarels /* 40430532Skarels * After a panic, or during autoconfiguration, 40530532Skarels * just give interrupts a chance, then just return; 40630532Skarels * don't run any other procs or panic below, 40730532Skarels * in case this is the idle process and already asleep. 40818363Skarels */ 40945671Skarels splx(safepri); 41018363Skarels splx(s); 41118363Skarels return; 41218363Skarels } 41340710Smarc #ifdef DIAGNOSTIC 41464590Sbostic if (ident == NULL || p->p_stat != SRUN || p->p_back) 41533Sbill panic("sleep"); 41640710Smarc #endif 41764413Sbostic p->p_wchan = ident; 41847544Skarels p->p_wmesg = NULL; 41947544Skarels p->p_slptime = 0; 42064590Sbostic p->p_priority = priority; 42164590Sbostic qp = &slpque[LOOKUP(ident)]; 42221099Smckusick if (qp->sq_head == 0) 42347544Skarels qp->sq_head = p; 42421099Smckusick else 42547544Skarels *qp->sq_tailp = p; 42664590Sbostic *(qp->sq_tailp = &p->p_forw) = 0; 42747544Skarels p->p_stat = SSLEEP; 42847544Skarels p->p_stats->p_ru.ru_nvcsw++; 42952498Smarc #ifdef KTRACE 43052498Smarc if (KTRPOINT(p, KTR_CSW)) 43152498Smarc ktrcsw(p->p_tracep, 1, 0); 43252498Smarc #endif 43364590Sbostic mi_switch(); 43452498Smarc #ifdef KTRACE 43552498Smarc if (KTRPOINT(p, KTR_CSW)) 43652498Smarc ktrcsw(p->p_tracep, 0, 0); 43752498Smarc #endif 43864413Sbostic curpriority = p->p_usrpri; 43933Sbill splx(s); 44033Sbill } 44133Sbill 44233Sbill /* 443181Sbill * Remove a process from its wait queue 444181Sbill */ 44554788Storek void 446181Sbill unsleep(p) 4474826Swnj register struct proc *p; 448181Sbill { 44921099Smckusick register struct slpque *qp; 450181Sbill register struct proc **hp; 45121099Smckusick int s; 452181Sbill 45317541Skarels s = splhigh(); 454181Sbill if (p->p_wchan) { 45564590Sbostic hp = &(qp = &slpque[LOOKUP(p->p_wchan)])->sq_head; 456181Sbill while (*hp != p) 45764590Sbostic hp = &(*hp)->p_forw; 45864590Sbostic *hp = p->p_forw; 45964590Sbostic if (qp->sq_tailp == &p->p_forw) 46021099Smckusick qp->sq_tailp = hp; 461181Sbill p->p_wchan = 0; 462181Sbill } 463181Sbill splx(s); 464181Sbill } 465181Sbill 466181Sbill /* 46764413Sbostic * Make all processes sleeping on the specified identifier runnable. 46833Sbill */ 46954788Storek void 47064413Sbostic wakeup(ident) 47164413Sbostic register void *ident; 47233Sbill { 47321099Smckusick register struct slpque *qp; 47421099Smckusick register struct proc *p, **q; 47533Sbill int s; 47633Sbill 47717541Skarels s = splhigh(); 47864590Sbostic qp = &slpque[LOOKUP(ident)]; 47933Sbill restart: 48021099Smckusick for (q = &qp->sq_head; p = *q; ) { 48140710Smarc #ifdef DIAGNOSTIC 48264590Sbostic if (p->p_back || p->p_stat != SSLEEP && p->p_stat != SSTOP) 48333Sbill panic("wakeup"); 48440710Smarc #endif 48564413Sbostic if (p->p_wchan == ident) { 48633Sbill p->p_wchan = 0; 48764590Sbostic *q = p->p_forw; 48864590Sbostic if (qp->sq_tailp == &p->p_forw) 48921099Smckusick qp->sq_tailp = q; 490181Sbill if (p->p_stat == SSLEEP) { 49164533Sbostic /* OPTIMIZED EXPANSION OF setrunnable(p); */ 49221763Skarels if (p->p_slptime > 1) 49321763Skarels updatepri(p); 49447544Skarels p->p_slptime = 0; 495181Sbill p->p_stat = SRUN; 49664590Sbostic if (p->p_flag & P_INMEM) 49764533Sbostic setrunqueue(p); 49816795Skarels /* 49964413Sbostic * Since curpriority is a user priority, 50064590Sbostic * p->p_priority is always better than 50164590Sbostic * curpriority. 50216795Skarels */ 50364590Sbostic if ((p->p_flag & P_INMEM) == 0) 50447544Skarels wakeup((caddr_t)&proc0); 50547544Skarels else 50647544Skarels need_resched(); 507181Sbill /* END INLINE EXPANSION */ 508187Sbill goto restart; 50933Sbill } 510187Sbill } else 51164590Sbostic q = &p->p_forw; 51233Sbill } 51333Sbill splx(s); 51433Sbill } 51533Sbill 51633Sbill /* 51764590Sbostic * The machine independent parts of mi_switch(). 51854788Storek * Must be called at splstatclock() or higher. 51954788Storek */ 52054788Storek void 52164590Sbostic mi_switch() 52254788Storek { 52354788Storek register struct proc *p = curproc; /* XXX */ 52454788Storek register struct rlimit *rlim; 52554788Storek register long s, u; 52654788Storek struct timeval tv; 52754788Storek 52854788Storek /* 52954788Storek * Compute the amount of time during which the current 53054788Storek * process was running, and add that to its total so far. 53154788Storek */ 53254788Storek microtime(&tv); 53354788Storek u = p->p_rtime.tv_usec + (tv.tv_usec - runtime.tv_usec); 53454788Storek s = p->p_rtime.tv_sec + (tv.tv_sec - runtime.tv_sec); 53554788Storek if (u < 0) { 53654788Storek u += 1000000; 53754788Storek s--; 53854788Storek } else if (u >= 1000000) { 53954788Storek u -= 1000000; 54054788Storek s++; 54154788Storek } 54254788Storek p->p_rtime.tv_usec = u; 54354788Storek p->p_rtime.tv_sec = s; 54454788Storek 54554788Storek /* 54654788Storek * Check if the process exceeds its cpu resource allocation. 54754788Storek * If over max, kill it. In any case, if it has run for more 54854788Storek * than 10 minutes, reduce priority to give others a chance. 54954788Storek */ 55054788Storek rlim = &p->p_rlimit[RLIMIT_CPU]; 55154788Storek if (s >= rlim->rlim_cur) { 55254788Storek if (s >= rlim->rlim_max) 55354788Storek psignal(p, SIGKILL); 55454788Storek else { 55554788Storek psignal(p, SIGXCPU); 55654788Storek if (rlim->rlim_cur < rlim->rlim_max) 55754788Storek rlim->rlim_cur += 5; 55854788Storek } 55954788Storek } 56054788Storek if (s > 10 * 60 && p->p_ucred->cr_uid && p->p_nice == NZERO) { 56154788Storek p->p_nice = NZERO + 4; 56264413Sbostic resetpriority(p); 56354788Storek } 56454788Storek 56554788Storek /* 56654788Storek * Pick a new current process and record its start time. 56754788Storek */ 56854788Storek cnt.v_swtch++; 56964590Sbostic cpu_switch(p); 57054788Storek microtime(&runtime); 57154788Storek } 57254788Storek 57354788Storek /* 57433Sbill * Initialize the (doubly-linked) run queues 57533Sbill * to be empty. 57633Sbill */ 57733Sbill rqinit() 57833Sbill { 57933Sbill register int i; 58033Sbill 58133Sbill for (i = 0; i < NQS; i++) 58233Sbill qs[i].ph_link = qs[i].ph_rlink = (struct proc *)&qs[i]; 58333Sbill } 58433Sbill 58533Sbill /* 58647544Skarels * Change process state to be runnable, 58747544Skarels * placing it on the run queue if it is in memory, 58847544Skarels * and awakening the swapper if it isn't in memory. 58933Sbill */ 59054788Storek void 59164533Sbostic setrunnable(p) 5924826Swnj register struct proc *p; 59333Sbill { 5944826Swnj register int s; 59533Sbill 59617541Skarels s = splhigh(); 59733Sbill switch (p->p_stat) { 59833Sbill case 0: 59933Sbill case SRUN: 60033Sbill case SZOMB: 60133Sbill default: 60264533Sbostic panic("setrunnable"); 603207Sbill case SSTOP: 60433Sbill case SSLEEP: 605181Sbill unsleep(p); /* e.g. when sending signals */ 60633Sbill break; 60733Sbill 60833Sbill case SIDL: 60933Sbill break; 61033Sbill } 61133Sbill p->p_stat = SRUN; 61264590Sbostic if (p->p_flag & P_INMEM) 61364533Sbostic setrunqueue(p); 61433Sbill splx(s); 61530232Skarels if (p->p_slptime > 1) 61630232Skarels updatepri(p); 61747544Skarels p->p_slptime = 0; 61864590Sbostic if ((p->p_flag & P_INMEM) == 0) 61947544Skarels wakeup((caddr_t)&proc0); 62064590Sbostic else if (p->p_priority < curpriority) 62147544Skarels need_resched(); 62233Sbill } 62333Sbill 62433Sbill /* 62564413Sbostic * Compute the priority of a process when running in user mode. 62664413Sbostic * Arrange to reschedule if the resulting priority is better 62764413Sbostic * than that of the current process. 62833Sbill */ 62954788Storek void 63064413Sbostic resetpriority(p) 63147544Skarels register struct proc *p; 63233Sbill { 63364413Sbostic register unsigned int newpriority; 63433Sbill 63564590Sbostic newpriority = PUSER + p->p_estcpu / 4 + 2 * p->p_nice; 63664413Sbostic newpriority = min(newpriority, MAXPRI); 63764413Sbostic p->p_usrpri = newpriority; 63864413Sbostic if (newpriority < curpriority) 63947544Skarels need_resched(); 64033Sbill } 641