1*8112Sroot /* kern_clock.c 4.39 82/09/08 */ 29Sbill 39Sbill #include "../h/param.h" 49Sbill #include "../h/systm.h" 5329Sbill #include "../h/dk.h" 62768Swnj #include "../h/callout.h" 79Sbill #include "../h/dir.h" 89Sbill #include "../h/user.h" 98028Sroot #include "../h/kernel.h" 109Sbill #include "../h/proc.h" 119Sbill #include "../h/psl.h" 129Sbill #include "../h/vm.h" 139Sbill #include "../h/text.h" 147490Skre #ifdef MUSH 157490Skre #include "../h/quota.h" 167490Skre #include "../h/share.h" 177490Skre #endif 189Sbill 191943Swnj #include "dh.h" 201943Swnj #include "dz.h" 217305Ssam #include "ps.h" 221559Sbill 237388Sroot #ifdef GPROF 247388Sroot extern int profiling; 257388Sroot extern char *s_lowpc; 267388Sroot extern u_long s_textsize; 277388Sroot extern u_short *kcount; 284968Swnj #endif 299Sbill 308097Sroot #define bumptime(tp) \ 318097Sroot (tp)->tv_usec += tick; \ 328097Sroot if ((tp)->tv_usec >= 1000000) { \ 338097Sroot (tp)->tv_usec -= 1000000; \ 348097Sroot (tp)->tv_sec++; \ 358097Sroot } 365247Sroot 372609Swnj /*ARGSUSED*/ 382442Swnj hardclock(pc, ps) 392450Swnj caddr_t pc; 409Sbill { 412768Swnj register struct callout *p1; 428097Sroot register struct proc *p; 432442Swnj register int s, cpstate; 447490Skre extern double avenrun[]; 459Sbill 467305Ssam #if NPS > 0 477305Ssam psextsync(pc, ps); 487305Ssam #endif 497305Ssam 508097Sroot /* update callout times */ 513542Swnj for (p1 = calltodo.c_next; p1 && p1->c_time <= 0; p1 = p1->c_next) 52*8112Sroot --p1->c_time; 533542Swnj if (p1) 54*8112Sroot --p1->c_time; 55138Sbill 568097Sroot /* charge process for resource usage... statistically! */ 579Sbill if (!noproc) { 589Sbill s = u.u_procp->p_rssize; 598097Sroot u.u_ru.ru_idrss += s; u.u_ru.ru_isrss += 0; /* XXX */ 609Sbill if (u.u_procp->p_textp) { 619Sbill register int xrss = u.u_procp->p_textp->x_rssize; 629Sbill 639Sbill s += xrss; 648028Sroot u.u_ru.ru_ixrss += xrss; 659Sbill } 668028Sroot if (s > u.u_ru.ru_maxrss) 678028Sroot u.u_ru.ru_maxrss = s; 688028Sroot if ((u.u_ru.ru_utime.tv_sec+u.u_ru.ru_stime.tv_sec+1) > 698028Sroot u.u_rlimit[RLIMIT_CPU].rlim_cur) { 70375Sbill psignal(u.u_procp, SIGXCPU); 718028Sroot if (u.u_rlimit[RLIMIT_CPU].rlim_cur < 728028Sroot u.u_rlimit[RLIMIT_CPU].rlim_max) 738028Sroot u.u_rlimit[RLIMIT_CPU].rlim_cur += 5; 74375Sbill } 758097Sroot if (timerisset(&u.u_timer[ITIMER_PROF].it_value) && 768097Sroot itimerdecr(&u.u_timer[ITIMER_PROF], tick) == 0) 778097Sroot psignal(u.u_procp, SIGPROF); 789Sbill } 798097Sroot 808097Sroot /* charge for cpu */ 819Sbill if (USERMODE(ps)) { 828097Sroot bumptime(&u.u_ru.ru_utime); 838097Sroot if (timerisset(&u.u_timer[ITIMER_VIRTUAL].it_value) && 848097Sroot itimerdecr(&u.u_timer[ITIMER_VIRTUAL], tick) == 0) 858097Sroot psignal(u.u_procp, SIGVTALRM); 868028Sroot if (u.u_procp->p_nice > NZERO) 87305Sbill cpstate = CP_NICE; 88305Sbill else 89305Sbill cpstate = CP_USER; 909Sbill } else { 917388Sroot #ifdef GPROF 927388Sroot int k = pc - s_lowpc; 937388Sroot if (profiling < 2 && k < s_textsize) 947388Sroot kcount[k / sizeof (*kcount)]++; 954968Swnj #endif 96305Sbill cpstate = CP_SYS; 977315Ssam if (noproc) { 987315Ssam if ((ps&PSL_IPL) != 0) 997315Ssam cpstate = CP_IDLE; 1008028Sroot } else { 1018097Sroot bumptime(&u.u_ru.ru_stime); 1028028Sroot } 1039Sbill } 1048097Sroot 1058097Sroot /* iostat statistics */ 1061408Sbill cp_time[cpstate]++; 1072442Swnj for (s = 0; s < DK_NDRIVE; s++) 1082442Swnj if (dk_busy&(1<<s)) 1092442Swnj dk_time[s]++; 1108097Sroot 1118097Sroot /* adjust priority of current process */ 1129Sbill if (!noproc) { 1138097Sroot p = u.u_procp; 1148097Sroot p->p_cpticks++; 1158097Sroot if (++p->p_cpu == 0) 1168097Sroot p->p_cpu--; 1177490Skre #ifdef MUSH 1188097Sroot p->p_quota->q_cost += (p->p_nice > NZERO ? 1198097Sroot (shconsts.sc_tic * ((2*NZERO)-p->p_nice)) / NZERO : 1207490Skre shconsts.sc_tic) * (((int)avenrun[0]+2)/3); 1217490Skre #endif 1228097Sroot if (p->p_cpu % 4 == 0) { 1238097Sroot (void) setpri(p); 1248097Sroot if (p->p_pri >= PUSER) 1258097Sroot p->p_pri = p->p_usrpri; 1269Sbill } 1279Sbill } 1288097Sroot bumptime(&time); 1292442Swnj setsoftclock(); 1302442Swnj } 1312442Swnj 1322609Swnj /*ARGSUSED*/ 1332442Swnj softclock(pc, ps) 1342450Swnj caddr_t pc; 1352442Swnj { 1363615Sroot register struct callout *p1; 1372442Swnj register int a, s; 1383542Swnj caddr_t arg; 1393542Swnj int (*func)(); 1402442Swnj 1418097Sroot if (panicstr) 1428097Sroot goto nocallout; 1438097Sroot for (;;) { 1448097Sroot s = spl7(); 1458097Sroot if ((p1 = calltodo.c_next) == 0 || p1->c_time > 0) { 1468097Sroot splx(s); 1478097Sroot break; 1482442Swnj } 1498097Sroot calltodo.c_next = p1->c_next; 1508097Sroot arg = p1->c_arg; 1518097Sroot func = p1->c_func; 152*8112Sroot a = p1->c_time; 1538097Sroot p1->c_next = callfree; 1548097Sroot callfree = p1; 1558097Sroot (void) splx(s); 156*8112Sroot (*func)(arg, a); 1572442Swnj } 1588097Sroot nocallout: 1592442Swnj 1602647Swnj #if NDH > 0 1612442Swnj s = spl5(); dhtimer(); splx(s); 1622442Swnj #endif 1632647Swnj #if NDZ > 0 1642442Swnj s = spl5(); dztimer(); splx(s); 1652442Swnj #endif 1662442Swnj 1678097Sroot /* if nothing to do, try swapin */ 1682450Swnj if (noproc && runin) { 1692450Swnj runin = 0; 1702450Swnj wakeup((caddr_t)&runin); 1712450Swnj } 1729Sbill } 1739Sbill 1749Sbill /* 1758097Sroot * Arrange that (*fun)(arg) is called in tim/hz seconds. 1769Sbill */ 1779Sbill timeout(fun, arg, tim) 1782450Swnj int (*fun)(); 1792450Swnj caddr_t arg; 1808097Sroot int tim; 1819Sbill { 1823542Swnj register struct callout *p1, *p2, *pnew; 1839Sbill register int t; 1849Sbill int s; 1859Sbill 1869Sbill t = tim; 1879Sbill s = spl7(); 1883542Swnj pnew = callfree; 1893542Swnj if (pnew == NULL) 1903542Swnj panic("timeout table overflow"); 1913542Swnj callfree = pnew->c_next; 1923542Swnj pnew->c_arg = arg; 1933542Swnj pnew->c_func = fun; 1943542Swnj for (p1 = &calltodo; (p2 = p1->c_next) && p2->c_time < t; p1 = p2) 1953542Swnj t -= p2->c_time; 1963542Swnj p1->c_next = pnew; 1973542Swnj pnew->c_next = p2; 1983542Swnj pnew->c_time = t; 1993542Swnj if (p2) 2003542Swnj p2->c_time -= t; 2019Sbill splx(s); 2029Sbill } 2037305Ssam 2047305Ssam /* 2057305Ssam * untimeout is called to remove a function timeout call 2067305Ssam * from the callout structure. 2077305Ssam */ 2088097Sroot untimeout(fun, arg) 2097305Ssam int (*fun)(); 2107305Ssam caddr_t arg; 2117305Ssam { 2127305Ssam register struct callout *p1, *p2; 2137305Ssam register int s; 2147305Ssam 2157305Ssam s = spl7(); 2167305Ssam for (p1 = &calltodo; (p2 = p1->c_next) != 0; p1 = p2) { 2177305Ssam if (p2->c_func == fun && p2->c_arg == arg) { 218*8112Sroot if (p2->c_next && p2->c_time > 0) 2197305Ssam p2->c_next->c_time += p2->c_time; 2207305Ssam p1->c_next = p2->c_next; 2217305Ssam p2->c_next = callfree; 2227305Ssam callfree = p2; 2237305Ssam break; 2247305Ssam } 2257305Ssam } 2267305Ssam splx(s); 2277305Ssam } 228*8112Sroot 229*8112Sroot hzto(tv) 230*8112Sroot struct timeval *tv; 231*8112Sroot { 232*8112Sroot register int ticks; 233*8112Sroot int s = spl7(); 234*8112Sroot 235*8112Sroot ticks = ((tv->tv_sec - time.tv_sec) * 1000 + 236*8112Sroot (tv->tv_usec - time.tv_usec) / 1000) / (tick / 1000); 237*8112Sroot splx(s); 238*8112Sroot return (ticks); 239*8112Sroot } 240