change %cpu constant; new disk monitoring/cpu scheme
[unix-history] / usr / src / sys / kern / kern_clock.c
CommitLineData
2d7d59e9 1/* %H% 3.21 kern_clock.c */
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
BJ
19
20#define SCHMAG 9/10
21
dd808ba3
BJ
22/*
23 * Constant for decay filter for cpu usage.
24 */
2d7d59e9 25double ccpu = 0.95122942450071400909; /* exp(-1/20) */
83be5fac
BJ
26
27/*
dd808ba3 28 * Clock is called straight from
83be5fac
BJ
29 * the real time clock interrupt.
30 *
31 * Functions:
32 * implement callouts
33 * maintain user/system times
34 * maintain date
35 * profile
36 * lightning bolt wakeup (every second)
37 * alarm clock signals
38 * jab the scheduler
39 */
40#ifdef KPROF
525dfa77 41unsigned short kcount[20000];
83be5fac
BJ
42#endif
43
1c108279
BJ
44/*
45 * We handle regular calls to the dh and dz silo input processors
46 * without using timeouts to save a little time.
47 */
d4be7420 48int rintvl = 0; /* every 1/60'th of sec check receivers */
1c108279
BJ
49int rcnt;
50
83be5fac
BJ
51clock(pc, ps)
52caddr_t pc;
53{
54 register struct callo *p1, *p2;
55 register struct proc *pp;
56 register int s;
2d7d59e9 57 int a, cpstate, i;
83be5fac
BJ
58
59 /*
60 * reprime clock
61 */
62 clkreld();
63
64 /*
65 * callouts
66 * else update first non-zero time
67 */
68
69 if(callout[0].c_func == NULL)
70 goto out;
71 p2 = &callout[0];
72 while(p2->c_time<=0 && p2->c_func!=NULL)
73 p2++;
74 p2->c_time--;
75
76 /*
77 * if ps is high, just return
78 */
79 if (BASEPRI(ps))
80 goto out;
81
82 /*
83 * callout
84 */
85
86 if(callout[0].c_time <= 0) {
87 p1 = &callout[0];
88 while(p1->c_func != 0 && p1->c_time <= 0) {
89 (*p1->c_func)(p1->c_arg);
90 p1++;
91 }
92 p2 = &callout[0];
93 while(p2->c_func = p1->c_func) {
94 p2->c_time = p1->c_time;
95 p2->c_arg = p1->c_arg;
96 p1++;
97 p2++;
98 }
99 }
100
101 /*
102 * lightning bolt time-out
103 * and time of day
104 */
105out:
5da67d35
BJ
106
107 /*
108 * In order to not take input character interrupts to use
109 * the input silo on DZ's we have to guarantee to echo
110 * characters regularly. This means that we have to
111 * call the timer routines predictably. Since blocking
112 * in these routines is at spl5(), we have to make spl5()
113 * really spl6() blocking off the clock to put this code
114 * here. Note also that it is critical that we run spl5()
115 * (i.e. really spl6()) in the receiver interrupt routines
116 * so we can't enter them recursively and transpose characters.
117 */
118 if (rcnt >= rintvl) {
119 dhtimer();
120 dztimer();
121 rcnt = 0;
122 } else
123 rcnt++;
83be5fac
BJ
124 if (!noproc) {
125 s = u.u_procp->p_rssize;
126 u.u_vm.vm_idsrss += s;
127 if (u.u_procp->p_textp) {
128 register int xrss = u.u_procp->p_textp->x_rssize;
129
130 s += xrss;
131 u.u_vm.vm_ixrss += xrss;
132 }
133 if (s > u.u_vm.vm_maxrss)
134 u.u_vm.vm_maxrss = s;
39f2f769
BJ
135 if ((u.u_vm.vm_utime+u.u_vm.vm_stime+1)/HZ > u.u_limit[LIM_CPU]) {
136 psignal(u.u_procp, SIGXCPU);
137 if (u.u_limit[LIM_CPU] < INFINITY - 5)
138 u.u_limit[LIM_CPU] += 5;
139 }
83be5fac 140 }
83be5fac
BJ
141 if (USERMODE(ps)) {
142 u.u_vm.vm_utime++;
143 if(u.u_procp->p_nice > NZERO)
41888f16
BJ
144 cpstate = CP_NICE;
145 else
146 cpstate = CP_USER;
83be5fac 147 } else {
41888f16 148 cpstate = CP_SYS;
83be5fac 149 if (noproc)
41888f16 150 cpstate = CP_IDLE;
83be5fac
BJ
151 else
152 u.u_vm.vm_stime++;
153 }
2d7d59e9
BJ
154 cp_time[cpstate]++;
155 for (i = 0; i < DK_NDRIVE; i++)
156 if (dk_busy&(1<<i))
157 dk_time[i]++;
83be5fac
BJ
158 if (!noproc) {
159 pp = u.u_procp;
dd808ba3 160 pp->p_cpticks++;
83be5fac
BJ
161 if(++pp->p_cpu == 0)
162 pp->p_cpu--;
163 if(pp->p_cpu % 16 == 0) {
81263dba 164 (void) setpri(pp);
83be5fac
BJ
165 if (pp->p_pri >= PUSER)
166 pp->p_pri = pp->p_usrpri;
167 }
168 }
169 ++lbolt;
170 if (lbolt % (HZ/4) == 0) {
171 vmpago();
172 runrun++;
173 }
174 if (lbolt >= HZ) {
95ce0d37
BJ
175 extern int hangcnt;
176
83be5fac
BJ
177 if (BASEPRI(ps))
178 return;
179 lbolt -= HZ;
180 ++time;
81263dba 181 (void) spl1();
95ce0d37
BJ
182 /*
183 * machdep.c:unhang uses hangcnt to make sure uba
184 * doesn't forget to interrupt (this has been observed).
185 * This prevents an accumulation of < 5 second uba failures
186 * from summing to a uba reset.
187 */
188 if (hangcnt)
189 hangcnt--;
83be5fac
BJ
190 runrun++;
191 wakeup((caddr_t)&lbolt);
192 for(pp = &proc[0]; pp < &proc[NPROC]; pp++)
8418f526 193 if (pp->p_stat && pp->p_stat!=SZOMB) {
83be5fac
BJ
194 if(pp->p_time != 127)
195 pp->p_time++;
196 if(pp->p_clktim)
197 if(--pp->p_clktim == 0)
8add37d7
BJ
198 if (pp->p_flag & STIMO) {
199 s = spl6();
daac5944
BJ
200 switch (pp->p_stat) {
201
202 case SSLEEP:
8add37d7 203 setrun(pp);
daac5944
BJ
204 break;
205
206 case SSTOP:
207 unsleep(pp);
208 break;
209 }
8add37d7
BJ
210 pp->p_flag &= ~STIMO;
211 splx(s);
212 } else
cccb9ee6 213 psignal(pp, SIGALRM);
83be5fac
BJ
214 if(pp->p_stat==SSLEEP||pp->p_stat==SSTOP)
215 if (pp->p_slptime != 127)
216 pp->p_slptime++;
dd808ba3
BJ
217 if (pp->p_flag&SLOAD)
218 pp->p_pctcpu = ccpu * pp->p_pctcpu +
219 (1.0 - ccpu) * (pp->p_cpticks/(float)HZ);
220 pp->p_cpticks = 0;
83be5fac
BJ
221 a = (pp->p_cpu & 0377)*SCHMAG + pp->p_nice - NZERO;
222 if(a < 0)
223 a = 0;
224 if(a > 255)
225 a = 255;
226 pp->p_cpu = a;
81263dba 227 (void) setpri(pp);
83be5fac
BJ
228 s = spl6();
229 if(pp->p_pri >= PUSER) {
230 if ((pp != u.u_procp || noproc) &&
231 pp->p_stat == SRUN &&
232 (pp->p_flag & SLOAD) &&
233 pp->p_pri != pp->p_usrpri) {
234 remrq(pp);
235 pp->p_pri = pp->p_usrpri;
236 setrq(pp);
237 } else
238 pp->p_pri = pp->p_usrpri;
239 }
240 splx(s);
241 }
242 vmmeter();
243 if(runin!=0) {
244 runin = 0;
245 wakeup((caddr_t)&runin);
246 }
247 /*
248 * If there are pages that have been cleaned,
249 * jolt the pageout daemon to process them.
250 * We do this here so that these pages will be
251 * freed if there is an abundance of memory and the
252 * daemon would not be awakened otherwise.
253 */
254 if (bclnlist != NULL)
255 wakeup((caddr_t)&proc[2]);
83be5fac
BJ
256 if (USERMODE(ps)) {
257 pp = u.u_procp;
054016e1 258#ifdef ERNIE
83be5fac
BJ
259 if (pp->p_uid)
260 if (pp->p_nice == NZERO && u.u_vm.vm_utime > 600 * HZ)
261 pp->p_nice = NZERO+4;
81263dba 262 (void) setpri(pp);
83be5fac 263 pp->p_pri = pp->p_usrpri;
83be5fac 264#endif
054016e1 265 }
83be5fac 266 }
92ca826b
BJ
267 if (!BASEPRI(ps))
268 unhang();
83be5fac
BJ
269 if (USERMODE(ps)) {
270 /*
271 * We do this last since it
272 * may block on a page fault in user space.
273 */
274 if (u.u_prof.pr_scale)
275 addupc(pc, &u.u_prof, 1);
276 }
277#ifdef KPROF
278 else if (!noproc) {
525dfa77 279 register int indx = ((int)pc & 0x7fffffff) / 4;
83be5fac
BJ
280
281 if (indx >= 0 && indx < 20000)
525dfa77
BJ
282 if (++kcount[indx] == 0)
283 --kcount[indx];
83be5fac
BJ
284 }
285#endif
286}
287
288/*
289 * timeout is called to arrange that
290 * fun(arg) is called in tim/HZ seconds.
291 * An entry is sorted into the callout
292 * structure. The time in each structure
293 * entry is the number of HZ's more
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)
303int (*fun)();
304caddr_t arg;
305{
306 register struct callo *p1, *p2;
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 }
317 if (p1 >= &callout[NCALL-1])
318 panic("Timeout table overflow");
319 p1->c_time -= t;
320 p2 = p1;
321 while(p2->c_func != 0)
322 p2++;
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}