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