fixup ecc code to work
[unix-history] / usr / src / sys / kern / kern_clock.c
CommitLineData
964bcfb1 1/* kern_clock.c 4.16 81/03/09 */
83be5fac
BJ
2
3#include "../h/param.h"
4#include "../h/systm.h"
d9b8447e 5#include "../h/dk.h"
0a34b6fd 6#include "../h/callout.h"
83be5fac
BJ
7#include "../h/seg.h"
8#include "../h/dir.h"
9#include "../h/user.h"
10#include "../h/proc.h"
11#include "../h/reg.h"
12#include "../h/psl.h"
13#include "../h/vm.h"
14#include "../h/buf.h"
15#include "../h/text.h"
95ce0d37
BJ
16#include "../h/vlimit.h"
17#include "../h/mtpr.h"
18#include "../h/clock.h"
e5a79c70 19#include "../h/cpu.h"
83be5fac 20
ec213dfb
BJ
21#include "dh.h"
22#include "dz.h"
6602c75b 23
83be5fac 24/*
f403d99f 25 * Hardclock is called straight from
83be5fac 26 * the real time clock interrupt.
f403d99f
BJ
27 * We limit the work we do at real clock interrupt time to:
28 * reloading clock
29 * decrementing time to callouts
30 * recording cpu time usage
4512b9a4 31 * modifying priority of current process
f403d99f
BJ
32 * arrange for soft clock interrupt
33 * kernel pc profiling
83be5fac 34 *
964bcfb1 35 * At software (softclock) interrupt time we:
83be5fac 36 * implement callouts
83be5fac 37 * maintain date
83be5fac
BJ
38 * lightning bolt wakeup (every second)
39 * alarm clock signals
40 * jab the scheduler
f403d99f
BJ
41 *
42 * On the vax softclock interrupts are implemented by
43 * software interrupts. Note that we may have multiple softclock
44 * interrupts compressed into one (due to excessive interrupt load),
45 * but that hardclock interrupts should never be lost.
83be5fac 46 */
83be5fac 47
260ea681 48/*ARGSUSED*/
f403d99f 49hardclock(pc, ps)
4512b9a4 50 caddr_t pc;
83be5fac 51{
0a34b6fd 52 register struct callout *p1;
83be5fac 53 register struct proc *pp;
f403d99f 54 register int s, cpstate;
83be5fac
BJ
55
56 /*
57 * reprime clock
58 */
59 clkreld();
60
61 /*
f403d99f 62 * update callout times
83be5fac 63 */
964bcfb1 64 if (callout[0].c_func == NULL)
83be5fac 65 goto out;
f403d99f 66 p1 = &callout[0];
964bcfb1 67 while (p1->c_time<=0 && p1->c_func!=NULL)
f403d99f
BJ
68 p1++;
69 p1->c_time--;
83be5fac 70out:
5da67d35
BJ
71
72 /*
f403d99f 73 * Maintain iostat and per-process cpu statistics
5da67d35 74 */
83be5fac
BJ
75 if (!noproc) {
76 s = u.u_procp->p_rssize;
77 u.u_vm.vm_idsrss += s;
78 if (u.u_procp->p_textp) {
79 register int xrss = u.u_procp->p_textp->x_rssize;
80
81 s += xrss;
82 u.u_vm.vm_ixrss += xrss;
83 }
84 if (s > u.u_vm.vm_maxrss)
85 u.u_vm.vm_maxrss = s;
0a34b6fd 86 if ((u.u_vm.vm_utime+u.u_vm.vm_stime+1)/hz > u.u_limit[LIM_CPU]) {
39f2f769
BJ
87 psignal(u.u_procp, SIGXCPU);
88 if (u.u_limit[LIM_CPU] < INFINITY - 5)
89 u.u_limit[LIM_CPU] += 5;
90 }
83be5fac 91 }
964bcfb1
BJ
92 /*
93 * Update iostat information.
94 */
83be5fac
BJ
95 if (USERMODE(ps)) {
96 u.u_vm.vm_utime++;
97 if(u.u_procp->p_nice > NZERO)
41888f16
BJ
98 cpstate = CP_NICE;
99 else
100 cpstate = CP_USER;
83be5fac 101 } else {
41888f16 102 cpstate = CP_SYS;
83be5fac 103 if (noproc)
41888f16 104 cpstate = CP_IDLE;
83be5fac
BJ
105 else
106 u.u_vm.vm_stime++;
107 }
2d7d59e9 108 cp_time[cpstate]++;
f403d99f
BJ
109 for (s = 0; s < DK_NDRIVE; s++)
110 if (dk_busy&(1<<s))
111 dk_time[s]++;
964bcfb1
BJ
112 /*
113 * Adjust priority of current process.
114 */
83be5fac
BJ
115 if (!noproc) {
116 pp = u.u_procp;
dd808ba3 117 pp->p_cpticks++;
83be5fac
BJ
118 if(++pp->p_cpu == 0)
119 pp->p_cpu--;
120 if(pp->p_cpu % 16 == 0) {
81263dba 121 (void) setpri(pp);
83be5fac
BJ
122 if (pp->p_pri >= PUSER)
123 pp->p_pri = pp->p_usrpri;
124 }
125 }
964bcfb1
BJ
126 /*
127 * Time moves on.
128 */
83be5fac 129 ++lbolt;
e5a79c70 130#if VAX780
964bcfb1
BJ
131 /*
132 * On 780's, impelement a fast UBA watcher,
133 * to make sure uba's don't get stuck.
134 */
287d9996 135 if (cpu == VAX_780 && panicstr == 0 && !BASEPRI(ps))
f403d99f
BJ
136 unhang();
137#endif
964bcfb1
BJ
138 /*
139 * Schedule a software interrupt for the rest
140 * of clock activities.
141 */
f403d99f
BJ
142 setsoftclock();
143}
144
145/*
964bcfb1
BJ
146 * SCHMAG is the constant in the digital decay cpu
147 * usage priority assignment. Each second we multiply
148 * the previous cpu usage estimate by SCHMAG. At 9/10
149 * it tends to decay away all knowledge of previous activity
150 * in about 10 seconds.
151 */
152#define SCHMAG 9/10
153
154/*
155 * Constant for decay filter for cpu usage field
156 * in process table (used by ps au).
f403d99f
BJ
157 */
158double ccpu = 0.95122942450071400909; /* exp(-1/20) */
159
160/*
161 * Software clock interrupt.
964bcfb1 162 * This routine runs at lower priority than device interrupts.
f403d99f 163 */
260ea681 164/*ARGSUSED*/
f403d99f 165softclock(pc, ps)
4512b9a4 166 caddr_t pc;
f403d99f 167{
0a34b6fd 168 register struct callout *p1, *p2;
f403d99f
BJ
169 register struct proc *pp;
170 register int a, s;
171
172 /*
287d9996 173 * Perform callouts (but not after panic's!)
f403d99f 174 */
287d9996 175 if (panicstr == 0 && callout[0].c_time <= 0) {
f403d99f 176 p1 = &callout[0];
287d9996 177 while (p1->c_func != 0 && p1->c_time <= 0) {
f403d99f
BJ
178 (*p1->c_func)(p1->c_arg);
179 p1++;
180 }
181 p2 = &callout[0];
287d9996 182 while (p2->c_func = p1->c_func) {
f403d99f
BJ
183 p2->c_time = p1->c_time;
184 p2->c_arg = p1->c_arg;
185 p1++;
186 p2++;
187 }
188 }
189
190 /*
191 * Drain silos.
192 */
3b90686d 193#if NDH > 0
f403d99f
BJ
194 s = spl5(); dhtimer(); splx(s);
195#endif
3b90686d 196#if NDZ > 0
f403d99f
BJ
197 s = spl5(); dztimer(); splx(s);
198#endif
199
4512b9a4
BJ
200 /*
201 * If idling and processes are waiting to swap in,
202 * check on them.
203 */
204 if (noproc && runin) {
205 runin = 0;
206 wakeup((caddr_t)&runin);
207 }
208
f403d99f
BJ
209 /*
210 * Run paging daemon and reschedule every 1/4 sec.
211 */
0a34b6fd 212 if (lbolt % (hz/4) == 0) {
83be5fac
BJ
213 vmpago();
214 runrun++;
f403d99f 215 aston();
83be5fac 216 }
f403d99f
BJ
217
218 /*
219 * Lightning bolt every second:
220 * sleep timeouts
221 * process priority recomputation
222 * process %cpu averaging
223 * virtual memory metering
224 * kick swapper if processes want in
225 */
0a34b6fd 226 if (lbolt >= hz) {
287d9996 227 /*
964bcfb1 228 * This doesn't mean much on VAX since we run at
287d9996
BJ
229 * software interrupt time... if hardclock()
230 * calls softclock() directly, it prevents
231 * this code from running when the priority
232 * was raised when the clock interrupt occurred.
233 */
83be5fac
BJ
234 if (BASEPRI(ps))
235 return;
287d9996
BJ
236
237 /*
238 * If we didn't run a few times because of
239 * long blockage at high ipl, we don't
240 * really want to run this code several times,
241 * so squish out all multiples of hz here.
242 */
243 time += lbolt / hz;
244 lbolt %= hz;
245
246 /*
247 * Wakeup lightning bolt sleepers.
248 * Processes sleep on lbolt to wait
249 * for short amounts of time (e.g. 1 second).
250 */
83be5fac 251 wakeup((caddr_t)&lbolt);
287d9996
BJ
252
253 /*
254 * Recompute process priority and process
255 * sleep() system calls as well as internal
256 * sleeps with timeouts (tsleep() kernel routine).
257 */
258 for (pp = proc; pp < procNPROC; pp++)
8418f526 259 if (pp->p_stat && pp->p_stat!=SZOMB) {
287d9996
BJ
260 /*
261 * Increase resident time, to max of 127 seconds
262 * (it is kept in a character.) For
263 * loaded processes this is time in core; for
264 * swapped processes, this is time on drum.
265 */
266 if (pp->p_time != 127)
83be5fac 267 pp->p_time++;
287d9996
BJ
268 /*
269 * If process has clock counting down, and it
270 * expires, set it running (if this is a tsleep()),
271 * or give it an SIGALRM (if the user process
272 * is using alarm signals.
273 */
274 if (pp->p_clktim && --pp->p_clktim == 0)
275 if (pp->p_flag & STIMO) {
276 s = spl6();
277 switch (pp->p_stat) {
daac5944 278
287d9996
BJ
279 case SSLEEP:
280 setrun(pp);
281 break;
daac5944 282
287d9996
BJ
283 case SSTOP:
284 unsleep(pp);
285 break;
286 }
287 pp->p_flag &= ~STIMO;
288 splx(s);
289 } else
290 psignal(pp, SIGALRM);
291 /*
292 * If process is blocked, increment computed
293 * time blocked. This is used in swap scheduling.
294 */
295 if (pp->p_stat==SSLEEP || pp->p_stat==SSTOP)
83be5fac
BJ
296 if (pp->p_slptime != 127)
297 pp->p_slptime++;
287d9996
BJ
298 /*
299 * Update digital filter estimation of process
300 * cpu utilization for loaded processes.
301 */
dd808ba3
BJ
302 if (pp->p_flag&SLOAD)
303 pp->p_pctcpu = ccpu * pp->p_pctcpu +
0a34b6fd 304 (1.0 - ccpu) * (pp->p_cpticks/(float)hz);
287d9996
BJ
305 /*
306 * Recompute process priority. The number p_cpu
307 * is a weighted estimate of cpu time consumed.
308 * A process which consumes cpu time has this
309 * increase regularly. We here decrease it by
310 * a fraction (SCHMAG is 90%), giving a digital
311 * decay filter which damps out in about 10 seconds.
312 *
313 * If a process is niced, then the nice directly
314 * affects the new priority. The final priority
315 * is in the range 0 to 255, to fit in a character.
316 */
dd808ba3 317 pp->p_cpticks = 0;
83be5fac 318 a = (pp->p_cpu & 0377)*SCHMAG + pp->p_nice - NZERO;
287d9996 319 if (a < 0)
83be5fac 320 a = 0;
287d9996 321 if (a > 255)
83be5fac
BJ
322 a = 255;
323 pp->p_cpu = a;
81263dba 324 (void) setpri(pp);
287d9996
BJ
325 /*
326 * Now have computed new process priority
327 * in p->p_usrpri. Carefully change p->p_pri.
328 * A process is on a run queue associated with
329 * this priority, so we must block out process
330 * state changes during the transition.
331 */
83be5fac 332 s = spl6();
287d9996 333 if (pp->p_pri >= PUSER) {
83be5fac
BJ
334 if ((pp != u.u_procp || noproc) &&
335 pp->p_stat == SRUN &&
336 (pp->p_flag & SLOAD) &&
337 pp->p_pri != pp->p_usrpri) {
338 remrq(pp);
339 pp->p_pri = pp->p_usrpri;
340 setrq(pp);
341 } else
342 pp->p_pri = pp->p_usrpri;
343 }
344 splx(s);
345 }
287d9996
BJ
346
347 /*
348 * Perform virtual memory metering.
349 */
83be5fac 350 vmmeter();
287d9996
BJ
351
352 /*
353 * If the swap process is trying to bring
354 * a process in, have it look again to see
355 * if it is possible now.
356 */
357 if (runin!=0) {
83be5fac
BJ
358 runin = 0;
359 wakeup((caddr_t)&runin);
360 }
287d9996 361
83be5fac
BJ
362 /*
363 * If there are pages that have been cleaned,
364 * jolt the pageout daemon to process them.
365 * We do this here so that these pages will be
366 * freed if there is an abundance of memory and the
367 * daemon would not be awakened otherwise.
368 */
369 if (bclnlist != NULL)
370 wakeup((caddr_t)&proc[2]);
287d9996
BJ
371
372 /*
373 * If the trap occurred from usermode,
374 * then check to see if it has now been
375 * running more than 10 minutes of user time
376 * and should thus run with reduced priority
377 * to give other processes a chance.
378 */
83be5fac
BJ
379 if (USERMODE(ps)) {
380 pp = u.u_procp;
287d9996
BJ
381 if (pp->p_uid && pp->p_nice == NZERO &&
382 u.u_vm.vm_utime > 600 * hz)
383 pp->p_nice = NZERO+4;
81263dba 384 (void) setpri(pp);
83be5fac 385 pp->p_pri = pp->p_usrpri;
054016e1 386 }
83be5fac 387 }
287d9996
BJ
388 /*
389 * If trapped user-mode, give it a profiling tick.
390 */
f403d99f
BJ
391 if (USERMODE(ps) && u.u_prof.pr_scale) {
392 u.u_procp->p_flag |= SOWEUPC;
393 aston();
83be5fac 394 }
83be5fac
BJ
395}
396
397/*
964bcfb1 398 * Timeout is called to arrange that
0a34b6fd 399 * fun(arg) is called in tim/hz seconds.
83be5fac 400 * An entry is sorted into the callout
964bcfb1 401 * structure. The time in each structure
0a34b6fd 402 * entry is the number of hz's more
83be5fac
BJ
403 * than the previous entry.
404 * In this way, decrementing the
405 * first entry has the effect of
406 * updating all entries.
407 *
408 * The panic is there because there is nothing
409 * intelligent to be done if an entry won't fit.
410 */
411timeout(fun, arg, tim)
4512b9a4
BJ
412 int (*fun)();
413 caddr_t arg;
83be5fac 414{
0a34b6fd 415 register struct callout *p1, *p2, *p3;
83be5fac
BJ
416 register int t;
417 int s;
418
419 t = tim;
420 p1 = &callout[0];
421 s = spl7();
964bcfb1 422 while (p1->c_func != 0 && p1->c_time <= t) {
83be5fac
BJ
423 t -= p1->c_time;
424 p1++;
425 }
83be5fac
BJ
426 p1->c_time -= t;
427 p2 = p1;
0a34b6fd 428 p3 = callout+(ncallout-2);
964bcfb1 429 while (p2->c_func != 0) {
72559ec9 430 if (p2 >= p3)
f403d99f 431 panic("timeout");
83be5fac 432 p2++;
72559ec9 433 }
964bcfb1 434 while (p2 >= p1) {
83be5fac
BJ
435 (p2+1)->c_time = p2->c_time;
436 (p2+1)->c_func = p2->c_func;
437 (p2+1)->c_arg = p2->c_arg;
438 p2--;
439 }
440 p1->c_time = t;
441 p1->c_func = fun;
442 p1->c_arg = arg;
443 splx(s);
444}