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