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