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