X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/ec213dfb3118d0247a75ef91ed0c6fd8e02ea351..233328fcccc6ee5a686c52f66897a525302bab23:/usr/src/sys/kern/kern_clock.c diff --git a/usr/src/sys/kern/kern_clock.c b/usr/src/sys/kern/kern_clock.c index 7f219d612d..f021224b6f 100644 --- a/usr/src/sys/kern/kern_clock.c +++ b/usr/src/sys/kern/kern_clock.c @@ -1,9 +1,9 @@ -/* kern_clock.c 4.3 %G% */ +/* kern_clock.c 4.14 %G% */ #include "../h/param.h" #include "../h/systm.h" #include "../h/dk.h" -#include "../h/callo.h" +#include "../h/callout.h" #include "../h/seg.h" #include "../h/dir.h" #include "../h/user.h" @@ -16,48 +16,45 @@ #include "../h/vlimit.h" #include "../h/mtpr.h" #include "../h/clock.h" +#include "../h/cpu.h" #include "dh.h" #include "dz.h" #define SCHMAG 9/10 -/* - * Constant for decay filter for cpu usage. - */ -double ccpu = 0.95122942450071400909; /* exp(-1/20) */ /* - * Clock is called straight from + * Hardclock is called straight from * the real time clock interrupt. + * We limit the work we do at real clock interrupt time to: + * reloading clock + * decrementing time to callouts + * recording cpu time usage + * modifying priority of current process + * arrange for soft clock interrupt + * kernel pc profiling * - * Functions: + * At softclock interrupt time we: * implement callouts - * maintain user/system times * maintain date - * profile * lightning bolt wakeup (every second) * alarm clock signals * jab the scheduler + * + * On the vax softclock interrupts are implemented by + * software interrupts. Note that we may have multiple softclock + * interrupts compressed into one (due to excessive interrupt load), + * but that hardclock interrupts should never be lost. */ -#ifdef KPROF -unsigned short kcount[20000]; -#endif - -/* - * We handle regular calls to the dh and dz silo input processors - * without using timeouts to save a little time. - */ -int rintvl = 0; /* every 1/60'th of sec check receivers */ -int rcnt; -clock(pc, ps) -caddr_t pc; +/*ARGSUSED*/ +hardclock(pc, ps) + caddr_t pc; { - register struct callo *p1, *p2; + register struct callout *p1; register struct proc *pp; - register int s; - int a, cpstate, i; + register int s, cpstate; /* * reprime clock @@ -65,69 +62,19 @@ caddr_t pc; clkreld(); /* - * callouts - * else update first non-zero time + * update callout times */ - if(callout[0].c_func == NULL) goto out; - p2 = &callout[0]; - while(p2->c_time<=0 && p2->c_func!=NULL) - p2++; - p2->c_time--; - - /* - * if ps is high, just return - */ - if (BASEPRI(ps)) - goto out; - - /* - * callout - */ - - if(callout[0].c_time <= 0) { - p1 = &callout[0]; - while(p1->c_func != 0 && p1->c_time <= 0) { - (*p1->c_func)(p1->c_arg); - p1++; - } - p2 = &callout[0]; - while(p2->c_func = p1->c_func) { - p2->c_time = p1->c_time; - p2->c_arg = p1->c_arg; - p1++; - p2++; - } - } - - /* - * lightning bolt time-out - * and time of day - */ + p1 = &callout[0]; + while(p1->c_time<=0 && p1->c_func!=NULL) + p1++; + p1->c_time--; out: /* - * In order to not take input character interrupts to use - * the input silo on DZ's we have to guarantee to echo - * characters regularly. This means that we have to - * call the timer routines predictably. Since blocking - * in these routines is at spl5(), we have to make spl5() - * really spl6() blocking off the clock to put this code - * here. Note also that it is critical that we run spl5() - * (i.e. really spl6()) in the receiver interrupt routines - * so we can't enter them recursively and transpose characters. + * Maintain iostat and per-process cpu statistics */ - if (rcnt >= rintvl) { -#if NDH11 > 0 - dhtimer(); -#endif -#if NDZ11 > 0 - dztimer(); -#endif - rcnt = 0; - } else - rcnt++; if (!noproc) { s = u.u_procp->p_rssize; u.u_vm.vm_idsrss += s; @@ -139,7 +86,7 @@ out: } if (s > u.u_vm.vm_maxrss) u.u_vm.vm_maxrss = s; - if ((u.u_vm.vm_utime+u.u_vm.vm_stime+1)/HZ > u.u_limit[LIM_CPU]) { + if ((u.u_vm.vm_utime+u.u_vm.vm_stime+1)/hz > u.u_limit[LIM_CPU]) { psignal(u.u_procp, SIGXCPU); if (u.u_limit[LIM_CPU] < INFINITY - 5) u.u_limit[LIM_CPU] += 5; @@ -159,9 +106,9 @@ out: u.u_vm.vm_stime++; } cp_time[cpstate]++; - for (i = 0; i < DK_NDRIVE; i++) - if (dk_busy&(1<p_cpticks++; @@ -174,33 +121,92 @@ out: } } ++lbolt; - if (lbolt % (HZ/4) == 0) { +#if VAX780 + if (cpu == VAX_780 && !BASEPRI(ps)) + unhang(); +#endif + setsoftclock(); +} + +/* + * Constant for decay filter for cpu usage. + */ +double ccpu = 0.95122942450071400909; /* exp(-1/20) */ + +/* + * Software clock interrupt. + * This routine is blocked by spl1(), + * which doesn't block device interrupts! + */ +/*ARGSUSED*/ +softclock(pc, ps) + caddr_t pc; +{ + register struct callout *p1, *p2; + register struct proc *pp; + register int a, s; + + /* + * callout + */ + if(callout[0].c_time <= 0) { + p1 = &callout[0]; + while(p1->c_func != 0 && p1->c_time <= 0) { + (*p1->c_func)(p1->c_arg); + p1++; + } + p2 = &callout[0]; + while(p2->c_func = p1->c_func) { + p2->c_time = p1->c_time; + p2->c_arg = p1->c_arg; + p1++; + p2++; + } + } + + /* + * Drain silos. + */ +#if NDH > 0 + s = spl5(); dhtimer(); splx(s); +#endif +#if NDZ > 0 + s = spl5(); dztimer(); splx(s); +#endif + + /* + * If idling and processes are waiting to swap in, + * check on them. + */ + if (noproc && runin) { + runin = 0; + wakeup((caddr_t)&runin); + } + + /* + * Run paging daemon and reschedule every 1/4 sec. + */ + if (lbolt % (hz/4) == 0) { vmpago(); runrun++; + aston(); } - if (lbolt >= HZ) { -#if VAX==780 - extern int hangcnt; -#endif + /* + * Lightning bolt every second: + * sleep timeouts + * process priority recomputation + * process %cpu averaging + * virtual memory metering + * kick swapper if processes want in + */ + if (lbolt >= hz) { if (BASEPRI(ps)) return; - lbolt -= HZ; + lbolt -= hz; ++time; - (void) spl1(); -#if VAX==780 - /* - * machdep.c:unhang uses hangcnt to make sure uba - * doesn't forget to interrupt (this has been observed). - * This prevents an accumulation of < 5 second uba failures - * from summing to a uba reset. - */ - if (hangcnt) - hangcnt--; -#endif - runrun++; wakeup((caddr_t)&lbolt); - for(pp = &proc[0]; pp < &proc[NPROC]; pp++) + for(pp = proc; pp < procNPROC; pp++) if (pp->p_stat && pp->p_stat!=SZOMB) { if(pp->p_time != 127) pp->p_time++; @@ -227,7 +233,7 @@ out: pp->p_slptime++; if (pp->p_flag&SLOAD) pp->p_pctcpu = ccpu * pp->p_pctcpu + - (1.0 - ccpu) * (pp->p_cpticks/(float)HZ); + (1.0 - ccpu) * (pp->p_cpticks/(float)hz); pp->p_cpticks = 0; a = (pp->p_cpu & 0377)*SCHMAG + pp->p_nice - NZERO; if(a < 0) @@ -266,44 +272,25 @@ out: wakeup((caddr_t)&proc[2]); if (USERMODE(ps)) { pp = u.u_procp; -#ifdef ERNIE if (pp->p_uid) - if (pp->p_nice == NZERO && u.u_vm.vm_utime > 600 * HZ) + if (pp->p_nice == NZERO && u.u_vm.vm_utime > 600 * hz) pp->p_nice = NZERO+4; (void) setpri(pp); pp->p_pri = pp->p_usrpri; -#endif } } -#if VAX==780 - if (!BASEPRI(ps)) - unhang(); -#endif - if (USERMODE(ps)) { - /* - * We do this last since it - * may block on a page fault in user space. - */ - if (u.u_prof.pr_scale) - addupc(pc, &u.u_prof, 1); - } -#ifdef KPROF - else if (!noproc) { - register int indx = ((int)pc & 0x7fffffff) / 4; - - if (indx >= 0 && indx < 20000) - if (++kcount[indx] == 0) - --kcount[indx]; + if (USERMODE(ps) && u.u_prof.pr_scale) { + u.u_procp->p_flag |= SOWEUPC; + aston(); } -#endif } /* * timeout is called to arrange that - * fun(arg) is called in tim/HZ seconds. + * fun(arg) is called in tim/hz seconds. * An entry is sorted into the callout * structure. The time in each structure - * entry is the number of HZ's more + * entry is the number of hz's more * than the previous entry. * In this way, decrementing the * first entry has the effect of @@ -313,10 +300,10 @@ out: * intelligent to be done if an entry won't fit. */ timeout(fun, arg, tim) -int (*fun)(); -caddr_t arg; + int (*fun)(); + caddr_t arg; { - register struct callo *p1, *p2; + register struct callout *p1, *p2, *p3; register int t; int s; @@ -327,12 +314,14 @@ caddr_t arg; t -= p1->c_time; p1++; } - if (p1 >= &callout[NCALL-1]) - panic("Timeout table overflow"); p1->c_time -= t; p2 = p1; - while(p2->c_func != 0) + p3 = callout+(ncallout-2); + while(p2->c_func != 0) { + if (p2 >= p3) + panic("timeout"); p2++; + } while(p2 >= p1) { (p2+1)->c_time = p2->c_time; (p2+1)->c_func = p2->c_func;