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