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