1*305Sbill /* 10/14/12 3.12 kern_clock.c */ 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; 49*305Sbill int a, cpstate; 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 if (USERMODE(ps)) { 1299Sbill u.u_vm.vm_utime++; 1309Sbill if(u.u_procp->p_nice > NZERO) 131*305Sbill cpstate = CP_NICE; 132*305Sbill else 133*305Sbill cpstate = CP_USER; 1349Sbill } else { 135*305Sbill cpstate = CP_SYS; 1369Sbill if (noproc) 137*305Sbill cpstate = CP_IDLE; 1389Sbill else 1399Sbill u.u_vm.vm_stime++; 1409Sbill } 141*305Sbill dk_time[cpstate][dk_busy&(DK_NSTATES-1)]++; 1429Sbill if (!noproc) { 1439Sbill pp = u.u_procp; 1449Sbill if(++pp->p_cpu == 0) 1459Sbill pp->p_cpu--; 1469Sbill if(pp->p_cpu % 16 == 0) { 147125Sbill (void) setpri(pp); 1489Sbill if (pp->p_pri >= PUSER) 1499Sbill pp->p_pri = pp->p_usrpri; 1509Sbill } 1519Sbill } 1529Sbill ++lbolt; 1539Sbill if (lbolt % (HZ/4) == 0) { 1549Sbill vmpago(); 1559Sbill runrun++; 1569Sbill } 1579Sbill if (lbolt >= HZ) { 1589Sbill if (BASEPRI(ps)) 1599Sbill return; 1609Sbill lbolt -= HZ; 1619Sbill ++time; 162125Sbill (void) spl1(); 1639Sbill runrun++; 1649Sbill wakeup((caddr_t)&lbolt); 1659Sbill for(pp = &proc[0]; pp < &proc[NPROC]; pp++) 1669Sbill if (pp->p_stat && pp->p_stat<SZOMB) { 1679Sbill if(pp->p_time != 127) 1689Sbill pp->p_time++; 1699Sbill if(pp->p_clktim) 1709Sbill if(--pp->p_clktim == 0) 171101Sbill if (pp->p_flag & STIMO) { 172101Sbill s = spl6(); 173204Sbill switch (pp->p_stat) { 174204Sbill 175204Sbill case SSLEEP: 176101Sbill setrun(pp); 177204Sbill break; 178204Sbill 179204Sbill case SSTOP: 180204Sbill unsleep(pp); 181204Sbill break; 182204Sbill } 183101Sbill pp->p_flag &= ~STIMO; 184101Sbill splx(s); 185101Sbill } else 186166Sbill psignal(pp, SIGALRM); 1879Sbill if(pp->p_stat==SSLEEP||pp->p_stat==SSTOP) 1889Sbill if (pp->p_slptime != 127) 1899Sbill pp->p_slptime++; 1909Sbill if(pp->p_flag&SLOAD) { 1919Sbill ave(pp->p_aveflt, pp->p_faults, 5); 1929Sbill pp->p_faults = 0; 1939Sbill } 1949Sbill a = (pp->p_cpu & 0377)*SCHMAG + pp->p_nice - NZERO; 1959Sbill if(a < 0) 1969Sbill a = 0; 1979Sbill if(a > 255) 1989Sbill a = 255; 1999Sbill pp->p_cpu = a; 200125Sbill (void) setpri(pp); 2019Sbill s = spl6(); 2029Sbill if(pp->p_pri >= PUSER) { 2039Sbill if ((pp != u.u_procp || noproc) && 2049Sbill pp->p_stat == SRUN && 2059Sbill (pp->p_flag & SLOAD) && 2069Sbill pp->p_pri != pp->p_usrpri) { 2079Sbill remrq(pp); 2089Sbill pp->p_pri = pp->p_usrpri; 2099Sbill setrq(pp); 2109Sbill } else 2119Sbill pp->p_pri = pp->p_usrpri; 2129Sbill } 2139Sbill splx(s); 2149Sbill } 2159Sbill vmmeter(); 2169Sbill if(runin!=0) { 2179Sbill runin = 0; 2189Sbill wakeup((caddr_t)&runin); 2199Sbill } 2209Sbill /* 2219Sbill * If there are pages that have been cleaned, 2229Sbill * jolt the pageout daemon to process them. 2239Sbill * We do this here so that these pages will be 2249Sbill * freed if there is an abundance of memory and the 2259Sbill * daemon would not be awakened otherwise. 2269Sbill */ 2279Sbill if (bclnlist != NULL) 2289Sbill wakeup((caddr_t)&proc[2]); 2299Sbill #ifdef ERNIE 2309Sbill if (USERMODE(ps)) { 2319Sbill pp = u.u_procp; 2329Sbill if (pp->p_uid) 2339Sbill if (pp->p_nice == NZERO && u.u_vm.vm_utime > 600 * HZ) 2349Sbill pp->p_nice = NZERO+4; 235125Sbill (void) setpri(pp); 2369Sbill pp->p_pri = pp->p_usrpri; 2379Sbill } 2389Sbill #endif 2399Sbill } 240277Sbill if (!BASEPRI(ps)) 241277Sbill unhang(); 2429Sbill if (USERMODE(ps)) { 2439Sbill /* 2449Sbill * We do this last since it 2459Sbill * may block on a page fault in user space. 2469Sbill */ 2479Sbill if (u.u_prof.pr_scale) 2489Sbill addupc(pc, &u.u_prof, 1); 2499Sbill } 2509Sbill #ifdef KPROF 2519Sbill else if (!noproc) { 252104Sbill register int indx = ((int)pc & 0x7fffffff) / 4; 2539Sbill 2549Sbill if (indx >= 0 && indx < 20000) 255104Sbill if (++kcount[indx] == 0) 256104Sbill --kcount[indx]; 2579Sbill } 2589Sbill #endif 2599Sbill } 2609Sbill 2619Sbill /* 2629Sbill * timeout is called to arrange that 2639Sbill * fun(arg) is called in tim/HZ seconds. 2649Sbill * An entry is sorted into the callout 2659Sbill * structure. The time in each structure 2669Sbill * entry is the number of HZ's more 2679Sbill * than the previous entry. 2689Sbill * In this way, decrementing the 2699Sbill * first entry has the effect of 2709Sbill * updating all entries. 2719Sbill * 2729Sbill * The panic is there because there is nothing 2739Sbill * intelligent to be done if an entry won't fit. 2749Sbill */ 2759Sbill timeout(fun, arg, tim) 2769Sbill int (*fun)(); 2779Sbill caddr_t arg; 2789Sbill { 2799Sbill register struct callo *p1, *p2; 2809Sbill register int t; 2819Sbill int s; 2829Sbill 2839Sbill t = tim; 2849Sbill p1 = &callout[0]; 2859Sbill s = spl7(); 2869Sbill while(p1->c_func != 0 && p1->c_time <= t) { 2879Sbill t -= p1->c_time; 2889Sbill p1++; 2899Sbill } 2909Sbill if (p1 >= &callout[NCALL-1]) 2919Sbill panic("Timeout table overflow"); 2929Sbill p1->c_time -= t; 2939Sbill p2 = p1; 2949Sbill while(p2->c_func != 0) 2959Sbill p2++; 2969Sbill while(p2 >= p1) { 2979Sbill (p2+1)->c_time = p2->c_time; 2989Sbill (p2+1)->c_func = p2->c_func; 2999Sbill (p2+1)->c_arg = p2->c_arg; 3009Sbill p2--; 3019Sbill } 3029Sbill p1->c_time = t; 3039Sbill p1->c_func = fun; 3049Sbill p1->c_arg = arg; 3059Sbill splx(s); 3069Sbill } 307