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