date and time created 81/03/02 21:29:48 by peter
[unix-history] / usr / src / sys / kern / kern_clock.c
CommitLineData
0a34b6fd 1/* kern_clock.c 4.14 %G% */
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
BJ
24#define SCHMAG 9/10
25
26
27/*
f403d99f 28 * Hardclock is called straight from
83be5fac 29 * the real time clock interrupt.
f403d99f
BJ
30 * We limit the work we do at real clock interrupt time to:
31 * reloading clock
32 * decrementing time to callouts
33 * recording cpu time usage
4512b9a4 34 * modifying priority of current process
f403d99f
BJ
35 * arrange for soft clock interrupt
36 * kernel pc profiling
83be5fac 37 *
f403d99f 38 * At softclock interrupt time we:
83be5fac 39 * implement callouts
83be5fac 40 * maintain date
83be5fac
BJ
41 * lightning bolt wakeup (every second)
42 * alarm clock signals
43 * jab the scheduler
f403d99f
BJ
44 *
45 * On the vax softclock interrupts are implemented by
46 * software interrupts. Note that we may have multiple softclock
47 * interrupts compressed into one (due to excessive interrupt load),
48 * but that hardclock interrupts should never be lost.
83be5fac 49 */
83be5fac 50
260ea681 51/*ARGSUSED*/
f403d99f 52hardclock(pc, ps)
4512b9a4 53 caddr_t pc;
83be5fac 54{
0a34b6fd 55 register struct callout *p1;
83be5fac 56 register struct proc *pp;
f403d99f 57 register int s, cpstate;
83be5fac
BJ
58
59 /*
60 * reprime clock
61 */
62 clkreld();
63
64 /*
f403d99f 65 * update callout times
83be5fac 66 */
83be5fac
BJ
67 if(callout[0].c_func == NULL)
68 goto out;
f403d99f
BJ
69 p1 = &callout[0];
70 while(p1->c_time<=0 && p1->c_func!=NULL)
71 p1++;
72 p1->c_time--;
83be5fac 73out:
5da67d35
BJ
74
75 /*
f403d99f 76 * Maintain iostat and per-process cpu statistics
5da67d35 77 */
83be5fac
BJ
78 if (!noproc) {
79 s = u.u_procp->p_rssize;
80 u.u_vm.vm_idsrss += s;
81 if (u.u_procp->p_textp) {
82 register int xrss = u.u_procp->p_textp->x_rssize;
83
84 s += xrss;
85 u.u_vm.vm_ixrss += xrss;
86 }
87 if (s > u.u_vm.vm_maxrss)
88 u.u_vm.vm_maxrss = s;
0a34b6fd 89 if ((u.u_vm.vm_utime+u.u_vm.vm_stime+1)/hz > u.u_limit[LIM_CPU]) {
39f2f769
BJ
90 psignal(u.u_procp, SIGXCPU);
91 if (u.u_limit[LIM_CPU] < INFINITY - 5)
92 u.u_limit[LIM_CPU] += 5;
93 }
83be5fac 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]++;
83be5fac
BJ
112 if (!noproc) {
113 pp = u.u_procp;
dd808ba3 114 pp->p_cpticks++;
83be5fac
BJ
115 if(++pp->p_cpu == 0)
116 pp->p_cpu--;
117 if(pp->p_cpu % 16 == 0) {
81263dba 118 (void) setpri(pp);
83be5fac
BJ
119 if (pp->p_pri >= PUSER)
120 pp->p_pri = pp->p_usrpri;
121 }
122 }
123 ++lbolt;
e5a79c70
BJ
124#if VAX780
125 if (cpu == VAX_780 && !BASEPRI(ps))
f403d99f
BJ
126 unhang();
127#endif
128 setsoftclock();
129}
130
131/*
132 * Constant for decay filter for cpu usage.
133 */
134double ccpu = 0.95122942450071400909; /* exp(-1/20) */
135
136/*
137 * Software clock interrupt.
138 * This routine is blocked by spl1(),
139 * which doesn't block device interrupts!
140 */
260ea681 141/*ARGSUSED*/
f403d99f 142softclock(pc, ps)
4512b9a4 143 caddr_t pc;
f403d99f 144{
0a34b6fd 145 register struct callout *p1, *p2;
f403d99f
BJ
146 register struct proc *pp;
147 register int a, s;
148
149 /*
150 * callout
151 */
152 if(callout[0].c_time <= 0) {
153 p1 = &callout[0];
154 while(p1->c_func != 0 && p1->c_time <= 0) {
155 (*p1->c_func)(p1->c_arg);
156 p1++;
157 }
158 p2 = &callout[0];
159 while(p2->c_func = p1->c_func) {
160 p2->c_time = p1->c_time;
161 p2->c_arg = p1->c_arg;
162 p1++;
163 p2++;
164 }
165 }
166
167 /*
168 * Drain silos.
169 */
3b90686d 170#if NDH > 0
f403d99f
BJ
171 s = spl5(); dhtimer(); splx(s);
172#endif
3b90686d 173#if NDZ > 0
f403d99f
BJ
174 s = spl5(); dztimer(); splx(s);
175#endif
176
4512b9a4
BJ
177 /*
178 * If idling and processes are waiting to swap in,
179 * check on them.
180 */
181 if (noproc && runin) {
182 runin = 0;
183 wakeup((caddr_t)&runin);
184 }
185
f403d99f
BJ
186 /*
187 * Run paging daemon and reschedule every 1/4 sec.
188 */
0a34b6fd 189 if (lbolt % (hz/4) == 0) {
83be5fac
BJ
190 vmpago();
191 runrun++;
f403d99f 192 aston();
83be5fac 193 }
f403d99f
BJ
194
195 /*
196 * Lightning bolt every second:
197 * sleep timeouts
198 * process priority recomputation
199 * process %cpu averaging
200 * virtual memory metering
201 * kick swapper if processes want in
202 */
0a34b6fd 203 if (lbolt >= hz) {
83be5fac
BJ
204 if (BASEPRI(ps))
205 return;
0a34b6fd 206 lbolt -= hz;
83be5fac 207 ++time;
83be5fac 208 wakeup((caddr_t)&lbolt);
86fd527f 209 for(pp = proc; pp < procNPROC; pp++)
8418f526 210 if (pp->p_stat && pp->p_stat!=SZOMB) {
83be5fac
BJ
211 if(pp->p_time != 127)
212 pp->p_time++;
213 if(pp->p_clktim)
214 if(--pp->p_clktim == 0)
8add37d7
BJ
215 if (pp->p_flag & STIMO) {
216 s = spl6();
daac5944
BJ
217 switch (pp->p_stat) {
218
219 case SSLEEP:
8add37d7 220 setrun(pp);
daac5944
BJ
221 break;
222
223 case SSTOP:
224 unsleep(pp);
225 break;
226 }
8add37d7
BJ
227 pp->p_flag &= ~STIMO;
228 splx(s);
229 } else
cccb9ee6 230 psignal(pp, SIGALRM);
83be5fac
BJ
231 if(pp->p_stat==SSLEEP||pp->p_stat==SSTOP)
232 if (pp->p_slptime != 127)
233 pp->p_slptime++;
dd808ba3
BJ
234 if (pp->p_flag&SLOAD)
235 pp->p_pctcpu = ccpu * pp->p_pctcpu +
0a34b6fd 236 (1.0 - ccpu) * (pp->p_cpticks/(float)hz);
dd808ba3 237 pp->p_cpticks = 0;
83be5fac
BJ
238 a = (pp->p_cpu & 0377)*SCHMAG + pp->p_nice - NZERO;
239 if(a < 0)
240 a = 0;
241 if(a > 255)
242 a = 255;
243 pp->p_cpu = a;
81263dba 244 (void) setpri(pp);
83be5fac
BJ
245 s = spl6();
246 if(pp->p_pri >= PUSER) {
247 if ((pp != u.u_procp || noproc) &&
248 pp->p_stat == SRUN &&
249 (pp->p_flag & SLOAD) &&
250 pp->p_pri != pp->p_usrpri) {
251 remrq(pp);
252 pp->p_pri = pp->p_usrpri;
253 setrq(pp);
254 } else
255 pp->p_pri = pp->p_usrpri;
256 }
257 splx(s);
258 }
259 vmmeter();
260 if(runin!=0) {
261 runin = 0;
262 wakeup((caddr_t)&runin);
263 }
264 /*
265 * If there are pages that have been cleaned,
266 * jolt the pageout daemon to process them.
267 * We do this here so that these pages will be
268 * freed if there is an abundance of memory and the
269 * daemon would not be awakened otherwise.
270 */
271 if (bclnlist != NULL)
272 wakeup((caddr_t)&proc[2]);
83be5fac
BJ
273 if (USERMODE(ps)) {
274 pp = u.u_procp;
275 if (pp->p_uid)
0a34b6fd 276 if (pp->p_nice == NZERO && u.u_vm.vm_utime > 600 * hz)
83be5fac 277 pp->p_nice = NZERO+4;
81263dba 278 (void) setpri(pp);
83be5fac 279 pp->p_pri = pp->p_usrpri;
054016e1 280 }
83be5fac 281 }
f403d99f
BJ
282 if (USERMODE(ps) && u.u_prof.pr_scale) {
283 u.u_procp->p_flag |= SOWEUPC;
284 aston();
83be5fac 285 }
83be5fac
BJ
286}
287
288/*
289 * timeout is called to arrange that
0a34b6fd 290 * fun(arg) is called in tim/hz seconds.
83be5fac
BJ
291 * An entry is sorted into the callout
292 * structure. The time in each structure
0a34b6fd 293 * entry is the number of hz's more
83be5fac
BJ
294 * than the previous entry.
295 * In this way, decrementing the
296 * first entry has the effect of
297 * updating all entries.
298 *
299 * The panic is there because there is nothing
300 * intelligent to be done if an entry won't fit.
301 */
302timeout(fun, arg, tim)
4512b9a4
BJ
303 int (*fun)();
304 caddr_t arg;
83be5fac 305{
0a34b6fd 306 register struct callout *p1, *p2, *p3;
83be5fac
BJ
307 register int t;
308 int s;
309
310 t = tim;
311 p1 = &callout[0];
312 s = spl7();
313 while(p1->c_func != 0 && p1->c_time <= t) {
314 t -= p1->c_time;
315 p1++;
316 }
83be5fac
BJ
317 p1->c_time -= t;
318 p2 = p1;
0a34b6fd 319 p3 = callout+(ncallout-2);
72559ec9
BJ
320 while(p2->c_func != 0) {
321 if (p2 >= p3)
f403d99f 322 panic("timeout");
83be5fac 323 p2++;
72559ec9 324 }
83be5fac
BJ
325 while(p2 >= p1) {
326 (p2+1)->c_time = p2->c_time;
327 (p2+1)->c_func = p2->c_func;
328 (p2+1)->c_arg = p2->c_arg;
329 p2--;
330 }
331 p1->c_time = t;
332 p1->c_func = fun;
333 p1->c_arg = arg;
334 splx(s);
335}