1*166Sbill /* kern_clock.c 3.8 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(); 172101Sbill if (pp->p_stat == SSLEEP) 173101Sbill setrun(pp); 174101Sbill pp->p_flag &= ~STIMO; 175101Sbill splx(s); 176101Sbill } else 177*166Sbill psignal(pp, SIGALRM); 1789Sbill if(pp->p_stat==SSLEEP||pp->p_stat==SSTOP) 1799Sbill if (pp->p_slptime != 127) 1809Sbill pp->p_slptime++; 1819Sbill if(pp->p_flag&SLOAD) { 1829Sbill ave(pp->p_aveflt, pp->p_faults, 5); 1839Sbill pp->p_faults = 0; 1849Sbill } 1859Sbill a = (pp->p_cpu & 0377)*SCHMAG + pp->p_nice - NZERO; 1869Sbill if(a < 0) 1879Sbill a = 0; 1889Sbill if(a > 255) 1899Sbill a = 255; 1909Sbill pp->p_cpu = a; 191125Sbill (void) setpri(pp); 1929Sbill s = spl6(); 1939Sbill if(pp->p_pri >= PUSER) { 1949Sbill if ((pp != u.u_procp || noproc) && 1959Sbill pp->p_stat == SRUN && 1969Sbill (pp->p_flag & SLOAD) && 1979Sbill pp->p_pri != pp->p_usrpri) { 1989Sbill remrq(pp); 1999Sbill pp->p_pri = pp->p_usrpri; 2009Sbill setrq(pp); 2019Sbill } else 2029Sbill pp->p_pri = pp->p_usrpri; 2039Sbill } 2049Sbill splx(s); 2059Sbill } 2069Sbill vmmeter(); 2079Sbill if(runin!=0) { 2089Sbill runin = 0; 2099Sbill wakeup((caddr_t)&runin); 2109Sbill } 2119Sbill /* 2129Sbill * If there are pages that have been cleaned, 2139Sbill * jolt the pageout daemon to process them. 2149Sbill * We do this here so that these pages will be 2159Sbill * freed if there is an abundance of memory and the 2169Sbill * daemon would not be awakened otherwise. 2179Sbill */ 2189Sbill if (bclnlist != NULL) 2199Sbill wakeup((caddr_t)&proc[2]); 2209Sbill #ifdef ERNIE 2219Sbill if (USERMODE(ps)) { 2229Sbill pp = u.u_procp; 2239Sbill if (pp->p_uid) 2249Sbill if (pp->p_nice == NZERO && u.u_vm.vm_utime > 600 * HZ) 2259Sbill pp->p_nice = NZERO+4; 226125Sbill (void) setpri(pp); 2279Sbill pp->p_pri = pp->p_usrpri; 2289Sbill } 2299Sbill #endif 2309Sbill } 2319Sbill if (USERMODE(ps)) { 2329Sbill /* 2339Sbill * We do this last since it 2349Sbill * may block on a page fault in user space. 2359Sbill */ 2369Sbill if (u.u_prof.pr_scale) 2379Sbill addupc(pc, &u.u_prof, 1); 2389Sbill } 2399Sbill #ifdef KPROF 2409Sbill else if (!noproc) { 241104Sbill register int indx = ((int)pc & 0x7fffffff) / 4; 2429Sbill 2439Sbill if (indx >= 0 && indx < 20000) 244104Sbill if (++kcount[indx] == 0) 245104Sbill --kcount[indx]; 2469Sbill } 2479Sbill #endif 2489Sbill } 2499Sbill 2509Sbill /* 2519Sbill * timeout is called to arrange that 2529Sbill * fun(arg) is called in tim/HZ seconds. 2539Sbill * An entry is sorted into the callout 2549Sbill * structure. The time in each structure 2559Sbill * entry is the number of HZ's more 2569Sbill * than the previous entry. 2579Sbill * In this way, decrementing the 2589Sbill * first entry has the effect of 2599Sbill * updating all entries. 2609Sbill * 2619Sbill * The panic is there because there is nothing 2629Sbill * intelligent to be done if an entry won't fit. 2639Sbill */ 2649Sbill timeout(fun, arg, tim) 2659Sbill int (*fun)(); 2669Sbill caddr_t arg; 2679Sbill { 2689Sbill register struct callo *p1, *p2; 2699Sbill register int t; 2709Sbill int s; 2719Sbill 2729Sbill t = tim; 2739Sbill p1 = &callout[0]; 2749Sbill s = spl7(); 2759Sbill while(p1->c_func != 0 && p1->c_time <= t) { 2769Sbill t -= p1->c_time; 2779Sbill p1++; 2789Sbill } 2799Sbill if (p1 >= &callout[NCALL-1]) 2809Sbill panic("Timeout table overflow"); 2819Sbill p1->c_time -= t; 2829Sbill p2 = p1; 2839Sbill while(p2->c_func != 0) 2849Sbill p2++; 2859Sbill while(p2 >= p1) { 2869Sbill (p2+1)->c_time = p2->c_time; 2879Sbill (p2+1)->c_func = p2->c_func; 2889Sbill (p2+1)->c_arg = p2->c_arg; 2899Sbill p2--; 2909Sbill } 2919Sbill p1->c_time = t; 2929Sbill p1->c_func = fun; 2939Sbill p1->c_arg = arg; 2949Sbill splx(s); 2959Sbill } 296