1*115Sbill /* kern_clock.c 3.4 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 36*115Sbill /* 37*115Sbill * We handle regular calls to the dh and dz silo input processors 38*115Sbill * without using timeouts to save a little time. 39*115Sbill */ 40*115Sbill int rintvl = 4; /* every 1/15'th of sec check receivers */ 41*115Sbill int rcnt; 42*115Sbill 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 } 92*115Sbill if (rcnt >= rintvl) { 93*115Sbill dhtimer(); 94*115Sbill dztimer(); 95*115Sbill rcnt = -1; 96*115Sbill } 979Sbill 989Sbill /* 999Sbill * lightning bolt time-out 1009Sbill * and time of day 1019Sbill */ 1029Sbill out: 103*115Sbill ++rcnt; 1049Sbill if (!noproc) { 1059Sbill s = u.u_procp->p_rssize; 1069Sbill u.u_vm.vm_idsrss += s; 1079Sbill if (u.u_procp->p_textp) { 1089Sbill register int xrss = u.u_procp->p_textp->x_rssize; 1099Sbill 1109Sbill s += xrss; 1119Sbill u.u_vm.vm_ixrss += xrss; 1129Sbill } 1139Sbill if (s > u.u_vm.vm_maxrss) 1149Sbill u.u_vm.vm_maxrss = s; 1159Sbill } 1169Sbill a = dk_busy&07; 1179Sbill if (USERMODE(ps)) { 1189Sbill u.u_vm.vm_utime++; 1199Sbill if(u.u_procp->p_nice > NZERO) 1209Sbill a += 8; 1219Sbill } else { 1229Sbill a += 16; 1239Sbill if (noproc) 1249Sbill a += 8; 1259Sbill else 1269Sbill u.u_vm.vm_stime++; 1279Sbill } 1289Sbill dk_time[a]++; 1299Sbill if (!noproc) { 1309Sbill pp = u.u_procp; 1319Sbill if(++pp->p_cpu == 0) 1329Sbill pp->p_cpu--; 1339Sbill if(pp->p_cpu % 16 == 0) { 1349Sbill VOID setpri(pp); 1359Sbill if (pp->p_pri >= PUSER) 1369Sbill pp->p_pri = pp->p_usrpri; 1379Sbill } 1389Sbill } 1399Sbill ++lbolt; 1409Sbill if (lbolt % (HZ/4) == 0) { 1419Sbill vmpago(); 1429Sbill runrun++; 1439Sbill } 1449Sbill if (lbolt >= HZ) { 1459Sbill if (BASEPRI(ps)) 1469Sbill return; 1479Sbill lbolt -= HZ; 1489Sbill ++time; 1499Sbill VOID spl1(); 1509Sbill runrun++; 1519Sbill wakeup((caddr_t)&lbolt); 1529Sbill for(pp = &proc[0]; pp < &proc[NPROC]; pp++) 1539Sbill if (pp->p_stat && pp->p_stat<SZOMB) { 1549Sbill if(pp->p_time != 127) 1559Sbill pp->p_time++; 1569Sbill if(pp->p_clktim) 1579Sbill if(--pp->p_clktim == 0) 158101Sbill if (pp->p_flag & STIMO) { 159101Sbill s = spl6(); 160101Sbill if (pp->p_stat == SSLEEP) 161101Sbill setrun(pp); 162101Sbill pp->p_flag &= ~STIMO; 163101Sbill splx(s); 164101Sbill } else 165101Sbill psignal(pp, SIGCLK); 1669Sbill if(pp->p_stat==SSLEEP||pp->p_stat==SSTOP) 1679Sbill if (pp->p_slptime != 127) 1689Sbill pp->p_slptime++; 1699Sbill if(pp->p_flag&SLOAD) { 1709Sbill ave(pp->p_aveflt, pp->p_faults, 5); 1719Sbill pp->p_faults = 0; 1729Sbill } 1739Sbill a = (pp->p_cpu & 0377)*SCHMAG + pp->p_nice - NZERO; 1749Sbill if(a < 0) 1759Sbill a = 0; 1769Sbill if(a > 255) 1779Sbill a = 255; 1789Sbill pp->p_cpu = a; 1799Sbill VOID setpri(pp); 1809Sbill s = spl6(); 1819Sbill if(pp->p_pri >= PUSER) { 1829Sbill if ((pp != u.u_procp || noproc) && 1839Sbill pp->p_stat == SRUN && 1849Sbill (pp->p_flag & SLOAD) && 1859Sbill pp->p_pri != pp->p_usrpri) { 1869Sbill remrq(pp); 1879Sbill pp->p_pri = pp->p_usrpri; 1889Sbill setrq(pp); 1899Sbill } else 1909Sbill pp->p_pri = pp->p_usrpri; 1919Sbill } 1929Sbill splx(s); 1939Sbill } 1949Sbill vmmeter(); 1959Sbill if(runin!=0) { 1969Sbill runin = 0; 1979Sbill wakeup((caddr_t)&runin); 1989Sbill } 1999Sbill /* 2009Sbill * If there are pages that have been cleaned, 2019Sbill * jolt the pageout daemon to process them. 2029Sbill * We do this here so that these pages will be 2039Sbill * freed if there is an abundance of memory and the 2049Sbill * daemon would not be awakened otherwise. 2059Sbill */ 2069Sbill if (bclnlist != NULL) 2079Sbill wakeup((caddr_t)&proc[2]); 2089Sbill #ifdef ERNIE 2099Sbill if (USERMODE(ps)) { 2109Sbill pp = u.u_procp; 2119Sbill if (pp->p_uid) 2129Sbill if (pp->p_nice == NZERO && u.u_vm.vm_utime > 600 * HZ) 2139Sbill pp->p_nice = NZERO+4; 2149Sbill VOID setpri(pp); 2159Sbill pp->p_pri = pp->p_usrpri; 2169Sbill } 2179Sbill #endif 2189Sbill } 2199Sbill if (USERMODE(ps)) { 2209Sbill /* 2219Sbill * We do this last since it 2229Sbill * may block on a page fault in user space. 2239Sbill */ 2249Sbill if (u.u_prof.pr_scale) 2259Sbill addupc(pc, &u.u_prof, 1); 2269Sbill } 2279Sbill #ifdef KPROF 2289Sbill else if (!noproc) { 229104Sbill register int indx = ((int)pc & 0x7fffffff) / 4; 2309Sbill 2319Sbill if (indx >= 0 && indx < 20000) 232104Sbill if (++kcount[indx] == 0) 233104Sbill --kcount[indx]; 2349Sbill } 2359Sbill #endif 2369Sbill } 2379Sbill 2389Sbill /* 2399Sbill * timeout is called to arrange that 2409Sbill * fun(arg) is called in tim/HZ seconds. 2419Sbill * An entry is sorted into the callout 2429Sbill * structure. The time in each structure 2439Sbill * entry is the number of HZ's more 2449Sbill * than the previous entry. 2459Sbill * In this way, decrementing the 2469Sbill * first entry has the effect of 2479Sbill * updating all entries. 2489Sbill * 2499Sbill * The panic is there because there is nothing 2509Sbill * intelligent to be done if an entry won't fit. 2519Sbill */ 2529Sbill timeout(fun, arg, tim) 2539Sbill int (*fun)(); 2549Sbill caddr_t arg; 2559Sbill { 2569Sbill register struct callo *p1, *p2; 2579Sbill register int t; 2589Sbill int s; 2599Sbill 2609Sbill t = tim; 2619Sbill p1 = &callout[0]; 2629Sbill s = spl7(); 2639Sbill while(p1->c_func != 0 && p1->c_time <= t) { 2649Sbill t -= p1->c_time; 2659Sbill p1++; 2669Sbill } 2679Sbill if (p1 >= &callout[NCALL-1]) 2689Sbill panic("Timeout table overflow"); 2699Sbill p1->c_time -= t; 2709Sbill p2 = p1; 2719Sbill while(p2->c_func != 0) 2729Sbill p2++; 2739Sbill while(p2 >= p1) { 2749Sbill (p2+1)->c_time = p2->c_time; 2759Sbill (p2+1)->c_func = p2->c_func; 2769Sbill (p2+1)->c_arg = p2->c_arg; 2779Sbill p2--; 2789Sbill } 2799Sbill p1->c_time = t; 2809Sbill p1->c_func = fun; 2819Sbill p1->c_arg = arg; 2829Sbill splx(s); 2839Sbill } 284