1*4968Swnj /* kern_clock.c 4.27 81/11/20 */ 29Sbill 39Sbill #include "../h/param.h" 49Sbill #include "../h/systm.h" 5329Sbill #include "../h/dk.h" 62768Swnj #include "../h/callout.h" 79Sbill #include "../h/seg.h" 89Sbill #include "../h/dir.h" 99Sbill #include "../h/user.h" 109Sbill #include "../h/proc.h" 119Sbill #include "../h/reg.h" 129Sbill #include "../h/psl.h" 139Sbill #include "../h/vm.h" 149Sbill #include "../h/buf.h" 159Sbill #include "../h/text.h" 16877Sbill #include "../h/vlimit.h" 17877Sbill #include "../h/mtpr.h" 18877Sbill #include "../h/clock.h" 192689Swnj #include "../h/cpu.h" 209Sbill 213511Sroot #include "bk.h" 221943Swnj #include "dh.h" 231943Swnj #include "dz.h" 241559Sbill 259Sbill /* 262442Swnj * Hardclock is called straight from 279Sbill * the real time clock interrupt. 282442Swnj * We limit the work we do at real clock interrupt time to: 292442Swnj * reloading clock 302442Swnj * decrementing time to callouts 312442Swnj * recording cpu time usage 322450Swnj * modifying priority of current process 332442Swnj * arrange for soft clock interrupt 342442Swnj * kernel pc profiling 359Sbill * 363110Swnj * At software (softclock) interrupt time we: 379Sbill * implement callouts 389Sbill * maintain date 399Sbill * lightning bolt wakeup (every second) 409Sbill * alarm clock signals 419Sbill * jab the scheduler 422442Swnj * 432442Swnj * On the vax softclock interrupts are implemented by 442442Swnj * software interrupts. Note that we may have multiple softclock 452442Swnj * interrupts compressed into one (due to excessive interrupt load), 462442Swnj * but that hardclock interrupts should never be lost. 479Sbill */ 48*4968Swnj #ifdef KPROF 494527Swnj int kcounts[20000]; 50*4968Swnj #endif 519Sbill 522609Swnj /*ARGSUSED*/ 532442Swnj hardclock(pc, ps) 542450Swnj caddr_t pc; 559Sbill { 562768Swnj register struct callout *p1; 579Sbill register struct proc *pp; 582442Swnj register int s, cpstate; 599Sbill 609Sbill /* 619Sbill * reprime clock 629Sbill */ 639Sbill clkreld(); 649Sbill 659Sbill /* 662442Swnj * update callout times 679Sbill */ 683542Swnj for (p1 = calltodo.c_next; p1 && p1->c_time <= 0; p1 = p1->c_next) 693542Swnj ; 703542Swnj if (p1) 713542Swnj p1->c_time--; 72138Sbill 73138Sbill /* 742442Swnj * Maintain iostat and per-process cpu statistics 75138Sbill */ 769Sbill if (!noproc) { 779Sbill s = u.u_procp->p_rssize; 789Sbill u.u_vm.vm_idsrss += s; 799Sbill if (u.u_procp->p_textp) { 809Sbill register int xrss = u.u_procp->p_textp->x_rssize; 819Sbill 829Sbill s += xrss; 839Sbill u.u_vm.vm_ixrss += xrss; 849Sbill } 859Sbill if (s > u.u_vm.vm_maxrss) 869Sbill u.u_vm.vm_maxrss = s; 872768Swnj if ((u.u_vm.vm_utime+u.u_vm.vm_stime+1)/hz > u.u_limit[LIM_CPU]) { 88375Sbill psignal(u.u_procp, SIGXCPU); 89375Sbill if (u.u_limit[LIM_CPU] < INFINITY - 5) 90375Sbill u.u_limit[LIM_CPU] += 5; 91375Sbill } 929Sbill } 933110Swnj /* 943110Swnj * Update iostat information. 953110Swnj */ 969Sbill if (USERMODE(ps)) { 979Sbill u.u_vm.vm_utime++; 989Sbill if(u.u_procp->p_nice > NZERO) 99305Sbill cpstate = CP_NICE; 100305Sbill else 101305Sbill cpstate = CP_USER; 1029Sbill } else { 103*4968Swnj #ifdef KPROF 104*4968Swnj int k = ((int)pc & 0x7fffffff) / 8; 105*4968Swnj if (k < 20000) 106*4968Swnj kcounts[k]++; 107*4968Swnj #endif 108305Sbill cpstate = CP_SYS; 1099Sbill if (noproc) 110305Sbill cpstate = CP_IDLE; 1119Sbill else 1129Sbill u.u_vm.vm_stime++; 1139Sbill } 1141408Sbill cp_time[cpstate]++; 1152442Swnj for (s = 0; s < DK_NDRIVE; s++) 1162442Swnj if (dk_busy&(1<<s)) 1172442Swnj dk_time[s]++; 1183110Swnj /* 1193110Swnj * Adjust priority of current process. 1203110Swnj */ 1219Sbill if (!noproc) { 1229Sbill pp = u.u_procp; 1231399Sbill pp->p_cpticks++; 1249Sbill if(++pp->p_cpu == 0) 1259Sbill pp->p_cpu--; 1263876Swnj if(pp->p_cpu % 4 == 0) { 127125Sbill (void) setpri(pp); 1289Sbill if (pp->p_pri >= PUSER) 1299Sbill pp->p_pri = pp->p_usrpri; 1309Sbill } 1319Sbill } 1323110Swnj /* 1333110Swnj * Time moves on. 1343110Swnj */ 1359Sbill ++lbolt; 1362689Swnj #if VAX780 1373110Swnj /* 1383110Swnj * On 780's, impelement a fast UBA watcher, 1393110Swnj * to make sure uba's don't get stuck. 1403110Swnj */ 1412872Swnj if (cpu == VAX_780 && panicstr == 0 && !BASEPRI(ps)) 1422442Swnj unhang(); 1432442Swnj #endif 1443110Swnj /* 1453110Swnj * Schedule a software interrupt for the rest 1463110Swnj * of clock activities. 1473110Swnj */ 1482442Swnj setsoftclock(); 1492442Swnj } 1502442Swnj 1512442Swnj /* 1523876Swnj * The digital decay cpu usage priority assignment is scaled to run in 1533876Swnj * time as expanded by the 1 minute load average. Each second we 1543876Swnj * multiply the the previous cpu usage estimate by 1553876Swnj * nrscale*avenrun[0] 1563876Swnj * The following relates the load average to the period over which 1573876Swnj * cpu usage is 90% forgotten: 1583876Swnj * loadav 1 5 seconds 1593876Swnj * loadav 5 24 seconds 1603876Swnj * loadav 10 47 seconds 1613876Swnj * loadav 20 93 seconds 1623876Swnj * This is a great improvement on the previous algorithm which 1633876Swnj * decayed the priorities by a constant, and decayed away all knowledge 1643876Swnj * of previous activity in about 20 seconds. Under heavy load, 1653876Swnj * the previous algorithm degenerated to round-robin with poor response 1663876Swnj * time when there was a high load average. 1672442Swnj */ 1683984Sroot #undef ave 1693876Swnj #define ave(a,b) ((int)(((int)(a*b))/(b+1))) 1703876Swnj int nrscale = 2; 1713876Swnj double avenrun[]; 1723110Swnj 1733110Swnj /* 1743110Swnj * Constant for decay filter for cpu usage field 1753110Swnj * in process table (used by ps au). 1763110Swnj */ 1772442Swnj double ccpu = 0.95122942450071400909; /* exp(-1/20) */ 1782442Swnj 1792442Swnj /* 1802442Swnj * Software clock interrupt. 1813110Swnj * This routine runs at lower priority than device interrupts. 1822442Swnj */ 1832609Swnj /*ARGSUSED*/ 1842442Swnj softclock(pc, ps) 1852450Swnj caddr_t pc; 1862442Swnj { 1873615Sroot register struct callout *p1; 1882442Swnj register struct proc *pp; 1892442Swnj register int a, s; 1903542Swnj caddr_t arg; 1913542Swnj int (*func)(); 1922442Swnj 1932442Swnj /* 1942872Swnj * Perform callouts (but not after panic's!) 1952442Swnj */ 1963542Swnj if (panicstr == 0) { 1973542Swnj for (;;) { 1983542Swnj s = spl7(); 1994250Swnj if ((p1 = calltodo.c_next) == 0 || p1->c_time > 0) { 2004250Swnj splx(s); 2013542Swnj break; 2024250Swnj } 2033542Swnj calltodo.c_next = p1->c_next; 2043542Swnj arg = p1->c_arg; 2053542Swnj func = p1->c_func; 2063542Swnj p1->c_next = callfree; 2073542Swnj callfree = p1; 2083542Swnj (void) splx(s); 2093542Swnj (*func)(arg); 2102442Swnj } 2112442Swnj } 2122442Swnj 2132442Swnj /* 2142442Swnj * Drain silos. 2152442Swnj */ 2162647Swnj #if NDH > 0 2172442Swnj s = spl5(); dhtimer(); splx(s); 2182442Swnj #endif 2192647Swnj #if NDZ > 0 2202442Swnj s = spl5(); dztimer(); splx(s); 2212442Swnj #endif 2222442Swnj 2232442Swnj /* 2242450Swnj * If idling and processes are waiting to swap in, 2252450Swnj * check on them. 2262450Swnj */ 2272450Swnj if (noproc && runin) { 2282450Swnj runin = 0; 2292450Swnj wakeup((caddr_t)&runin); 2302450Swnj } 2312450Swnj 2322450Swnj /* 2333876Swnj * Run paging daemon every 1/4 sec. 2342442Swnj */ 2352768Swnj if (lbolt % (hz/4) == 0) { 2369Sbill vmpago(); 2373876Swnj } 2383876Swnj 2393876Swnj /* 2403876Swnj * Reschedule every 1/10 sec. 2413876Swnj */ 2423876Swnj if (lbolt % (hz/10) == 0) { 2439Sbill runrun++; 2442442Swnj aston(); 2459Sbill } 2462442Swnj 2472442Swnj /* 2482442Swnj * Lightning bolt every second: 2492442Swnj * sleep timeouts 2502442Swnj * process priority recomputation 2512442Swnj * process %cpu averaging 2522442Swnj * virtual memory metering 2532442Swnj * kick swapper if processes want in 2542442Swnj */ 2552768Swnj if (lbolt >= hz) { 2562872Swnj /* 2573110Swnj * This doesn't mean much on VAX since we run at 2582872Swnj * software interrupt time... if hardclock() 2592872Swnj * calls softclock() directly, it prevents 2602872Swnj * this code from running when the priority 2612872Swnj * was raised when the clock interrupt occurred. 2622872Swnj */ 2639Sbill if (BASEPRI(ps)) 2649Sbill return; 2652872Swnj 2662872Swnj /* 2672872Swnj * If we didn't run a few times because of 2682872Swnj * long blockage at high ipl, we don't 2692872Swnj * really want to run this code several times, 2702872Swnj * so squish out all multiples of hz here. 2712872Swnj */ 2722872Swnj time += lbolt / hz; 2732872Swnj lbolt %= hz; 2742872Swnj 2752872Swnj /* 2762872Swnj * Wakeup lightning bolt sleepers. 2772872Swnj * Processes sleep on lbolt to wait 2782872Swnj * for short amounts of time (e.g. 1 second). 2792872Swnj */ 2809Sbill wakeup((caddr_t)&lbolt); 2812872Swnj 2822872Swnj /* 2832872Swnj * Recompute process priority and process 2842872Swnj * sleep() system calls as well as internal 2852872Swnj * sleeps with timeouts (tsleep() kernel routine). 2862872Swnj */ 2872872Swnj for (pp = proc; pp < procNPROC; pp++) 288928Sbill if (pp->p_stat && pp->p_stat!=SZOMB) { 2892872Swnj /* 2902872Swnj * Increase resident time, to max of 127 seconds 2912872Swnj * (it is kept in a character.) For 2922872Swnj * loaded processes this is time in core; for 2932872Swnj * swapped processes, this is time on drum. 2942872Swnj */ 2952872Swnj if (pp->p_time != 127) 2969Sbill pp->p_time++; 2972872Swnj /* 2982872Swnj * If process has clock counting down, and it 2992872Swnj * expires, set it running (if this is a tsleep()), 3002872Swnj * or give it an SIGALRM (if the user process 3012872Swnj * is using alarm signals. 3022872Swnj */ 3032872Swnj if (pp->p_clktim && --pp->p_clktim == 0) 3042872Swnj if (pp->p_flag & STIMO) { 3052872Swnj s = spl6(); 3062872Swnj switch (pp->p_stat) { 307204Sbill 3082872Swnj case SSLEEP: 3092872Swnj setrun(pp); 3102872Swnj break; 311204Sbill 3122872Swnj case SSTOP: 3132872Swnj unsleep(pp); 3142872Swnj break; 3152872Swnj } 3162872Swnj pp->p_flag &= ~STIMO; 3172872Swnj splx(s); 3182872Swnj } else 3192872Swnj psignal(pp, SIGALRM); 3202872Swnj /* 3212872Swnj * If process is blocked, increment computed 3222872Swnj * time blocked. This is used in swap scheduling. 3232872Swnj */ 3242872Swnj if (pp->p_stat==SSLEEP || pp->p_stat==SSTOP) 3259Sbill if (pp->p_slptime != 127) 3269Sbill pp->p_slptime++; 3272872Swnj /* 3282872Swnj * Update digital filter estimation of process 3292872Swnj * cpu utilization for loaded processes. 3302872Swnj */ 3311399Sbill if (pp->p_flag&SLOAD) 3321399Sbill pp->p_pctcpu = ccpu * pp->p_pctcpu + 3332768Swnj (1.0 - ccpu) * (pp->p_cpticks/(float)hz); 3342872Swnj /* 3352872Swnj * Recompute process priority. The number p_cpu 3362872Swnj * is a weighted estimate of cpu time consumed. 3372872Swnj * A process which consumes cpu time has this 3382872Swnj * increase regularly. We here decrease it by 3393876Swnj * a fraction based on load average giving a digital 3403876Swnj * decay filter which damps out in about 5 seconds 3413876Swnj * when seconds are measured in time expanded by the 3423876Swnj * load average. 3432872Swnj * 3442872Swnj * If a process is niced, then the nice directly 3452872Swnj * affects the new priority. The final priority 3462872Swnj * is in the range 0 to 255, to fit in a character. 3472872Swnj */ 3481399Sbill pp->p_cpticks = 0; 3493876Swnj a = ave((pp->p_cpu & 0377), avenrun[0]*nrscale) + 3503876Swnj pp->p_nice - NZERO; 3512872Swnj if (a < 0) 3529Sbill a = 0; 3532872Swnj if (a > 255) 3549Sbill a = 255; 3559Sbill pp->p_cpu = a; 356125Sbill (void) setpri(pp); 3572872Swnj /* 3582872Swnj * Now have computed new process priority 3592872Swnj * in p->p_usrpri. Carefully change p->p_pri. 3602872Swnj * A process is on a run queue associated with 3612872Swnj * this priority, so we must block out process 3622872Swnj * state changes during the transition. 3632872Swnj */ 3649Sbill s = spl6(); 3652872Swnj if (pp->p_pri >= PUSER) { 3669Sbill if ((pp != u.u_procp || noproc) && 3679Sbill pp->p_stat == SRUN && 3689Sbill (pp->p_flag & SLOAD) && 3699Sbill pp->p_pri != pp->p_usrpri) { 3709Sbill remrq(pp); 3719Sbill pp->p_pri = pp->p_usrpri; 3729Sbill setrq(pp); 3739Sbill } else 3749Sbill pp->p_pri = pp->p_usrpri; 3759Sbill } 3769Sbill splx(s); 3779Sbill } 3782872Swnj 3792872Swnj /* 3802872Swnj * Perform virtual memory metering. 3812872Swnj */ 3829Sbill vmmeter(); 3832872Swnj 3842872Swnj /* 3852872Swnj * If the swap process is trying to bring 3862872Swnj * a process in, have it look again to see 3872872Swnj * if it is possible now. 3882872Swnj */ 3892872Swnj if (runin!=0) { 3909Sbill runin = 0; 3919Sbill wakeup((caddr_t)&runin); 3929Sbill } 3932872Swnj 3949Sbill /* 3959Sbill * If there are pages that have been cleaned, 3969Sbill * jolt the pageout daemon to process them. 3979Sbill * We do this here so that these pages will be 3989Sbill * freed if there is an abundance of memory and the 3999Sbill * daemon would not be awakened otherwise. 4009Sbill */ 4019Sbill if (bclnlist != NULL) 4029Sbill wakeup((caddr_t)&proc[2]); 4032872Swnj 4042872Swnj /* 4052872Swnj * If the trap occurred from usermode, 4062872Swnj * then check to see if it has now been 4072872Swnj * running more than 10 minutes of user time 4082872Swnj * and should thus run with reduced priority 4092872Swnj * to give other processes a chance. 4102872Swnj */ 4119Sbill if (USERMODE(ps)) { 4129Sbill pp = u.u_procp; 4132872Swnj if (pp->p_uid && pp->p_nice == NZERO && 4142872Swnj u.u_vm.vm_utime > 600 * hz) 4152872Swnj pp->p_nice = NZERO+4; 416125Sbill (void) setpri(pp); 4179Sbill pp->p_pri = pp->p_usrpri; 4189Sbill } 4199Sbill } 4202872Swnj /* 4212872Swnj * If trapped user-mode, give it a profiling tick. 4222872Swnj */ 4232442Swnj if (USERMODE(ps) && u.u_prof.pr_scale) { 4242442Swnj u.u_procp->p_flag |= SOWEUPC; 4252442Swnj aston(); 4269Sbill } 4279Sbill } 4289Sbill 4299Sbill /* 4303110Swnj * Timeout is called to arrange that 4312768Swnj * fun(arg) is called in tim/hz seconds. 4323542Swnj * An entry is linked into the callout 4333110Swnj * structure. The time in each structure 4342768Swnj * entry is the number of hz's more 4359Sbill * than the previous entry. 4369Sbill * In this way, decrementing the 4379Sbill * first entry has the effect of 4389Sbill * updating all entries. 4399Sbill * 4409Sbill * The panic is there because there is nothing 4419Sbill * intelligent to be done if an entry won't fit. 4429Sbill */ 4439Sbill timeout(fun, arg, tim) 4442450Swnj int (*fun)(); 4452450Swnj caddr_t arg; 4469Sbill { 4473542Swnj register struct callout *p1, *p2, *pnew; 4489Sbill register int t; 4499Sbill int s; 4509Sbill 4513446Sroot /* DEBUGGING CODE */ 4523446Sroot int ttrstrt(); 4533446Sroot 4543446Sroot if (fun == ttrstrt && arg == 0) 4553446Sroot panic("timeout ttrstr arg"); 4563446Sroot /* END DEBUGGING CODE */ 4579Sbill t = tim; 4589Sbill s = spl7(); 4593542Swnj pnew = callfree; 4603542Swnj if (pnew == NULL) 4613542Swnj panic("timeout table overflow"); 4623542Swnj callfree = pnew->c_next; 4633542Swnj pnew->c_arg = arg; 4643542Swnj pnew->c_func = fun; 4653542Swnj for (p1 = &calltodo; (p2 = p1->c_next) && p2->c_time < t; p1 = p2) 4663542Swnj t -= p2->c_time; 4673542Swnj p1->c_next = pnew; 4683542Swnj pnew->c_next = p2; 4693542Swnj pnew->c_time = t; 4703542Swnj if (p2) 4713542Swnj p2->c_time -= t; 4729Sbill splx(s); 4739Sbill } 474