1*204Sbill /* kern_clock.c 3.9 10/14/12 */ 29Sbill 39Sbill #include "../h/param.h" 49Sbill #include "../h/systm.h" 59Sbill #include "../h/callo.h" 69Sbill #include "../h/seg.h" 79Sbill #include "../h/dir.h" 89Sbill #include "../h/user.h" 99Sbill #include "../h/proc.h" 109Sbill #include "../h/reg.h" 119Sbill #include "../h/psl.h" 129Sbill #include "../h/vm.h" 139Sbill #include "../h/buf.h" 149Sbill #include "../h/text.h" 159Sbill 169Sbill #define SCHMAG 9/10 179Sbill 189Sbill 199Sbill /* 209Sbill * clock is called straight from 219Sbill * the real time clock interrupt. 229Sbill * 239Sbill * Functions: 249Sbill * implement callouts 259Sbill * maintain user/system times 269Sbill * maintain date 279Sbill * profile 289Sbill * lightning bolt wakeup (every second) 299Sbill * alarm clock signals 309Sbill * jab the scheduler 319Sbill */ 329Sbill #ifdef KPROF 33104Sbill unsigned short kcount[20000]; 349Sbill #endif 359Sbill 36115Sbill /* 37115Sbill * We handle regular calls to the dh and dz silo input processors 38115Sbill * without using timeouts to save a little time. 39115Sbill */ 40142Sbill int rintvl = 0; /* every 1/60'th of sec check receivers */ 41115Sbill int rcnt; 42115Sbill 439Sbill clock(pc, ps) 449Sbill caddr_t pc; 459Sbill { 469Sbill register struct callo *p1, *p2; 479Sbill register struct proc *pp; 489Sbill register int s; 499Sbill int a; 509Sbill 519Sbill /* 529Sbill * reprime clock 539Sbill */ 549Sbill clkreld(); 559Sbill 569Sbill /* 579Sbill * callouts 589Sbill * else update first non-zero time 599Sbill */ 609Sbill 619Sbill if(callout[0].c_func == NULL) 629Sbill goto out; 639Sbill p2 = &callout[0]; 649Sbill while(p2->c_time<=0 && p2->c_func!=NULL) 659Sbill p2++; 669Sbill p2->c_time--; 679Sbill 689Sbill /* 699Sbill * if ps is high, just return 709Sbill */ 719Sbill if (BASEPRI(ps)) 729Sbill goto out; 739Sbill 749Sbill /* 759Sbill * callout 769Sbill */ 779Sbill 789Sbill if(callout[0].c_time <= 0) { 799Sbill p1 = &callout[0]; 809Sbill while(p1->c_func != 0 && p1->c_time <= 0) { 819Sbill (*p1->c_func)(p1->c_arg); 829Sbill p1++; 839Sbill } 849Sbill p2 = &callout[0]; 859Sbill while(p2->c_func = p1->c_func) { 869Sbill p2->c_time = p1->c_time; 879Sbill p2->c_arg = p1->c_arg; 889Sbill p1++; 899Sbill p2++; 909Sbill } 919Sbill } 929Sbill 939Sbill /* 949Sbill * lightning bolt time-out 959Sbill * and time of day 969Sbill */ 979Sbill out: 98138Sbill 99138Sbill /* 100138Sbill * In order to not take input character interrupts to use 101138Sbill * the input silo on DZ's we have to guarantee to echo 102138Sbill * characters regularly. This means that we have to 103138Sbill * call the timer routines predictably. Since blocking 104138Sbill * in these routines is at spl5(), we have to make spl5() 105138Sbill * really spl6() blocking off the clock to put this code 106138Sbill * here. Note also that it is critical that we run spl5() 107138Sbill * (i.e. really spl6()) in the receiver interrupt routines 108138Sbill * so we can't enter them recursively and transpose characters. 109138Sbill */ 110138Sbill if (rcnt >= rintvl) { 111138Sbill dhtimer(); 112138Sbill dztimer(); 113138Sbill rcnt = 0; 114138Sbill } else 115138Sbill rcnt++; 1169Sbill if (!noproc) { 1179Sbill s = u.u_procp->p_rssize; 1189Sbill u.u_vm.vm_idsrss += s; 1199Sbill if (u.u_procp->p_textp) { 1209Sbill register int xrss = u.u_procp->p_textp->x_rssize; 1219Sbill 1229Sbill s += xrss; 1239Sbill u.u_vm.vm_ixrss += xrss; 1249Sbill } 1259Sbill if (s > u.u_vm.vm_maxrss) 1269Sbill u.u_vm.vm_maxrss = s; 1279Sbill } 1289Sbill a = dk_busy&07; 1299Sbill if (USERMODE(ps)) { 1309Sbill u.u_vm.vm_utime++; 1319Sbill if(u.u_procp->p_nice > NZERO) 1329Sbill a += 8; 1339Sbill } else { 1349Sbill a += 16; 1359Sbill if (noproc) 1369Sbill a += 8; 1379Sbill else 1389Sbill u.u_vm.vm_stime++; 1399Sbill } 1409Sbill dk_time[a]++; 1419Sbill if (!noproc) { 1429Sbill pp = u.u_procp; 1439Sbill if(++pp->p_cpu == 0) 1449Sbill pp->p_cpu--; 1459Sbill if(pp->p_cpu % 16 == 0) { 146125Sbill (void) setpri(pp); 1479Sbill if (pp->p_pri >= PUSER) 1489Sbill pp->p_pri = pp->p_usrpri; 1499Sbill } 1509Sbill } 1519Sbill ++lbolt; 1529Sbill if (lbolt % (HZ/4) == 0) { 1539Sbill vmpago(); 1549Sbill runrun++; 1559Sbill } 1569Sbill if (lbolt >= HZ) { 1579Sbill if (BASEPRI(ps)) 1589Sbill return; 1599Sbill lbolt -= HZ; 1609Sbill ++time; 161125Sbill (void) spl1(); 1629Sbill runrun++; 1639Sbill wakeup((caddr_t)&lbolt); 1649Sbill for(pp = &proc[0]; pp < &proc[NPROC]; pp++) 1659Sbill if (pp->p_stat && pp->p_stat<SZOMB) { 1669Sbill if(pp->p_time != 127) 1679Sbill pp->p_time++; 1689Sbill if(pp->p_clktim) 1699Sbill if(--pp->p_clktim == 0) 170101Sbill if (pp->p_flag & STIMO) { 171101Sbill s = spl6(); 172*204Sbill switch (pp->p_stat) { 173*204Sbill 174*204Sbill case SSLEEP: 175101Sbill setrun(pp); 176*204Sbill break; 177*204Sbill 178*204Sbill case SSTOP: 179*204Sbill unsleep(pp); 180*204Sbill break; 181*204Sbill } 182101Sbill pp->p_flag &= ~STIMO; 183101Sbill splx(s); 184101Sbill } else 185166Sbill psignal(pp, SIGALRM); 1869Sbill if(pp->p_stat==SSLEEP||pp->p_stat==SSTOP) 1879Sbill if (pp->p_slptime != 127) 1889Sbill pp->p_slptime++; 1899Sbill if(pp->p_flag&SLOAD) { 1909Sbill ave(pp->p_aveflt, pp->p_faults, 5); 1919Sbill pp->p_faults = 0; 1929Sbill } 1939Sbill a = (pp->p_cpu & 0377)*SCHMAG + pp->p_nice - NZERO; 1949Sbill if(a < 0) 1959Sbill a = 0; 1969Sbill if(a > 255) 1979Sbill a = 255; 1989Sbill pp->p_cpu = a; 199125Sbill (void) setpri(pp); 2009Sbill s = spl6(); 2019Sbill if(pp->p_pri >= PUSER) { 2029Sbill if ((pp != u.u_procp || noproc) && 2039Sbill pp->p_stat == SRUN && 2049Sbill (pp->p_flag & SLOAD) && 2059Sbill pp->p_pri != pp->p_usrpri) { 2069Sbill remrq(pp); 2079Sbill pp->p_pri = pp->p_usrpri; 2089Sbill setrq(pp); 2099Sbill } else 2109Sbill pp->p_pri = pp->p_usrpri; 2119Sbill } 2129Sbill splx(s); 2139Sbill } 2149Sbill vmmeter(); 2159Sbill if(runin!=0) { 2169Sbill runin = 0; 2179Sbill wakeup((caddr_t)&runin); 2189Sbill } 2199Sbill /* 2209Sbill * If there are pages that have been cleaned, 2219Sbill * jolt the pageout daemon to process them. 2229Sbill * We do this here so that these pages will be 2239Sbill * freed if there is an abundance of memory and the 2249Sbill * daemon would not be awakened otherwise. 2259Sbill */ 2269Sbill if (bclnlist != NULL) 2279Sbill wakeup((caddr_t)&proc[2]); 2289Sbill #ifdef ERNIE 2299Sbill if (USERMODE(ps)) { 2309Sbill pp = u.u_procp; 2319Sbill if (pp->p_uid) 2329Sbill if (pp->p_nice == NZERO && u.u_vm.vm_utime > 600 * HZ) 2339Sbill pp->p_nice = NZERO+4; 234125Sbill (void) setpri(pp); 2359Sbill pp->p_pri = pp->p_usrpri; 2369Sbill } 2379Sbill #endif 2389Sbill } 2399Sbill if (USERMODE(ps)) { 2409Sbill /* 2419Sbill * We do this last since it 2429Sbill * may block on a page fault in user space. 2439Sbill */ 2449Sbill if (u.u_prof.pr_scale) 2459Sbill addupc(pc, &u.u_prof, 1); 2469Sbill } 2479Sbill #ifdef KPROF 2489Sbill else if (!noproc) { 249104Sbill register int indx = ((int)pc & 0x7fffffff) / 4; 2509Sbill 2519Sbill if (indx >= 0 && indx < 20000) 252104Sbill if (++kcount[indx] == 0) 253104Sbill --kcount[indx]; 2549Sbill } 2559Sbill #endif 2569Sbill } 2579Sbill 2589Sbill /* 2599Sbill * timeout is called to arrange that 2609Sbill * fun(arg) is called in tim/HZ seconds. 2619Sbill * An entry is sorted into the callout 2629Sbill * structure. The time in each structure 2639Sbill * entry is the number of HZ's more 2649Sbill * than the previous entry. 2659Sbill * In this way, decrementing the 2669Sbill * first entry has the effect of 2679Sbill * updating all entries. 2689Sbill * 2699Sbill * The panic is there because there is nothing 2709Sbill * intelligent to be done if an entry won't fit. 2719Sbill */ 2729Sbill timeout(fun, arg, tim) 2739Sbill int (*fun)(); 2749Sbill caddr_t arg; 2759Sbill { 2769Sbill register struct callo *p1, *p2; 2779Sbill register int t; 2789Sbill int s; 2799Sbill 2809Sbill t = tim; 2819Sbill p1 = &callout[0]; 2829Sbill s = spl7(); 2839Sbill while(p1->c_func != 0 && p1->c_time <= t) { 2849Sbill t -= p1->c_time; 2859Sbill p1++; 2869Sbill } 2879Sbill if (p1 >= &callout[NCALL-1]) 2889Sbill panic("Timeout table overflow"); 2899Sbill p1->c_time -= t; 2909Sbill p2 = p1; 2919Sbill while(p2->c_func != 0) 2929Sbill p2++; 2939Sbill while(p2 >= p1) { 2949Sbill (p2+1)->c_time = p2->c_time; 2959Sbill (p2+1)->c_func = p2->c_func; 2969Sbill (p2+1)->c_arg = p2->c_arg; 2979Sbill p2--; 2989Sbill } 2999Sbill p1->c_time = t; 3009Sbill p1->c_func = fun; 3019Sbill p1->c_arg = arg; 3029Sbill splx(s); 3039Sbill } 304