1 /* kern_clock.c 4.49 82/12/30 */ 2 3 #include "../machine/reg.h" 4 #include "../machine/psl.h" 5 6 #include "../h/param.h" 7 #include "../h/systm.h" 8 #include "../h/dk.h" 9 #include "../h/callout.h" 10 #include "../h/dir.h" 11 #include "../h/user.h" 12 #include "../h/kernel.h" 13 #include "../h/proc.h" 14 #include "../h/vm.h" 15 #include "../h/text.h" 16 #ifdef MUSH 17 #include "../h/quota.h" 18 #include "../h/share.h" 19 #endif 20 21 #ifdef vax 22 #include "../vax/mtpr.h" 23 #endif 24 25 # 26 /* 27 * Clock handling routines. 28 * 29 * This code is written for a machine with only one interval timer, 30 * and does timing and resource utilization estimation statistically 31 * based on the state of the machine hz times a second. A machine 32 * with proper clocks (running separately in user state, system state, 33 * interrupt state and idle state) as well as a time-of-day clock 34 * would allow a non-approximate implementation. 35 */ 36 37 /* 38 * TODO: 39 * * Keep more accurate statistics by simulating good interval timers. 40 * * Use the time-of-day clock on the VAX to keep more accurate time 41 * than is possible by repeated use of the interval timer. 42 * * Allocate more timeout table slots when table overflows. 43 */ 44 45 /* bump a timeval by a small number of usec's */ 46 #define bumptime(tp, usec) \ 47 (tp)->tv_usec += usec; \ 48 if ((tp)->tv_usec >= 1000000) { \ 49 (tp)->tv_usec -= 1000000; \ 50 (tp)->tv_sec++; \ 51 } 52 53 /* 54 * The (single) hardware interval timer. 55 * We update the events relating to real time, and then 56 * make a gross assumption: that the system has been in the 57 * state it is in (user state, kernel state, interrupt state, 58 * or idle state) for the entire last time interval, and 59 * update statistics accordingly. 60 */ 61 /*ARGSUSED*/ 62 #ifdef vax 63 hardclock(pc, ps) 64 caddr_t pc; 65 int ps; 66 { 67 #endif 68 #ifdef sun 69 hardclock(regs) 70 struct regs regs; 71 { 72 int ps = regs.r_sr; 73 caddr_t pc = (caddr_t)regs.r_pc; 74 #endif 75 register struct callout *p1; 76 register struct proc *p; 77 register int s, cpstate; 78 79 #ifdef sun 80 if (USERMODE(ps)) /* aston needs ar0 */ 81 u.u_ar0 = ®s.r_r0; 82 #endif 83 /* 84 * Update real-time timeout queue. 85 * At front of queue are some number of events which are ``due''. 86 * The time to these is <= 0 and if negative represents the 87 * number of ticks which have passed since it was supposed to happen. 88 * The rest of the q elements (times > 0) are events yet to happen, 89 * where the time for each is given as a delta from the previous. 90 * Decrementing just the first of these serves to decrement the time 91 * to all events. 92 */ 93 for (p1 = calltodo.c_next; p1 && p1->c_time <= 0; p1 = p1->c_next) 94 --p1->c_time; 95 if (p1) 96 --p1->c_time; 97 98 /* 99 * Charge the time out based on the mode the cpu is in. 100 * Here again we fudge for the lack of proper interval timers 101 * assuming that the current state has been around at least 102 * one tick. 103 */ 104 if (USERMODE(ps)) { 105 /* 106 * CPU was in user state. Increment 107 * user time counter, and process process-virtual time 108 * interval timer. 109 */ 110 bumptime(&u.u_ru.ru_utime, tick); 111 if (timerisset(&u.u_timer[ITIMER_VIRTUAL].it_value) && 112 itimerdecr(&u.u_timer[ITIMER_VIRTUAL], tick) == 0) 113 psignal(u.u_procp, SIGVTALRM); 114 if (u.u_procp->p_nice > NZERO) 115 cpstate = CP_NICE; 116 else 117 cpstate = CP_USER; 118 /* 119 * Charge it with resource utilization for a tick, updating 120 * statistics which run in (user+system) virtual time, 121 * such as the cpu time limit and profiling timers. 122 * This assumes that the current process has been running 123 * the entire last tick. 124 */ 125 if (!noproc) { 126 s = u.u_procp->p_rssize; 127 u.u_ru.ru_idrss += s; u.u_ru.ru_isrss += 0; /* XXX */ 128 if (u.u_procp->p_textp) { 129 register int xrss = u.u_procp->p_textp->x_rssize; 130 131 s += xrss; 132 u.u_ru.ru_ixrss += xrss; 133 } 134 if (s > u.u_ru.ru_maxrss) 135 u.u_ru.ru_maxrss = s; 136 if ((u.u_ru.ru_utime.tv_sec+u.u_ru.ru_stime.tv_sec+1) > 137 u.u_rlimit[RLIMIT_CPU].rlim_cur) { 138 psignal(u.u_procp, SIGXCPU); 139 if (u.u_rlimit[RLIMIT_CPU].rlim_cur < 140 u.u_rlimit[RLIMIT_CPU].rlim_max) 141 u.u_rlimit[RLIMIT_CPU].rlim_cur += 5; 142 } 143 if (timerisset(&u.u_timer[ITIMER_PROF].it_value) && 144 itimerdecr(&u.u_timer[ITIMER_PROF], tick) == 0) 145 psignal(u.u_procp, SIGPROF); 146 } 147 148 } else { 149 /* 150 * CPU was in system state. If profiling kernel 151 * increment a counter. If no process is running 152 * then this is a system tick if we were running 153 * at a non-zero IPL (in a driver). If a process is running, 154 * then we charge it with system time even if we were 155 * at a non-zero IPL, since the system often runs 156 * this way during processing of system calls. 157 * This is approximate, but the lack of true interval 158 * timers makes doing anything else difficult. 159 */ 160 #ifdef GPROF 161 int k = pc - s_lowpc; 162 if (profiling < 2 && k < s_textsize) 163 kcount[k / sizeof (*kcount)]++; 164 #endif 165 cpstate = CP_SYS; 166 if (noproc) { 167 if (BASEPRI(ps)) 168 cpstate = CP_IDLE; 169 } else { 170 bumptime(&u.u_ru.ru_stime, tick); 171 } 172 } 173 174 /* 175 * We maintain statistics shown by user-level statistics 176 * programs: the amount of time in each cpu state, and 177 * the amount of time each of DK_NDRIVE ``drives'' is busy. 178 */ 179 cp_time[cpstate]++; 180 for (s = 0; s < DK_NDRIVE; s++) 181 if (dk_busy&(1<<s)) 182 dk_time[s]++; 183 184 /* 185 * We adjust the priority of the current process. 186 * The priority of a process gets worse as it accumulates 187 * CPU time. The cpu usage estimator (p_cpu) is increased here 188 * and the formula for computing priorities (in kern_synch.c) 189 * will compute a different value each time the p_cpu increases 190 * by 4. The cpu usage estimator ramps up quite quickly when 191 * the process is running (linearly), and decays away exponentially, 192 * at a rate which is proportionally slower when the system is 193 * busy. The basic principal is that the system will 90% forget 194 * that a process used a lot of CPU time in 5*loadav seconds. 195 * This causes the system to favor processes which haven't run 196 * much recently, and to round-robin among other processes. 197 */ 198 if (!noproc) { 199 p = u.u_procp; 200 p->p_cpticks++; 201 if (++p->p_cpu == 0) 202 p->p_cpu--; 203 #ifdef MUSH 204 p->p_quota->q_cost += (p->p_nice > NZERO ? 205 (shconsts.sc_tic * ((2*NZERO)-p->p_nice)) / NZERO : 206 shconsts.sc_tic) * (((int)avenrun[0]+2)/3); 207 #endif 208 if ((p->p_cpu&3) == 0) { 209 (void) setpri(p); 210 if (p->p_pri >= PUSER) 211 p->p_pri = p->p_usrpri; 212 } 213 } 214 215 /* 216 * Increment the time-of-day, and schedule 217 * processing of the callouts at a very low cpu priority, 218 * so we don't keep the relatively high clock interrupt 219 * priority any longer than necessary. 220 */ 221 bumptime(&time, tick); 222 setsoftclock(); 223 } 224 225 /* 226 * Software priority level clock interrupt. 227 * Run periodic events from timeout queue. 228 */ 229 /*ARGSUSED*/ 230 #ifdef vax 231 softclock(pc, ps) 232 caddr_t pc; 233 int ps; 234 { 235 #endif 236 #ifdef sun 237 softclock() 238 { 239 int ps = u.u_ar0[PS]; 240 caddr_t pc = (caddr_t)u.u_ar0[PC]; 241 #endif 242 243 for (;;) { 244 register struct callout *p1; 245 register caddr_t arg; 246 register int (*func)(); 247 register int a, s; 248 249 s = spl7(); 250 if ((p1 = calltodo.c_next) == 0 || p1->c_time > 0) { 251 splx(s); 252 break; 253 } 254 arg = p1->c_arg; func = p1->c_func; a = p1->c_time; 255 calltodo.c_next = p1->c_next; 256 p1->c_next = callfree; 257 callfree = p1; 258 splx(s); 259 (*func)(arg, a); 260 } 261 /* 262 * If trapped user-mode, give it a profiling tick. 263 */ 264 if (USERMODE(ps) && u.u_prof.pr_scale) { 265 u.u_procp->p_flag |= SOWEUPC; 266 aston(); 267 } 268 } 269 270 /* 271 * Arrange that (*fun)(arg) is called in tim/hz seconds. 272 */ 273 timeout(fun, arg, tim) 274 int (*fun)(); 275 caddr_t arg; 276 int tim; 277 { 278 register struct callout *p1, *p2, *pnew; 279 register int t; 280 int s; 281 282 t = tim; 283 s = spl7(); 284 pnew = callfree; 285 if (pnew == NULL) 286 panic("timeout table overflow"); 287 callfree = pnew->c_next; 288 pnew->c_arg = arg; 289 pnew->c_func = fun; 290 for (p1 = &calltodo; (p2 = p1->c_next) && p2->c_time < t; p1 = p2) 291 if (p2->c_time > 0) 292 t -= p2->c_time; 293 p1->c_next = pnew; 294 pnew->c_next = p2; 295 pnew->c_time = t; 296 if (p2) 297 p2->c_time -= t; 298 splx(s); 299 } 300 301 /* 302 * untimeout is called to remove a function timeout call 303 * from the callout structure. 304 */ 305 untimeout(fun, arg) 306 int (*fun)(); 307 caddr_t arg; 308 { 309 register struct callout *p1, *p2; 310 register int s; 311 312 s = spl7(); 313 for (p1 = &calltodo; (p2 = p1->c_next) != 0; p1 = p2) { 314 if (p2->c_func == fun && p2->c_arg == arg) { 315 if (p2->c_next && p2->c_time > 0) 316 p2->c_next->c_time += p2->c_time; 317 p1->c_next = p2->c_next; 318 p2->c_next = callfree; 319 callfree = p2; 320 break; 321 } 322 } 323 splx(s); 324 } 325 326 /* 327 * Compute number of hz until specified time. 328 * Used to compute third argument to timeout() from an 329 * absolute time. 330 */ 331 hzto(tv) 332 struct timeval *tv; 333 { 334 register long ticks; 335 register long sec; 336 int s = spl7(); 337 338 /* 339 * If number of milliseconds will fit in 32 bit arithmetic, 340 * then compute number of milliseconds to time and scale to 341 * ticks. Otherwise just compute number of hz in time, rounding 342 * times greater than representible to maximum value. 343 * 344 * Delta times less than 25 days can be computed ``exactly''. 345 * Maximum value for any timeout in 10ms ticks is 250 days. 346 */ 347 sec = tv->tv_sec - time.tv_sec; 348 if (sec <= 0x7fffffff / 1000 - 1000) 349 ticks = ((tv->tv_sec - time.tv_sec) * 1000 + 350 (tv->tv_usec - time.tv_usec) / 1000) / (tick / 1000); 351 else if (sec <= 0x7fffffff / hz) 352 ticks = sec * hz; 353 else 354 ticks = 0x7fffffff; 355 splx(s); 356 return (ticks); 357 } 358