use rdwri()
[unix-history] / usr / src / sys / kern / kern_clock.c
CommitLineData
7e827e79 1/* kern_clock.c 4.36 82/08/22 */
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"
72857acf 20#include "../h/protosw.h"
951c32fc
SL
21#include "../h/socket.h"
22#include "../net/if.h"
c53dce5d
RE
23#ifdef MUSH
24#include "../h/quota.h"
25#include "../h/share.h"
26#endif
83be5fac 27
738a68d6 28#include "bk.h"
ec213dfb
BJ
29#include "dh.h"
30#include "dz.h"
1fa9ff62 31#include "ps.h"
6602c75b 32
83be5fac 33/*
f403d99f 34 * Hardclock is called straight from
83be5fac 35 * the real time clock interrupt.
f403d99f
BJ
36 * We limit the work we do at real clock interrupt time to:
37 * reloading clock
38 * decrementing time to callouts
39 * recording cpu time usage
4512b9a4 40 * modifying priority of current process
f403d99f
BJ
41 * arrange for soft clock interrupt
42 * kernel pc profiling
83be5fac 43 *
964bcfb1 44 * At software (softclock) interrupt time we:
83be5fac 45 * implement callouts
83be5fac 46 * maintain date
83be5fac
BJ
47 * lightning bolt wakeup (every second)
48 * alarm clock signals
49 * jab the scheduler
f403d99f
BJ
50 *
51 * On the vax softclock interrupts are implemented by
52 * software interrupts. Note that we may have multiple softclock
53 * interrupts compressed into one (due to excessive interrupt load),
54 * but that hardclock interrupts should never be lost.
83be5fac 55 */
3484be37
BJ
56#ifdef GPROF
57extern int profiling;
58extern char *s_lowpc;
59extern u_long s_textsize;
60extern u_short *kcount;
2752c877 61#endif
83be5fac 62
72857acf
BJ
63/*
64 * Protoslow is like lbolt, but for slow protocol timeouts, counting
65 * up to (hz/PR_SLOWHZ), then causing a pfslowtimo().
66 * Protofast is like lbolt, but for fast protocol timeouts, counting
67 * up to (hz/PR_FASTHZ), then causing a pffasttimo().
68 */
69int protoslow;
70int protofast;
951c32fc 71int ifnetslow;
72857acf 72
260ea681 73/*ARGSUSED*/
f403d99f 74hardclock(pc, ps)
4512b9a4 75 caddr_t pc;
83be5fac 76{
0a34b6fd 77 register struct callout *p1;
83be5fac 78 register struct proc *pp;
f403d99f 79 register int s, cpstate;
c53dce5d 80 extern double avenrun[];
83be5fac
BJ
81
82 /*
83 * reprime clock
84 */
85 clkreld();
86
1fa9ff62
SL
87#if NPS > 0
88 /*
89 * sync referesh of picture system
90 */
91 psextsync(pc, ps);
92#endif
93
83be5fac 94 /*
f403d99f 95 * update callout times
83be5fac 96 */
c4710996
BJ
97 for (p1 = calltodo.c_next; p1 && p1->c_time <= 0; p1 = p1->c_next)
98 ;
99 if (p1)
100 p1->c_time--;
5da67d35
BJ
101
102 /*
f403d99f 103 * Maintain iostat and per-process cpu statistics
5da67d35 104 */
83be5fac
BJ
105 if (!noproc) {
106 s = u.u_procp->p_rssize;
107 u.u_vm.vm_idsrss += s;
108 if (u.u_procp->p_textp) {
109 register int xrss = u.u_procp->p_textp->x_rssize;
110
111 s += xrss;
112 u.u_vm.vm_ixrss += xrss;
113 }
114 if (s > u.u_vm.vm_maxrss)
115 u.u_vm.vm_maxrss = s;
0a34b6fd 116 if ((u.u_vm.vm_utime+u.u_vm.vm_stime+1)/hz > u.u_limit[LIM_CPU]) {
39f2f769
BJ
117 psignal(u.u_procp, SIGXCPU);
118 if (u.u_limit[LIM_CPU] < INFINITY - 5)
119 u.u_limit[LIM_CPU] += 5;
120 }
83be5fac 121 }
964bcfb1
BJ
122 /*
123 * Update iostat information.
124 */
83be5fac
BJ
125 if (USERMODE(ps)) {
126 u.u_vm.vm_utime++;
127 if(u.u_procp->p_nice > NZERO)
41888f16
BJ
128 cpstate = CP_NICE;
129 else
130 cpstate = CP_USER;
83be5fac 131 } else {
3484be37
BJ
132#ifdef GPROF
133 int k = pc - s_lowpc;
134 if (profiling < 2 && k < s_textsize)
135 kcount[k / sizeof (*kcount)]++;
2752c877 136#endif
41888f16 137 cpstate = CP_SYS;
ddb3ced5
SL
138 if (noproc) {
139 if ((ps&PSL_IPL) != 0)
140 cpstate = CP_IDLE;
141 } else
83be5fac
BJ
142 u.u_vm.vm_stime++;
143 }
2d7d59e9 144 cp_time[cpstate]++;
f403d99f
BJ
145 for (s = 0; s < DK_NDRIVE; s++)
146 if (dk_busy&(1<<s))
147 dk_time[s]++;
964bcfb1
BJ
148 /*
149 * Adjust priority of current process.
150 */
83be5fac
BJ
151 if (!noproc) {
152 pp = u.u_procp;
dd808ba3 153 pp->p_cpticks++;
83be5fac
BJ
154 if(++pp->p_cpu == 0)
155 pp->p_cpu--;
c53dce5d
RE
156#ifdef MUSH
157 pp->p_quota->q_cost += (pp->p_nice > NZERO ?
158 (shconsts.sc_tic * ((2*NZERO)-pp->p_nice)) / NZERO :
159 shconsts.sc_tic) * (((int)avenrun[0]+2)/3);
160#endif
16a64baa 161 if(pp->p_cpu % 4 == 0) {
81263dba 162 (void) setpri(pp);
83be5fac
BJ
163 if (pp->p_pri >= PUSER)
164 pp->p_pri = pp->p_usrpri;
165 }
166 }
964bcfb1
BJ
167 /*
168 * Time moves on.
169 */
83be5fac 170 ++lbolt;
72857acf
BJ
171
172 /*
173 * Time moves on for protocols.
174 */
951c32fc 175 --protoslow; --protofast; --ifnetslow;
72857acf 176
e5a79c70 177#if VAX780
964bcfb1
BJ
178 /*
179 * On 780's, impelement a fast UBA watcher,
180 * to make sure uba's don't get stuck.
181 */
287d9996 182 if (cpu == VAX_780 && panicstr == 0 && !BASEPRI(ps))
f403d99f
BJ
183 unhang();
184#endif
964bcfb1
BJ
185 /*
186 * Schedule a software interrupt for the rest
187 * of clock activities.
188 */
f403d99f
BJ
189 setsoftclock();
190}
191
192/*
16a64baa
BJ
193 * The digital decay cpu usage priority assignment is scaled to run in
194 * time as expanded by the 1 minute load average. Each second we
195 * multiply the the previous cpu usage estimate by
196 * nrscale*avenrun[0]
197 * The following relates the load average to the period over which
198 * cpu usage is 90% forgotten:
199 * loadav 1 5 seconds
200 * loadav 5 24 seconds
201 * loadav 10 47 seconds
202 * loadav 20 93 seconds
203 * This is a great improvement on the previous algorithm which
204 * decayed the priorities by a constant, and decayed away all knowledge
205 * of previous activity in about 20 seconds. Under heavy load,
206 * the previous algorithm degenerated to round-robin with poor response
207 * time when there was a high load average.
964bcfb1 208 */
b620b354 209#undef ave
16a64baa
BJ
210#define ave(a,b) ((int)(((int)(a*b))/(b+1)))
211int nrscale = 2;
212double avenrun[];
964bcfb1
BJ
213
214/*
215 * Constant for decay filter for cpu usage field
216 * in process table (used by ps au).
f403d99f
BJ
217 */
218double ccpu = 0.95122942450071400909; /* exp(-1/20) */
219
c53dce5d
RE
220#ifdef MELB
221/*
222 * Automatic niceness rate & max constants
223 */
224#define MAXNICE (8 + NZERO) /* maximum auto nice value */
225#define NFACT (40 * hz) /* nice++ every 40 secs cpu+sys time */
226#endif
227
f403d99f
BJ
228/*
229 * Software clock interrupt.
964bcfb1 230 * This routine runs at lower priority than device interrupts.
f403d99f 231 */
260ea681 232/*ARGSUSED*/
f403d99f 233softclock(pc, ps)
4512b9a4 234 caddr_t pc;
f403d99f 235{
dee48a1b 236 register struct callout *p1;
f403d99f
BJ
237 register struct proc *pp;
238 register int a, s;
c4710996
BJ
239 caddr_t arg;
240 int (*func)();
f403d99f
BJ
241
242 /*
287d9996 243 * Perform callouts (but not after panic's!)
f403d99f 244 */
c4710996
BJ
245 if (panicstr == 0) {
246 for (;;) {
247 s = spl7();
849fc3ee
BJ
248 if ((p1 = calltodo.c_next) == 0 || p1->c_time > 0) {
249 splx(s);
c4710996 250 break;
849fc3ee 251 }
c4710996
BJ
252 calltodo.c_next = p1->c_next;
253 arg = p1->c_arg;
254 func = p1->c_func;
255 p1->c_next = callfree;
256 callfree = p1;
257 (void) splx(s);
258 (*func)(arg);
f403d99f
BJ
259 }
260 }
261
262 /*
263 * Drain silos.
264 */
3b90686d 265#if NDH > 0
f403d99f
BJ
266 s = spl5(); dhtimer(); splx(s);
267#endif
3b90686d 268#if NDZ > 0
f403d99f
BJ
269 s = spl5(); dztimer(); splx(s);
270#endif
271
4512b9a4
BJ
272 /*
273 * If idling and processes are waiting to swap in,
274 * check on them.
275 */
276 if (noproc && runin) {
277 runin = 0;
278 wakeup((caddr_t)&runin);
279 }
280
f403d99f 281 /*
16a64baa 282 * Run paging daemon every 1/4 sec.
f403d99f 283 */
0a34b6fd 284 if (lbolt % (hz/4) == 0) {
83be5fac 285 vmpago();
16a64baa
BJ
286 }
287
288 /*
289 * Reschedule every 1/10 sec.
290 */
291 if (lbolt % (hz/10) == 0) {
83be5fac 292 runrun++;
f403d99f 293 aston();
83be5fac 294 }
f403d99f 295
72857acf
BJ
296 /*
297 * Run network slow and fast timeouts.
298 */
20bbf2f5
BJ
299 if (protofast <= 0) {
300 protofast = hz / PR_FASTHZ;
72857acf 301 pffasttimo();
20bbf2f5
BJ
302 }
303 if (protoslow <= 0) {
304 protoslow = hz / PR_SLOWHZ;
72857acf 305 pfslowtimo();
20bbf2f5 306 }
951c32fc
SL
307 if (ifnetslow <= 0) {
308 ifnetslow = hz / IFNET_SLOWHZ;
309 if_slowtimo();
310 }
72857acf 311
f403d99f
BJ
312 /*
313 * Lightning bolt every second:
314 * sleep timeouts
315 * process priority recomputation
316 * process %cpu averaging
317 * virtual memory metering
318 * kick swapper if processes want in
319 */
0a34b6fd 320 if (lbolt >= hz) {
287d9996 321 /*
964bcfb1 322 * This doesn't mean much on VAX since we run at
287d9996
BJ
323 * software interrupt time... if hardclock()
324 * calls softclock() directly, it prevents
325 * this code from running when the priority
326 * was raised when the clock interrupt occurred.
327 */
83be5fac
BJ
328 if (BASEPRI(ps))
329 return;
287d9996
BJ
330
331 /*
332 * If we didn't run a few times because of
333 * long blockage at high ipl, we don't
334 * really want to run this code several times,
335 * so squish out all multiples of hz here.
336 */
ddb3ced5
SL
337 s = spl6();
338 time += lbolt / hz; lbolt %= hz;
339 splx(s);
287d9996
BJ
340
341 /*
342 * Wakeup lightning bolt sleepers.
343 * Processes sleep on lbolt to wait
344 * for short amounts of time (e.g. 1 second).
345 */
83be5fac 346 wakeup((caddr_t)&lbolt);
287d9996
BJ
347
348 /*
349 * Recompute process priority and process
350 * sleep() system calls as well as internal
351 * sleeps with timeouts (tsleep() kernel routine).
352 */
353 for (pp = proc; pp < procNPROC; pp++)
8418f526 354 if (pp->p_stat && pp->p_stat!=SZOMB) {
c53dce5d
RE
355#ifdef MUSH
356 /*
357 * Charge process for memory in use
358 */
359 if (pp->p_quota->q_uid)
360 pp->p_quota->q_cost +=
361 shconsts.sc_click * pp->p_rssize;
362#endif
287d9996
BJ
363 /*
364 * Increase resident time, to max of 127 seconds
365 * (it is kept in a character.) For
366 * loaded processes this is time in core; for
367 * swapped processes, this is time on drum.
368 */
369 if (pp->p_time != 127)
83be5fac 370 pp->p_time++;
287d9996
BJ
371 /*
372 * If process has clock counting down, and it
373 * expires, set it running (if this is a tsleep()),
374 * or give it an SIGALRM (if the user process
375 * is using alarm signals.
376 */
377 if (pp->p_clktim && --pp->p_clktim == 0)
378 if (pp->p_flag & STIMO) {
379 s = spl6();
380 switch (pp->p_stat) {
daac5944 381
287d9996
BJ
382 case SSLEEP:
383 setrun(pp);
384 break;
daac5944 385
287d9996
BJ
386 case SSTOP:
387 unsleep(pp);
388 break;
389 }
390 pp->p_flag &= ~STIMO;
391 splx(s);
392 } else
393 psignal(pp, SIGALRM);
394 /*
395 * If process is blocked, increment computed
396 * time blocked. This is used in swap scheduling.
397 */
398 if (pp->p_stat==SSLEEP || pp->p_stat==SSTOP)
83be5fac
BJ
399 if (pp->p_slptime != 127)
400 pp->p_slptime++;
287d9996
BJ
401 /*
402 * Update digital filter estimation of process
403 * cpu utilization for loaded processes.
404 */
dd808ba3
BJ
405 if (pp->p_flag&SLOAD)
406 pp->p_pctcpu = ccpu * pp->p_pctcpu +
0a34b6fd 407 (1.0 - ccpu) * (pp->p_cpticks/(float)hz);
287d9996
BJ
408 /*
409 * Recompute process priority. The number p_cpu
410 * is a weighted estimate of cpu time consumed.
411 * A process which consumes cpu time has this
412 * increase regularly. We here decrease it by
16a64baa
BJ
413 * a fraction based on load average giving a digital
414 * decay filter which damps out in about 5 seconds
415 * when seconds are measured in time expanded by the
416 * load average.
287d9996
BJ
417 *
418 * If a process is niced, then the nice directly
419 * affects the new priority. The final priority
420 * is in the range 0 to 255, to fit in a character.
421 */
dd808ba3 422 pp->p_cpticks = 0;
c53dce5d
RE
423#ifdef MUSH
424 a = ave((pp->p_cpu & 0377), avenrun[0]*nrscale) +
425 pp->p_nice - NZERO + pp->p_quota->q_nice;
426#else
16a64baa
BJ
427 a = ave((pp->p_cpu & 0377), avenrun[0]*nrscale) +
428 pp->p_nice - NZERO;
c53dce5d 429#endif
287d9996 430 if (a < 0)
83be5fac 431 a = 0;
287d9996 432 if (a > 255)
83be5fac
BJ
433 a = 255;
434 pp->p_cpu = a;
81263dba 435 (void) setpri(pp);
287d9996
BJ
436 /*
437 * Now have computed new process priority
438 * in p->p_usrpri. Carefully change p->p_pri.
439 * A process is on a run queue associated with
440 * this priority, so we must block out process
441 * state changes during the transition.
442 */
83be5fac 443 s = spl6();
287d9996 444 if (pp->p_pri >= PUSER) {
83be5fac
BJ
445 if ((pp != u.u_procp || noproc) &&
446 pp->p_stat == SRUN &&
447 (pp->p_flag & SLOAD) &&
448 pp->p_pri != pp->p_usrpri) {
449 remrq(pp);
450 pp->p_pri = pp->p_usrpri;
451 setrq(pp);
452 } else
453 pp->p_pri = pp->p_usrpri;
454 }
455 splx(s);
456 }
287d9996
BJ
457
458 /*
459 * Perform virtual memory metering.
460 */
83be5fac 461 vmmeter();
287d9996
BJ
462
463 /*
464 * If the swap process is trying to bring
465 * a process in, have it look again to see
466 * if it is possible now.
467 */
468 if (runin!=0) {
83be5fac
BJ
469 runin = 0;
470 wakeup((caddr_t)&runin);
471 }
287d9996 472
83be5fac
BJ
473 /*
474 * If there are pages that have been cleaned,
475 * jolt the pageout daemon to process them.
476 * We do this here so that these pages will be
477 * freed if there is an abundance of memory and the
478 * daemon would not be awakened otherwise.
479 */
480 if (bclnlist != NULL)
481 wakeup((caddr_t)&proc[2]);
287d9996 482
c53dce5d
RE
483#ifdef MELB
484 /*
485 * If a process was running, see if time to make it nicer
486 */
487 if (!noproc) {
488 pp = u.u_procp;
489 if (pp->p_uid
490#ifdef MUSH
491 && !(pp->p_flag & SLOGIN)
492#else
493 /* this is definitely not good enough */
494 && (pp->p_pid != pp->p_pgrp || pp->p_ppid != 1)
495#endif
496 && (u.u_vm.vm_utime + u.u_vm.vm_stime) >
497 (pp->p_nice-NZERO+1)*NFACT
498 && pp->p_nice >= NZERO
499 && pp->p_nice < MAXNICE
500 ) {
501 pp->p_nice++;
502 (void) setpri(pp);
503 pp->p_pri = pp->p_usrpri;
504 }
505 }
506#else
287d9996
BJ
507 /*
508 * If the trap occurred from usermode,
509 * then check to see if it has now been
510 * running more than 10 minutes of user time
511 * and should thus run with reduced priority
512 * to give other processes a chance.
513 */
83be5fac
BJ
514 if (USERMODE(ps)) {
515 pp = u.u_procp;
287d9996
BJ
516 if (pp->p_uid && pp->p_nice == NZERO &&
517 u.u_vm.vm_utime > 600 * hz)
518 pp->p_nice = NZERO+4;
81263dba 519 (void) setpri(pp);
83be5fac 520 pp->p_pri = pp->p_usrpri;
054016e1 521 }
c53dce5d 522#endif
83be5fac 523 }
287d9996
BJ
524 /*
525 * If trapped user-mode, give it a profiling tick.
526 */
f403d99f
BJ
527 if (USERMODE(ps) && u.u_prof.pr_scale) {
528 u.u_procp->p_flag |= SOWEUPC;
529 aston();
83be5fac 530 }
83be5fac
BJ
531}
532
533/*
964bcfb1 534 * Timeout is called to arrange that
0a34b6fd 535 * fun(arg) is called in tim/hz seconds.
c4710996 536 * An entry is linked into the callout
964bcfb1 537 * structure. The time in each structure
0a34b6fd 538 * entry is the number of hz's more
83be5fac
BJ
539 * than the previous entry.
540 * In this way, decrementing the
541 * first entry has the effect of
542 * updating all entries.
543 *
544 * The panic is there because there is nothing
545 * intelligent to be done if an entry won't fit.
546 */
547timeout(fun, arg, tim)
4512b9a4
BJ
548 int (*fun)();
549 caddr_t arg;
83be5fac 550{
c4710996 551 register struct callout *p1, *p2, *pnew;
83be5fac
BJ
552 register int t;
553 int s;
554
47477f34
BJ
555/* DEBUGGING CODE */
556 int ttrstrt();
557
558 if (fun == ttrstrt && arg == 0)
559 panic("timeout ttrstr arg");
560/* END DEBUGGING CODE */
83be5fac 561 t = tim;
83be5fac 562 s = spl7();
c4710996
BJ
563 pnew = callfree;
564 if (pnew == NULL)
565 panic("timeout table overflow");
566 callfree = pnew->c_next;
567 pnew->c_arg = arg;
568 pnew->c_func = fun;
569 for (p1 = &calltodo; (p2 = p1->c_next) && p2->c_time < t; p1 = p2)
570 t -= p2->c_time;
571 p1->c_next = pnew;
572 pnew->c_next = p2;
573 pnew->c_time = t;
574 if (p2)
575 p2->c_time -= t;
83be5fac
BJ
576 splx(s);
577}
1fa9ff62 578
7e827e79 579#ifdef notdef
1fa9ff62
SL
580/*
581 * untimeout is called to remove a function timeout call
582 * from the callout structure.
583 */
584untimeout (fun, arg)
585 int (*fun)();
586 caddr_t arg;
587{
588
589 register struct callout *p1, *p2;
590 register int s;
591
592 s = spl7();
593 for (p1 = &calltodo; (p2 = p1->c_next) != 0; p1 = p2) {
594 if (p2->c_func == fun && p2->c_arg == arg) {
595 if (p2->c_next)
596 p2->c_next->c_time += p2->c_time;
597 p1->c_next = p2->c_next;
598 p2->c_next = callfree;
599 callfree = p2;
600 break;
601 }
602 }
603 splx(s);
604}
7e827e79 605#endif