1*101Sbill /* kern_clock.c 3.2 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 339Sbill short kcount[20000]; 349Sbill #endif 359Sbill 369Sbill clock(pc, ps) 379Sbill caddr_t pc; 389Sbill { 399Sbill register struct callo *p1, *p2; 409Sbill register struct proc *pp; 419Sbill register int s; 429Sbill int a; 439Sbill 449Sbill /* 459Sbill * reprime clock 469Sbill */ 479Sbill clkreld(); 489Sbill 499Sbill /* 509Sbill * callouts 519Sbill * else update first non-zero time 529Sbill */ 539Sbill 549Sbill if(callout[0].c_func == NULL) 559Sbill goto out; 569Sbill p2 = &callout[0]; 579Sbill while(p2->c_time<=0 && p2->c_func!=NULL) 589Sbill p2++; 599Sbill p2->c_time--; 609Sbill 619Sbill /* 629Sbill * if ps is high, just return 639Sbill */ 649Sbill if (BASEPRI(ps)) 659Sbill goto out; 669Sbill 679Sbill /* 689Sbill * callout 699Sbill */ 709Sbill 719Sbill if(callout[0].c_time <= 0) { 729Sbill p1 = &callout[0]; 739Sbill while(p1->c_func != 0 && p1->c_time <= 0) { 749Sbill (*p1->c_func)(p1->c_arg); 759Sbill p1++; 769Sbill } 779Sbill p2 = &callout[0]; 789Sbill while(p2->c_func = p1->c_func) { 799Sbill p2->c_time = p1->c_time; 809Sbill p2->c_arg = p1->c_arg; 819Sbill p1++; 829Sbill p2++; 839Sbill } 849Sbill } 859Sbill 869Sbill /* 879Sbill * lightning bolt time-out 889Sbill * and time of day 899Sbill */ 909Sbill out: 919Sbill if (!noproc) { 929Sbill s = u.u_procp->p_rssize; 939Sbill u.u_vm.vm_idsrss += s; 949Sbill if (u.u_procp->p_textp) { 959Sbill register int xrss = u.u_procp->p_textp->x_rssize; 969Sbill 979Sbill s += xrss; 989Sbill u.u_vm.vm_ixrss += xrss; 999Sbill } 1009Sbill if (s > u.u_vm.vm_maxrss) 1019Sbill u.u_vm.vm_maxrss = s; 1029Sbill } 1039Sbill a = dk_busy&07; 1049Sbill if (USERMODE(ps)) { 1059Sbill u.u_vm.vm_utime++; 1069Sbill if(u.u_procp->p_nice > NZERO) 1079Sbill a += 8; 1089Sbill } else { 1099Sbill a += 16; 1109Sbill if (noproc) 1119Sbill a += 8; 1129Sbill else 1139Sbill u.u_vm.vm_stime++; 1149Sbill } 1159Sbill dk_time[a]++; 1169Sbill if (!noproc) { 1179Sbill pp = u.u_procp; 1189Sbill if(++pp->p_cpu == 0) 1199Sbill pp->p_cpu--; 1209Sbill if(pp->p_cpu % 16 == 0) { 1219Sbill VOID setpri(pp); 1229Sbill if (pp->p_pri >= PUSER) 1239Sbill pp->p_pri = pp->p_usrpri; 1249Sbill } 1259Sbill } 1269Sbill ++lbolt; 1279Sbill if (lbolt % (HZ/4) == 0) { 1289Sbill vmpago(); 1299Sbill runrun++; 1309Sbill } 1319Sbill if (lbolt >= HZ) { 1329Sbill if (BASEPRI(ps)) 1339Sbill return; 1349Sbill lbolt -= HZ; 1359Sbill ++time; 1369Sbill VOID spl1(); 1379Sbill runrun++; 1389Sbill wakeup((caddr_t)&lbolt); 1399Sbill for(pp = &proc[0]; pp < &proc[NPROC]; pp++) 1409Sbill if (pp->p_stat && pp->p_stat<SZOMB) { 1419Sbill if(pp->p_time != 127) 1429Sbill pp->p_time++; 1439Sbill if(pp->p_clktim) 1449Sbill if(--pp->p_clktim == 0) 145*101Sbill if (pp->p_flag & STIMO) { 146*101Sbill s = spl6(); 147*101Sbill if (pp->p_stat == SSLEEP) 148*101Sbill setrun(pp); 149*101Sbill pp->p_flag &= ~STIMO; 150*101Sbill splx(s); 151*101Sbill } else 152*101Sbill psignal(pp, SIGCLK); 1539Sbill if(pp->p_stat==SSLEEP||pp->p_stat==SSTOP) 1549Sbill if (pp->p_slptime != 127) 1559Sbill pp->p_slptime++; 1569Sbill if(pp->p_flag&SLOAD) { 1579Sbill ave(pp->p_aveflt, pp->p_faults, 5); 1589Sbill pp->p_faults = 0; 1599Sbill } 1609Sbill a = (pp->p_cpu & 0377)*SCHMAG + pp->p_nice - NZERO; 1619Sbill if(a < 0) 1629Sbill a = 0; 1639Sbill if(a > 255) 1649Sbill a = 255; 1659Sbill pp->p_cpu = a; 1669Sbill VOID setpri(pp); 1679Sbill s = spl6(); 1689Sbill if(pp->p_pri >= PUSER) { 1699Sbill if ((pp != u.u_procp || noproc) && 1709Sbill pp->p_stat == SRUN && 1719Sbill (pp->p_flag & SLOAD) && 1729Sbill pp->p_pri != pp->p_usrpri) { 1739Sbill remrq(pp); 1749Sbill pp->p_pri = pp->p_usrpri; 1759Sbill setrq(pp); 1769Sbill } else 1779Sbill pp->p_pri = pp->p_usrpri; 1789Sbill } 1799Sbill splx(s); 1809Sbill } 1819Sbill vmmeter(); 1829Sbill if(runin!=0) { 1839Sbill runin = 0; 1849Sbill wakeup((caddr_t)&runin); 1859Sbill } 1869Sbill /* 1879Sbill * If there are pages that have been cleaned, 1889Sbill * jolt the pageout daemon to process them. 1899Sbill * We do this here so that these pages will be 1909Sbill * freed if there is an abundance of memory and the 1919Sbill * daemon would not be awakened otherwise. 1929Sbill */ 1939Sbill if (bclnlist != NULL) 1949Sbill wakeup((caddr_t)&proc[2]); 1959Sbill #ifdef ERNIE 1969Sbill if (USERMODE(ps)) { 1979Sbill pp = u.u_procp; 1989Sbill if (pp->p_uid) 1999Sbill if (pp->p_nice == NZERO && u.u_vm.vm_utime > 600 * HZ) 2009Sbill pp->p_nice = NZERO+4; 2019Sbill VOID setpri(pp); 2029Sbill pp->p_pri = pp->p_usrpri; 2039Sbill } 2049Sbill #endif 2059Sbill } 2069Sbill if (USERMODE(ps)) { 2079Sbill /* 2089Sbill * We do this last since it 2099Sbill * may block on a page fault in user space. 2109Sbill */ 2119Sbill if (u.u_prof.pr_scale) 2129Sbill addupc(pc, &u.u_prof, 1); 2139Sbill } 2149Sbill #ifdef KPROF 2159Sbill else if (!noproc) { 2169Sbill register int indx = ((int)pc & 0x7fffffff) / 8; 2179Sbill 2189Sbill if (indx >= 0 && indx < 20000) 2199Sbill kcount[indx]++; 2209Sbill } 2219Sbill #endif 2229Sbill } 2239Sbill 2249Sbill /* 2259Sbill * timeout is called to arrange that 2269Sbill * fun(arg) is called in tim/HZ seconds. 2279Sbill * An entry is sorted into the callout 2289Sbill * structure. The time in each structure 2299Sbill * entry is the number of HZ's more 2309Sbill * than the previous entry. 2319Sbill * In this way, decrementing the 2329Sbill * first entry has the effect of 2339Sbill * updating all entries. 2349Sbill * 2359Sbill * The panic is there because there is nothing 2369Sbill * intelligent to be done if an entry won't fit. 2379Sbill */ 2389Sbill timeout(fun, arg, tim) 2399Sbill int (*fun)(); 2409Sbill caddr_t arg; 2419Sbill { 2429Sbill register struct callo *p1, *p2; 2439Sbill register int t; 2449Sbill int s; 2459Sbill 2469Sbill t = tim; 2479Sbill p1 = &callout[0]; 2489Sbill s = spl7(); 2499Sbill while(p1->c_func != 0 && p1->c_time <= t) { 2509Sbill t -= p1->c_time; 2519Sbill p1++; 2529Sbill } 2539Sbill if (p1 >= &callout[NCALL-1]) 2549Sbill panic("Timeout table overflow"); 2559Sbill p1->c_time -= t; 2569Sbill p2 = p1; 2579Sbill while(p2->c_func != 0) 2589Sbill p2++; 2599Sbill while(p2 >= p1) { 2609Sbill (p2+1)->c_time = p2->c_time; 2619Sbill (p2+1)->c_func = p2->c_func; 2629Sbill (p2+1)->c_arg = p2->c_arg; 2639Sbill p2--; 2649Sbill } 2659Sbill p1->c_time = t; 2669Sbill p1->c_func = fun; 2679Sbill p1->c_arg = arg; 2689Sbill splx(s); 2699Sbill } 270