%cpu
[unix-history] / usr / src / sys / kern / kern_clock.c
CommitLineData
dd808ba3 1/* %H% 3.20 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 */
25double ccpu = 0.93550698503161773774; /* exp(-1/15) */
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;
41888f16 57 int a, cpstate;
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 }
41888f16 154 dk_time[cpstate][dk_busy&(DK_NSTATES-1)]++;
83be5fac
BJ
155 if (!noproc) {
156 pp = u.u_procp;
dd808ba3 157 pp->p_cpticks++;
83be5fac
BJ
158 if(++pp->p_cpu == 0)
159 pp->p_cpu--;
160 if(pp->p_cpu % 16 == 0) {
81263dba 161 (void) setpri(pp);
83be5fac
BJ
162 if (pp->p_pri >= PUSER)
163 pp->p_pri = pp->p_usrpri;
164 }
165 }
166 ++lbolt;
167 if (lbolt % (HZ/4) == 0) {
168 vmpago();
169 runrun++;
170 }
171 if (lbolt >= HZ) {
95ce0d37
BJ
172 extern int hangcnt;
173
83be5fac
BJ
174 if (BASEPRI(ps))
175 return;
176 lbolt -= HZ;
177 ++time;
81263dba 178 (void) spl1();
95ce0d37
BJ
179 /*
180 * machdep.c:unhang uses hangcnt to make sure uba
181 * doesn't forget to interrupt (this has been observed).
182 * This prevents an accumulation of < 5 second uba failures
183 * from summing to a uba reset.
184 */
185 if (hangcnt)
186 hangcnt--;
83be5fac
BJ
187 runrun++;
188 wakeup((caddr_t)&lbolt);
189 for(pp = &proc[0]; pp < &proc[NPROC]; pp++)
8418f526 190 if (pp->p_stat && pp->p_stat!=SZOMB) {
83be5fac
BJ
191 if(pp->p_time != 127)
192 pp->p_time++;
193 if(pp->p_clktim)
194 if(--pp->p_clktim == 0)
8add37d7
BJ
195 if (pp->p_flag & STIMO) {
196 s = spl6();
daac5944
BJ
197 switch (pp->p_stat) {
198
199 case SSLEEP:
8add37d7 200 setrun(pp);
daac5944
BJ
201 break;
202
203 case SSTOP:
204 unsleep(pp);
205 break;
206 }
8add37d7
BJ
207 pp->p_flag &= ~STIMO;
208 splx(s);
209 } else
cccb9ee6 210 psignal(pp, SIGALRM);
83be5fac
BJ
211 if(pp->p_stat==SSLEEP||pp->p_stat==SSTOP)
212 if (pp->p_slptime != 127)
213 pp->p_slptime++;
dd808ba3
BJ
214 if (pp->p_flag&SLOAD)
215 pp->p_pctcpu = ccpu * pp->p_pctcpu +
216 (1.0 - ccpu) * (pp->p_cpticks/(float)HZ);
217 pp->p_cpticks = 0;
83be5fac
BJ
218 a = (pp->p_cpu & 0377)*SCHMAG + pp->p_nice - NZERO;
219 if(a < 0)
220 a = 0;
221 if(a > 255)
222 a = 255;
223 pp->p_cpu = a;
81263dba 224 (void) setpri(pp);
83be5fac
BJ
225 s = spl6();
226 if(pp->p_pri >= PUSER) {
227 if ((pp != u.u_procp || noproc) &&
228 pp->p_stat == SRUN &&
229 (pp->p_flag & SLOAD) &&
230 pp->p_pri != pp->p_usrpri) {
231 remrq(pp);
232 pp->p_pri = pp->p_usrpri;
233 setrq(pp);
234 } else
235 pp->p_pri = pp->p_usrpri;
236 }
237 splx(s);
238 }
239 vmmeter();
240 if(runin!=0) {
241 runin = 0;
242 wakeup((caddr_t)&runin);
243 }
244 /*
245 * If there are pages that have been cleaned,
246 * jolt the pageout daemon to process them.
247 * We do this here so that these pages will be
248 * freed if there is an abundance of memory and the
249 * daemon would not be awakened otherwise.
250 */
251 if (bclnlist != NULL)
252 wakeup((caddr_t)&proc[2]);
83be5fac
BJ
253 if (USERMODE(ps)) {
254 pp = u.u_procp;
054016e1 255#ifdef ERNIE
83be5fac
BJ
256 if (pp->p_uid)
257 if (pp->p_nice == NZERO && u.u_vm.vm_utime > 600 * HZ)
258 pp->p_nice = NZERO+4;
81263dba 259 (void) setpri(pp);
83be5fac 260 pp->p_pri = pp->p_usrpri;
83be5fac 261#endif
054016e1 262 }
83be5fac 263 }
92ca826b
BJ
264 if (!BASEPRI(ps))
265 unhang();
83be5fac
BJ
266 if (USERMODE(ps)) {
267 /*
268 * We do this last since it
269 * may block on a page fault in user space.
270 */
271 if (u.u_prof.pr_scale)
272 addupc(pc, &u.u_prof, 1);
273 }
274#ifdef KPROF
275 else if (!noproc) {
525dfa77 276 register int indx = ((int)pc & 0x7fffffff) / 4;
83be5fac
BJ
277
278 if (indx >= 0 && indx < 20000)
525dfa77
BJ
279 if (++kcount[indx] == 0)
280 --kcount[indx];
83be5fac
BJ
281 }
282#endif
283}
284
285/*
286 * timeout is called to arrange that
287 * fun(arg) is called in tim/HZ seconds.
288 * An entry is sorted into the callout
289 * structure. The time in each structure
290 * entry is the number of HZ's more
291 * than the previous entry.
292 * In this way, decrementing the
293 * first entry has the effect of
294 * updating all entries.
295 *
296 * The panic is there because there is nothing
297 * intelligent to be done if an entry won't fit.
298 */
299timeout(fun, arg, tim)
300int (*fun)();
301caddr_t arg;
302{
303 register struct callo *p1, *p2;
304 register int t;
305 int s;
306
307 t = tim;
308 p1 = &callout[0];
309 s = spl7();
310 while(p1->c_func != 0 && p1->c_time <= t) {
311 t -= p1->c_time;
312 p1++;
313 }
314 if (p1 >= &callout[NCALL-1])
315 panic("Timeout table overflow");
316 p1->c_time -= t;
317 p2 = p1;
318 while(p2->c_func != 0)
319 p2++;
320 while(p2 >= p1) {
321 (p2+1)->c_time = p2->c_time;
322 (p2+1)->c_func = p2->c_func;
323 (p2+1)->c_arg = p2->c_arg;
324 p2--;
325 }
326 p1->c_time = t;
327 p1->c_func = fun;
328 p1->c_arg = arg;
329 splx(s);
330}