1*370Sbill /* 10/14/12 3.15 kern_clock.c */ 29Sbill 39Sbill #include "../h/param.h" 49Sbill #include "../h/systm.h" 5329Sbill #include "../h/dk.h" 69Sbill #include "../h/callo.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" 16*370Sbill #include "../h/limit.h" 179Sbill 189Sbill #define SCHMAG 9/10 199Sbill 209Sbill 219Sbill /* 229Sbill * clock is called straight from 239Sbill * the real time clock interrupt. 249Sbill * 259Sbill * Functions: 269Sbill * implement callouts 279Sbill * maintain user/system times 289Sbill * maintain date 299Sbill * profile 309Sbill * lightning bolt wakeup (every second) 319Sbill * alarm clock signals 329Sbill * jab the scheduler 339Sbill */ 349Sbill #ifdef KPROF 35104Sbill unsigned short kcount[20000]; 369Sbill #endif 379Sbill 38115Sbill /* 39115Sbill * We handle regular calls to the dh and dz silo input processors 40115Sbill * without using timeouts to save a little time. 41115Sbill */ 42142Sbill int rintvl = 0; /* every 1/60'th of sec check receivers */ 43115Sbill int rcnt; 44115Sbill 459Sbill clock(pc, ps) 469Sbill caddr_t pc; 479Sbill { 489Sbill register struct callo *p1, *p2; 499Sbill register struct proc *pp; 509Sbill register int s; 51305Sbill int a, cpstate; 529Sbill 539Sbill /* 549Sbill * reprime clock 559Sbill */ 569Sbill clkreld(); 579Sbill 589Sbill /* 599Sbill * callouts 609Sbill * else update first non-zero time 619Sbill */ 629Sbill 639Sbill if(callout[0].c_func == NULL) 649Sbill goto out; 659Sbill p2 = &callout[0]; 669Sbill while(p2->c_time<=0 && p2->c_func!=NULL) 679Sbill p2++; 689Sbill p2->c_time--; 699Sbill 709Sbill /* 719Sbill * if ps is high, just return 729Sbill */ 739Sbill if (BASEPRI(ps)) 749Sbill goto out; 759Sbill 769Sbill /* 779Sbill * callout 789Sbill */ 799Sbill 809Sbill if(callout[0].c_time <= 0) { 819Sbill p1 = &callout[0]; 829Sbill while(p1->c_func != 0 && p1->c_time <= 0) { 839Sbill (*p1->c_func)(p1->c_arg); 849Sbill p1++; 859Sbill } 869Sbill p2 = &callout[0]; 879Sbill while(p2->c_func = p1->c_func) { 889Sbill p2->c_time = p1->c_time; 899Sbill p2->c_arg = p1->c_arg; 909Sbill p1++; 919Sbill p2++; 929Sbill } 939Sbill } 949Sbill 959Sbill /* 969Sbill * lightning bolt time-out 979Sbill * and time of day 989Sbill */ 999Sbill out: 100138Sbill 101138Sbill /* 102138Sbill * In order to not take input character interrupts to use 103138Sbill * the input silo on DZ's we have to guarantee to echo 104138Sbill * characters regularly. This means that we have to 105138Sbill * call the timer routines predictably. Since blocking 106138Sbill * in these routines is at spl5(), we have to make spl5() 107138Sbill * really spl6() blocking off the clock to put this code 108138Sbill * here. Note also that it is critical that we run spl5() 109138Sbill * (i.e. really spl6()) in the receiver interrupt routines 110138Sbill * so we can't enter them recursively and transpose characters. 111138Sbill */ 112138Sbill if (rcnt >= rintvl) { 113138Sbill dhtimer(); 114138Sbill dztimer(); 115138Sbill rcnt = 0; 116138Sbill } else 117138Sbill rcnt++; 1189Sbill if (!noproc) { 1199Sbill s = u.u_procp->p_rssize; 1209Sbill u.u_vm.vm_idsrss += s; 1219Sbill if (u.u_procp->p_textp) { 1229Sbill register int xrss = u.u_procp->p_textp->x_rssize; 1239Sbill 1249Sbill s += xrss; 1259Sbill u.u_vm.vm_ixrss += xrss; 1269Sbill } 1279Sbill if (s > u.u_vm.vm_maxrss) 1289Sbill u.u_vm.vm_maxrss = s; 1299Sbill } 1309Sbill if (USERMODE(ps)) { 1319Sbill u.u_vm.vm_utime++; 1329Sbill if(u.u_procp->p_nice > NZERO) 133305Sbill cpstate = CP_NICE; 134305Sbill else 135305Sbill cpstate = CP_USER; 1369Sbill } else { 137305Sbill cpstate = CP_SYS; 1389Sbill if (noproc) 139305Sbill cpstate = CP_IDLE; 1409Sbill else 1419Sbill u.u_vm.vm_stime++; 1429Sbill } 143305Sbill dk_time[cpstate][dk_busy&(DK_NSTATES-1)]++; 1449Sbill if (!noproc) { 1459Sbill pp = u.u_procp; 1469Sbill if(++pp->p_cpu == 0) 1479Sbill pp->p_cpu--; 1489Sbill if(pp->p_cpu % 16 == 0) { 149125Sbill (void) setpri(pp); 1509Sbill if (pp->p_pri >= PUSER) 1519Sbill pp->p_pri = pp->p_usrpri; 1529Sbill } 1539Sbill } 1549Sbill ++lbolt; 1559Sbill if (lbolt % (HZ/4) == 0) { 1569Sbill vmpago(); 1579Sbill runrun++; 1589Sbill } 1599Sbill if (lbolt >= HZ) { 1609Sbill if (BASEPRI(ps)) 1619Sbill return; 1629Sbill lbolt -= HZ; 1639Sbill ++time; 164125Sbill (void) spl1(); 1659Sbill runrun++; 1669Sbill wakeup((caddr_t)&lbolt); 1679Sbill for(pp = &proc[0]; pp < &proc[NPROC]; pp++) 1689Sbill if (pp->p_stat && pp->p_stat<SZOMB) { 1699Sbill if(pp->p_time != 127) 1709Sbill pp->p_time++; 1719Sbill if(pp->p_clktim) 1729Sbill if(--pp->p_clktim == 0) 173101Sbill if (pp->p_flag & STIMO) { 174101Sbill s = spl6(); 175204Sbill switch (pp->p_stat) { 176204Sbill 177204Sbill case SSLEEP: 178101Sbill setrun(pp); 179204Sbill break; 180204Sbill 181204Sbill case SSTOP: 182204Sbill unsleep(pp); 183204Sbill break; 184204Sbill } 185101Sbill pp->p_flag &= ~STIMO; 186101Sbill splx(s); 187101Sbill } else 188166Sbill psignal(pp, SIGALRM); 1899Sbill if(pp->p_stat==SSLEEP||pp->p_stat==SSTOP) 1909Sbill if (pp->p_slptime != 127) 1919Sbill pp->p_slptime++; 1929Sbill if(pp->p_flag&SLOAD) { 1939Sbill ave(pp->p_aveflt, pp->p_faults, 5); 1949Sbill pp->p_faults = 0; 1959Sbill } 1969Sbill a = (pp->p_cpu & 0377)*SCHMAG + pp->p_nice - NZERO; 1979Sbill if(a < 0) 1989Sbill a = 0; 1999Sbill if(a > 255) 2009Sbill a = 255; 2019Sbill pp->p_cpu = a; 202125Sbill (void) setpri(pp); 2039Sbill s = spl6(); 2049Sbill if(pp->p_pri >= PUSER) { 2059Sbill if ((pp != u.u_procp || noproc) && 2069Sbill pp->p_stat == SRUN && 2079Sbill (pp->p_flag & SLOAD) && 2089Sbill pp->p_pri != pp->p_usrpri) { 2099Sbill remrq(pp); 2109Sbill pp->p_pri = pp->p_usrpri; 2119Sbill setrq(pp); 2129Sbill } else 2139Sbill pp->p_pri = pp->p_usrpri; 2149Sbill } 2159Sbill splx(s); 2169Sbill } 2179Sbill vmmeter(); 2189Sbill if(runin!=0) { 2199Sbill runin = 0; 2209Sbill wakeup((caddr_t)&runin); 2219Sbill } 2229Sbill /* 2239Sbill * If there are pages that have been cleaned, 2249Sbill * jolt the pageout daemon to process them. 2259Sbill * We do this here so that these pages will be 2269Sbill * freed if there is an abundance of memory and the 2279Sbill * daemon would not be awakened otherwise. 2289Sbill */ 2299Sbill if (bclnlist != NULL) 2309Sbill wakeup((caddr_t)&proc[2]); 2319Sbill if (USERMODE(ps)) { 2329Sbill pp = u.u_procp; 233362Sbill #ifdef ERNIE 2349Sbill if (pp->p_uid) 2359Sbill if (pp->p_nice == NZERO && u.u_vm.vm_utime > 600 * HZ) 2369Sbill pp->p_nice = NZERO+4; 237125Sbill (void) setpri(pp); 2389Sbill pp->p_pri = pp->p_usrpri; 239362Sbill #endif 240362Sbill if (u.u_vm.vm_utime+u.u_vm.vm_stime > u.u_limit[LIM_CPU]) 241362Sbill psignal(pp, SIGXCPU); 2429Sbill } 2439Sbill } 244277Sbill if (!BASEPRI(ps)) 245277Sbill unhang(); 2469Sbill if (USERMODE(ps)) { 2479Sbill /* 2489Sbill * We do this last since it 2499Sbill * may block on a page fault in user space. 2509Sbill */ 2519Sbill if (u.u_prof.pr_scale) 2529Sbill addupc(pc, &u.u_prof, 1); 2539Sbill } 2549Sbill #ifdef KPROF 2559Sbill else if (!noproc) { 256104Sbill register int indx = ((int)pc & 0x7fffffff) / 4; 2579Sbill 2589Sbill if (indx >= 0 && indx < 20000) 259104Sbill if (++kcount[indx] == 0) 260104Sbill --kcount[indx]; 2619Sbill } 2629Sbill #endif 2639Sbill } 2649Sbill 2659Sbill /* 2669Sbill * timeout is called to arrange that 2679Sbill * fun(arg) is called in tim/HZ seconds. 2689Sbill * An entry is sorted into the callout 2699Sbill * structure. The time in each structure 2709Sbill * entry is the number of HZ's more 2719Sbill * than the previous entry. 2729Sbill * In this way, decrementing the 2739Sbill * first entry has the effect of 2749Sbill * updating all entries. 2759Sbill * 2769Sbill * The panic is there because there is nothing 2779Sbill * intelligent to be done if an entry won't fit. 2789Sbill */ 2799Sbill timeout(fun, arg, tim) 2809Sbill int (*fun)(); 2819Sbill caddr_t arg; 2829Sbill { 2839Sbill register struct callo *p1, *p2; 2849Sbill register int t; 2859Sbill int s; 2869Sbill 2879Sbill t = tim; 2889Sbill p1 = &callout[0]; 2899Sbill s = spl7(); 2909Sbill while(p1->c_func != 0 && p1->c_time <= t) { 2919Sbill t -= p1->c_time; 2929Sbill p1++; 2939Sbill } 2949Sbill if (p1 >= &callout[NCALL-1]) 2959Sbill panic("Timeout table overflow"); 2969Sbill p1->c_time -= t; 2979Sbill p2 = p1; 2989Sbill while(p2->c_func != 0) 2999Sbill p2++; 3009Sbill while(p2 >= p1) { 3019Sbill (p2+1)->c_time = p2->c_time; 3029Sbill (p2+1)->c_func = p2->c_func; 3039Sbill (p2+1)->c_arg = p2->c_arg; 3049Sbill p2--; 3059Sbill } 3069Sbill p1->c_time = t; 3079Sbill p1->c_func = fun; 3089Sbill p1->c_arg = arg; 3099Sbill splx(s); 3109Sbill } 311