xref: /original-bsd/sys/kern/kern_clock.c (revision 898732d7)
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 = &regs.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