1*375Sbill /* 10/14/12 3.17 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" 16370Sbill #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; 129*375Sbill if ((u.u_vm.vm_utime+u.u_vm.vm_stime+1)/HZ > u.u_limit[LIM_CPU]) { 130*375Sbill psignal(u.u_procp, SIGXCPU); 131*375Sbill if (u.u_limit[LIM_CPU] < INFINITY - 5) 132*375Sbill u.u_limit[LIM_CPU] += 5; 133*375Sbill } 1349Sbill } 1359Sbill if (USERMODE(ps)) { 1369Sbill u.u_vm.vm_utime++; 1379Sbill if(u.u_procp->p_nice > NZERO) 138305Sbill cpstate = CP_NICE; 139305Sbill else 140305Sbill cpstate = CP_USER; 1419Sbill } else { 142305Sbill cpstate = CP_SYS; 1439Sbill if (noproc) 144305Sbill cpstate = CP_IDLE; 1459Sbill else 1469Sbill u.u_vm.vm_stime++; 1479Sbill } 148305Sbill dk_time[cpstate][dk_busy&(DK_NSTATES-1)]++; 1499Sbill if (!noproc) { 1509Sbill pp = u.u_procp; 1519Sbill if(++pp->p_cpu == 0) 1529Sbill pp->p_cpu--; 1539Sbill if(pp->p_cpu % 16 == 0) { 154125Sbill (void) setpri(pp); 1559Sbill if (pp->p_pri >= PUSER) 1569Sbill pp->p_pri = pp->p_usrpri; 1579Sbill } 1589Sbill } 1599Sbill ++lbolt; 1609Sbill if (lbolt % (HZ/4) == 0) { 1619Sbill vmpago(); 1629Sbill runrun++; 1639Sbill } 1649Sbill if (lbolt >= HZ) { 1659Sbill if (BASEPRI(ps)) 1669Sbill return; 1679Sbill lbolt -= HZ; 1689Sbill ++time; 169125Sbill (void) spl1(); 1709Sbill runrun++; 1719Sbill wakeup((caddr_t)&lbolt); 1729Sbill for(pp = &proc[0]; pp < &proc[NPROC]; pp++) 1739Sbill if (pp->p_stat && pp->p_stat<SZOMB) { 1749Sbill if(pp->p_time != 127) 1759Sbill pp->p_time++; 1769Sbill if(pp->p_clktim) 1779Sbill if(--pp->p_clktim == 0) 178101Sbill if (pp->p_flag & STIMO) { 179101Sbill s = spl6(); 180204Sbill switch (pp->p_stat) { 181204Sbill 182204Sbill case SSLEEP: 183101Sbill setrun(pp); 184204Sbill break; 185204Sbill 186204Sbill case SSTOP: 187204Sbill unsleep(pp); 188204Sbill break; 189204Sbill } 190101Sbill pp->p_flag &= ~STIMO; 191101Sbill splx(s); 192101Sbill } else 193166Sbill psignal(pp, SIGALRM); 1949Sbill if(pp->p_stat==SSLEEP||pp->p_stat==SSTOP) 1959Sbill if (pp->p_slptime != 127) 1969Sbill pp->p_slptime++; 1979Sbill if(pp->p_flag&SLOAD) { 1989Sbill ave(pp->p_aveflt, pp->p_faults, 5); 1999Sbill pp->p_faults = 0; 2009Sbill } 2019Sbill a = (pp->p_cpu & 0377)*SCHMAG + pp->p_nice - NZERO; 2029Sbill if(a < 0) 2039Sbill a = 0; 2049Sbill if(a > 255) 2059Sbill a = 255; 2069Sbill pp->p_cpu = a; 207125Sbill (void) setpri(pp); 2089Sbill s = spl6(); 2099Sbill if(pp->p_pri >= PUSER) { 2109Sbill if ((pp != u.u_procp || noproc) && 2119Sbill pp->p_stat == SRUN && 2129Sbill (pp->p_flag & SLOAD) && 2139Sbill pp->p_pri != pp->p_usrpri) { 2149Sbill remrq(pp); 2159Sbill pp->p_pri = pp->p_usrpri; 2169Sbill setrq(pp); 2179Sbill } else 2189Sbill pp->p_pri = pp->p_usrpri; 2199Sbill } 2209Sbill splx(s); 2219Sbill } 2229Sbill vmmeter(); 2239Sbill if(runin!=0) { 2249Sbill runin = 0; 2259Sbill wakeup((caddr_t)&runin); 2269Sbill } 2279Sbill /* 2289Sbill * If there are pages that have been cleaned, 2299Sbill * jolt the pageout daemon to process them. 2309Sbill * We do this here so that these pages will be 2319Sbill * freed if there is an abundance of memory and the 2329Sbill * daemon would not be awakened otherwise. 2339Sbill */ 2349Sbill if (bclnlist != NULL) 2359Sbill wakeup((caddr_t)&proc[2]); 2369Sbill if (USERMODE(ps)) { 2379Sbill pp = u.u_procp; 238362Sbill #ifdef ERNIE 2399Sbill if (pp->p_uid) 2409Sbill if (pp->p_nice == NZERO && u.u_vm.vm_utime > 600 * HZ) 2419Sbill pp->p_nice = NZERO+4; 242125Sbill (void) setpri(pp); 2439Sbill pp->p_pri = pp->p_usrpri; 244362Sbill #endif 2459Sbill } 2469Sbill } 247277Sbill if (!BASEPRI(ps)) 248277Sbill unhang(); 2499Sbill if (USERMODE(ps)) { 2509Sbill /* 2519Sbill * We do this last since it 2529Sbill * may block on a page fault in user space. 2539Sbill */ 2549Sbill if (u.u_prof.pr_scale) 2559Sbill addupc(pc, &u.u_prof, 1); 2569Sbill } 2579Sbill #ifdef KPROF 2589Sbill else if (!noproc) { 259104Sbill register int indx = ((int)pc & 0x7fffffff) / 4; 2609Sbill 2619Sbill if (indx >= 0 && indx < 20000) 262104Sbill if (++kcount[indx] == 0) 263104Sbill --kcount[indx]; 2649Sbill } 2659Sbill #endif 2669Sbill } 2679Sbill 2689Sbill /* 2699Sbill * timeout is called to arrange that 2709Sbill * fun(arg) is called in tim/HZ seconds. 2719Sbill * An entry is sorted into the callout 2729Sbill * structure. The time in each structure 2739Sbill * entry is the number of HZ's more 2749Sbill * than the previous entry. 2759Sbill * In this way, decrementing the 2769Sbill * first entry has the effect of 2779Sbill * updating all entries. 2789Sbill * 2799Sbill * The panic is there because there is nothing 2809Sbill * intelligent to be done if an entry won't fit. 2819Sbill */ 2829Sbill timeout(fun, arg, tim) 2839Sbill int (*fun)(); 2849Sbill caddr_t arg; 2859Sbill { 2869Sbill register struct callo *p1, *p2; 2879Sbill register int t; 2889Sbill int s; 2899Sbill 2909Sbill t = tim; 2919Sbill p1 = &callout[0]; 2929Sbill s = spl7(); 2939Sbill while(p1->c_func != 0 && p1->c_time <= t) { 2949Sbill t -= p1->c_time; 2959Sbill p1++; 2969Sbill } 2979Sbill if (p1 >= &callout[NCALL-1]) 2989Sbill panic("Timeout table overflow"); 2999Sbill p1->c_time -= t; 3009Sbill p2 = p1; 3019Sbill while(p2->c_func != 0) 3029Sbill p2++; 3039Sbill while(p2 >= p1) { 3049Sbill (p2+1)->c_time = p2->c_time; 3059Sbill (p2+1)->c_func = p2->c_func; 3069Sbill (p2+1)->c_arg = p2->c_arg; 3079Sbill p2--; 3089Sbill } 3099Sbill p1->c_time = t; 3109Sbill p1->c_func = fun; 3119Sbill p1->c_arg = arg; 3129Sbill splx(s); 3139Sbill } 314