1*9742Ssam /* kern_clock.c 4.47 82/12/16 */ 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" 149604Ssam #ifdef vax 159604Ssam #include "../vax/mtpr.h" 169604Ssam #endif 177490Skre #ifdef MUSH 187490Skre #include "../h/quota.h" 197490Skre #include "../h/share.h" 207490Skre #endif 219Sbill 228124Sroot /* 238124Sroot * Clock handling routines. 248124Sroot * 258124Sroot * This code is written for a machine with only one interval timer, 268124Sroot * and does timing and resource utilization estimation statistically 278124Sroot * based on the state of the machine hz times a second. A machine 288124Sroot * with proper clocks (running separately in user state, system state, 298124Sroot * interrupt state and idle state) as well as a time-of-day clock 308124Sroot * would allow a non-approximate implementation. 318124Sroot */ 321559Sbill 338124Sroot /* 348124Sroot * TODO: 358124Sroot * * Keep more accurate statistics by simulating good interval timers. 368124Sroot * * Use the time-of-day clock on the VAX to keep more accurate time 378124Sroot * than is possible by repeated use of the interval timer. 388124Sroot * * Allocate more timeout table slots when table overflows. 398124Sroot */ 409Sbill 418124Sroot /* bump a timeval by a small number of usec's */ 428124Sroot #define bumptime(tp, usec) \ 438124Sroot (tp)->tv_usec += usec; \ 448097Sroot if ((tp)->tv_usec >= 1000000) { \ 458097Sroot (tp)->tv_usec -= 1000000; \ 468097Sroot (tp)->tv_sec++; \ 478097Sroot } 485247Sroot 498124Sroot /* 508124Sroot * The (single) hardware interval timer. 518124Sroot * We update the events relating to real time, and then 528124Sroot * make a gross assumption: that the system has been in the 538124Sroot * state it is in (user state, kernel state, interrupt state, 548124Sroot * or idle state) for the entire last time interval, and 558124Sroot * update statistics accordingly. 568124Sroot */ 572609Swnj /*ARGSUSED*/ 588965Sroot #ifdef vax 592442Swnj hardclock(pc, ps) 602450Swnj caddr_t pc; 618944Sroot int ps; 629Sbill { 638944Sroot #endif 648965Sroot #ifdef sun 658944Sroot hardclock(regs) 668944Sroot struct regs regs; 678944Sroot { 688944Sroot int ps = regs.r_sr; 698944Sroot caddr_t pc = (caddr_t)regs.r_pc; 708944Sroot #endif 712768Swnj register struct callout *p1; 728097Sroot register struct proc *p; 732442Swnj register int s, cpstate; 749Sbill 758124Sroot /* 768124Sroot * Update real-time timeout queue. 778124Sroot * At front of queue are some number of events which are ``due''. 788124Sroot * The time to these is <= 0 and if negative represents the 798124Sroot * number of ticks which have passed since it was supposed to happen. 808124Sroot * The rest of the q elements (times > 0) are events yet to happen, 818124Sroot * where the time for each is given as a delta from the previous. 828124Sroot * Decrementing just the first of these serves to decrement the time 838124Sroot * to all events. 848124Sroot */ 853542Swnj for (p1 = calltodo.c_next; p1 && p1->c_time <= 0; p1 = p1->c_next) 868112Sroot --p1->c_time; 873542Swnj if (p1) 888112Sroot --p1->c_time; 89138Sbill 908124Sroot /* 918124Sroot * If the cpu is currently scheduled to a process, then 928124Sroot * charge it with resource utilization for a tick, updating 938124Sroot * statistics which run in (user+system) virtual time, 948124Sroot * such as the cpu time limit and profiling timers. 958124Sroot * This assumes that the current process has been running 968124Sroot * the entire last tick. 978124Sroot */ 989Sbill if (!noproc) { 999Sbill s = u.u_procp->p_rssize; 1008097Sroot u.u_ru.ru_idrss += s; u.u_ru.ru_isrss += 0; /* XXX */ 1019Sbill if (u.u_procp->p_textp) { 1029Sbill register int xrss = u.u_procp->p_textp->x_rssize; 1039Sbill 1049Sbill s += xrss; 1058028Sroot u.u_ru.ru_ixrss += xrss; 1069Sbill } 1078028Sroot if (s > u.u_ru.ru_maxrss) 1088028Sroot u.u_ru.ru_maxrss = s; 1098028Sroot if ((u.u_ru.ru_utime.tv_sec+u.u_ru.ru_stime.tv_sec+1) > 1108028Sroot u.u_rlimit[RLIMIT_CPU].rlim_cur) { 111375Sbill psignal(u.u_procp, SIGXCPU); 1128028Sroot if (u.u_rlimit[RLIMIT_CPU].rlim_cur < 1138028Sroot u.u_rlimit[RLIMIT_CPU].rlim_max) 1148028Sroot u.u_rlimit[RLIMIT_CPU].rlim_cur += 5; 115375Sbill } 1168097Sroot if (timerisset(&u.u_timer[ITIMER_PROF].it_value) && 1178097Sroot itimerdecr(&u.u_timer[ITIMER_PROF], tick) == 0) 1188097Sroot psignal(u.u_procp, SIGPROF); 1199Sbill } 1208097Sroot 1218124Sroot /* 1228124Sroot * Charge the time out based on the mode the cpu is in. 1238124Sroot * Here again we fudge for the lack of proper interval timers 1248124Sroot * assuming that the current state has been around at least 1258124Sroot * one tick. 1268124Sroot */ 1279Sbill if (USERMODE(ps)) { 1288124Sroot /* 1298124Sroot * CPU was in user state. Increment 1308124Sroot * user time counter, and process process-virtual time 1319604Ssam * interval timer. 1328124Sroot */ 1338124Sroot bumptime(&u.u_ru.ru_utime, tick); 1348097Sroot if (timerisset(&u.u_timer[ITIMER_VIRTUAL].it_value) && 1358097Sroot itimerdecr(&u.u_timer[ITIMER_VIRTUAL], tick) == 0) 1368097Sroot psignal(u.u_procp, SIGVTALRM); 1378028Sroot if (u.u_procp->p_nice > NZERO) 138305Sbill cpstate = CP_NICE; 139305Sbill else 140305Sbill cpstate = CP_USER; 1419Sbill } else { 1428124Sroot /* 1438124Sroot * CPU was in system state. If profiling kernel 1448124Sroot * increment a counter. If no process is running 1458124Sroot * then this is a system tick if we were running 1468124Sroot * at a non-zero IPL (in a driver). If a process is running, 1478124Sroot * then we charge it with system time even if we were 1488124Sroot * at a non-zero IPL, since the system often runs 1498124Sroot * this way during processing of system calls. 1508124Sroot * This is approximate, but the lack of true interval 1518124Sroot * timers makes doing anything else difficult. 1528124Sroot */ 1537388Sroot #ifdef GPROF 1547388Sroot int k = pc - s_lowpc; 1557388Sroot if (profiling < 2 && k < s_textsize) 1567388Sroot kcount[k / sizeof (*kcount)]++; 1574968Swnj #endif 158305Sbill cpstate = CP_SYS; 1597315Ssam if (noproc) { 1608944Sroot if (BASEPRI(ps)) 1617315Ssam cpstate = CP_IDLE; 1628028Sroot } else { 1638124Sroot bumptime(&u.u_ru.ru_stime, tick); 1648028Sroot } 1659Sbill } 1668097Sroot 1678124Sroot /* 1688124Sroot * We maintain statistics shown by user-level statistics 1698124Sroot * programs: the amount of time in each cpu state, and 1708124Sroot * the amount of time each of DK_NDRIVE ``drives'' is busy. 1718124Sroot */ 1721408Sbill cp_time[cpstate]++; 1732442Swnj for (s = 0; s < DK_NDRIVE; s++) 1742442Swnj if (dk_busy&(1<<s)) 1752442Swnj dk_time[s]++; 1768097Sroot 1778124Sroot /* 1788124Sroot * We adjust the priority of the current process. 1798124Sroot * The priority of a process gets worse as it accumulates 1808124Sroot * CPU time. The cpu usage estimator (p_cpu) is increased here 1818124Sroot * and the formula for computing priorities (in kern_synch.c) 1828124Sroot * will compute a different value each time the p_cpu increases 1838124Sroot * by 4. The cpu usage estimator ramps up quite quickly when 1848124Sroot * the process is running (linearly), and decays away exponentially, 1858124Sroot * at a rate which is proportionally slower when the system is 1868124Sroot * busy. The basic principal is that the system will 90% forget 1878124Sroot * that a process used a lot of CPU time in 5*loadav seconds. 1888124Sroot * This causes the system to favor processes which haven't run 1898124Sroot * much recently, and to round-robin among other processes. 1908124Sroot */ 1919Sbill if (!noproc) { 1928097Sroot p = u.u_procp; 1938097Sroot p->p_cpticks++; 1948097Sroot if (++p->p_cpu == 0) 1958097Sroot p->p_cpu--; 1967490Skre #ifdef MUSH 1978097Sroot p->p_quota->q_cost += (p->p_nice > NZERO ? 1988097Sroot (shconsts.sc_tic * ((2*NZERO)-p->p_nice)) / NZERO : 1997490Skre shconsts.sc_tic) * (((int)avenrun[0]+2)/3); 2007490Skre #endif 2018124Sroot if ((p->p_cpu&3) == 0) { 2028097Sroot (void) setpri(p); 2038097Sroot if (p->p_pri >= PUSER) 2048097Sroot p->p_pri = p->p_usrpri; 2059Sbill } 2069Sbill } 2078124Sroot 2088124Sroot /* 2098124Sroot * Increment the time-of-day, and schedule 2108124Sroot * processing of the callouts at a very low cpu priority, 2118124Sroot * so we don't keep the relatively high clock interrupt 2128124Sroot * priority any longer than necessary. 2138124Sroot */ 2148124Sroot bumptime(&time, tick); 2152442Swnj setsoftclock(); 2162442Swnj } 2172442Swnj 2188124Sroot /* 2198124Sroot * Software priority level clock interrupt. 2208124Sroot * Run periodic events from timeout queue. 2218124Sroot */ 2222609Swnj /*ARGSUSED*/ 2238965Sroot #ifdef vax 2242442Swnj softclock(pc, ps) 2252450Swnj caddr_t pc; 2268944Sroot int ps; 2272442Swnj { 2288944Sroot #endif 2298965Sroot #ifdef sun 2308944Sroot softclock(sirret, regs) 2318944Sroot caddr_t sirreg; 2328944Sroot struct regs regs; 2338944Sroot { 2348944Sroot int ps = regs.r_sr; 2358944Sroot caddr_t pc = (caddr_t)regs.r_pc; 2368944Sroot #endif 2372442Swnj 2388097Sroot for (;;) { 2398124Sroot register struct callout *p1; 2408124Sroot register caddr_t arg; 2418124Sroot register int (*func)(); 2428124Sroot register int a, s; 2438124Sroot 2448097Sroot s = spl7(); 2458097Sroot if ((p1 = calltodo.c_next) == 0 || p1->c_time > 0) { 2468097Sroot splx(s); 2478097Sroot break; 2482442Swnj } 2498124Sroot arg = p1->c_arg; func = p1->c_func; a = p1->c_time; 2508097Sroot calltodo.c_next = p1->c_next; 2518097Sroot p1->c_next = callfree; 2528097Sroot callfree = p1; 2539157Ssam splx(s); 2548112Sroot (*func)(arg, a); 2552442Swnj } 2569604Ssam /* 2579604Ssam * If trapped user-mode, give it a profiling tick. 2589604Ssam */ 2599604Ssam if (USERMODE(ps) && u.u_prof.pr_scale) { 2609604Ssam u.u_procp->p_flag |= SOWEUPC; 2619604Ssam aston(); 2629604Ssam } 2639Sbill } 2649Sbill 2659Sbill /* 2668097Sroot * Arrange that (*fun)(arg) is called in tim/hz seconds. 2679Sbill */ 2689Sbill timeout(fun, arg, tim) 2692450Swnj int (*fun)(); 2702450Swnj caddr_t arg; 2718097Sroot int tim; 2729Sbill { 2733542Swnj register struct callout *p1, *p2, *pnew; 2749Sbill register int t; 2759Sbill int s; 2769Sbill 2779Sbill t = tim; 2789Sbill s = spl7(); 2793542Swnj pnew = callfree; 2803542Swnj if (pnew == NULL) 2813542Swnj panic("timeout table overflow"); 2823542Swnj callfree = pnew->c_next; 2833542Swnj pnew->c_arg = arg; 2843542Swnj pnew->c_func = fun; 2853542Swnj for (p1 = &calltodo; (p2 = p1->c_next) && p2->c_time < t; p1 = p2) 286*9742Ssam if (p2->c_time > 0) 287*9742Ssam t -= p2->c_time; 2883542Swnj p1->c_next = pnew; 2893542Swnj pnew->c_next = p2; 2903542Swnj pnew->c_time = t; 2913542Swnj if (p2) 2923542Swnj p2->c_time -= t; 2939Sbill splx(s); 2949Sbill } 2957305Ssam 2967305Ssam /* 2977305Ssam * untimeout is called to remove a function timeout call 2987305Ssam * from the callout structure. 2997305Ssam */ 3008097Sroot untimeout(fun, arg) 3017305Ssam int (*fun)(); 3027305Ssam caddr_t arg; 3037305Ssam { 3047305Ssam register struct callout *p1, *p2; 3057305Ssam register int s; 3067305Ssam 3077305Ssam s = spl7(); 3087305Ssam for (p1 = &calltodo; (p2 = p1->c_next) != 0; p1 = p2) { 3097305Ssam if (p2->c_func == fun && p2->c_arg == arg) { 3108112Sroot if (p2->c_next && p2->c_time > 0) 3117305Ssam p2->c_next->c_time += p2->c_time; 3127305Ssam p1->c_next = p2->c_next; 3137305Ssam p2->c_next = callfree; 3147305Ssam callfree = p2; 3157305Ssam break; 3167305Ssam } 3177305Ssam } 3187305Ssam splx(s); 3197305Ssam } 3208112Sroot 3218124Sroot /* 3228124Sroot * Compute number of hz until specified time. 3238124Sroot * Used to compute third argument to timeout() from an 3248124Sroot * absolute time. 3258124Sroot */ 3268112Sroot hzto(tv) 3278112Sroot struct timeval *tv; 3288112Sroot { 3298124Sroot register long ticks; 3308124Sroot register long sec; 3318112Sroot int s = spl7(); 3328112Sroot 3338124Sroot /* 3348124Sroot * If number of milliseconds will fit in 32 bit arithmetic, 3358124Sroot * then compute number of milliseconds to time and scale to 3368124Sroot * ticks. Otherwise just compute number of hz in time, rounding 3378124Sroot * times greater than representible to maximum value. 3388124Sroot * 3398124Sroot * Delta times less than 25 days can be computed ``exactly''. 3408124Sroot * Maximum value for any timeout in 10ms ticks is 250 days. 3418124Sroot */ 3428124Sroot sec = tv->tv_sec - time.tv_sec; 3438124Sroot if (sec <= 0x7fffffff / 1000 - 1000) 3448124Sroot ticks = ((tv->tv_sec - time.tv_sec) * 1000 + 3458124Sroot (tv->tv_usec - time.tv_usec) / 1000) / (tick / 1000); 3468124Sroot else if (sec <= 0x7fffffff / hz) 3478124Sroot ticks = sec * hz; 3488124Sroot else 3498124Sroot ticks = 0x7fffffff; 3508112Sroot splx(s); 3518112Sroot return (ticks); 3528112Sroot } 353