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