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