VOID=>(void)
[unix-history] / usr / src / sys / kern / kern_clock.c
CommitLineData
5da67d35 1/* kern_clock.c 3.6 %H% */
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 */
40int rintvl = 4; /* every 1/15'th of sec check receivers */
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;
49 int a;
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 }
128 a = dk_busy&07;
129 if (USERMODE(ps)) {
130 u.u_vm.vm_utime++;
131 if(u.u_procp->p_nice > NZERO)
132 a += 8;
133 } else {
134 a += 16;
135 if (noproc)
136 a += 8;
137 else
138 u.u_vm.vm_stime++;
139 }
140 dk_time[a]++;
141 if (!noproc) {
142 pp = u.u_procp;
143 if(++pp->p_cpu == 0)
144 pp->p_cpu--;
145 if(pp->p_cpu % 16 == 0) {
81263dba 146 (void) setpri(pp);
83be5fac
BJ
147 if (pp->p_pri >= PUSER)
148 pp->p_pri = pp->p_usrpri;
149 }
150 }
151 ++lbolt;
152 if (lbolt % (HZ/4) == 0) {
153 vmpago();
154 runrun++;
155 }
156 if (lbolt >= HZ) {
157 if (BASEPRI(ps))
158 return;
159 lbolt -= HZ;
160 ++time;
81263dba 161 (void) spl1();
83be5fac
BJ
162 runrun++;
163 wakeup((caddr_t)&lbolt);
164 for(pp = &proc[0]; pp < &proc[NPROC]; pp++)
165 if (pp->p_stat && pp->p_stat<SZOMB) {
166 if(pp->p_time != 127)
167 pp->p_time++;
168 if(pp->p_clktim)
169 if(--pp->p_clktim == 0)
8add37d7
BJ
170 if (pp->p_flag & STIMO) {
171 s = spl6();
172 if (pp->p_stat == SSLEEP)
173 setrun(pp);
174 pp->p_flag &= ~STIMO;
175 splx(s);
176 } else
177 psignal(pp, SIGCLK);
83be5fac
BJ
178 if(pp->p_stat==SSLEEP||pp->p_stat==SSTOP)
179 if (pp->p_slptime != 127)
180 pp->p_slptime++;
181 if(pp->p_flag&SLOAD) {
182 ave(pp->p_aveflt, pp->p_faults, 5);
183 pp->p_faults = 0;
184 }
185 a = (pp->p_cpu & 0377)*SCHMAG + pp->p_nice - NZERO;
186 if(a < 0)
187 a = 0;
188 if(a > 255)
189 a = 255;
190 pp->p_cpu = a;
81263dba 191 (void) setpri(pp);
83be5fac
BJ
192 s = spl6();
193 if(pp->p_pri >= PUSER) {
194 if ((pp != u.u_procp || noproc) &&
195 pp->p_stat == SRUN &&
196 (pp->p_flag & SLOAD) &&
197 pp->p_pri != pp->p_usrpri) {
198 remrq(pp);
199 pp->p_pri = pp->p_usrpri;
200 setrq(pp);
201 } else
202 pp->p_pri = pp->p_usrpri;
203 }
204 splx(s);
205 }
206 vmmeter();
207 if(runin!=0) {
208 runin = 0;
209 wakeup((caddr_t)&runin);
210 }
211 /*
212 * If there are pages that have been cleaned,
213 * jolt the pageout daemon to process them.
214 * We do this here so that these pages will be
215 * freed if there is an abundance of memory and the
216 * daemon would not be awakened otherwise.
217 */
218 if (bclnlist != NULL)
219 wakeup((caddr_t)&proc[2]);
220#ifdef ERNIE
221 if (USERMODE(ps)) {
222 pp = u.u_procp;
223 if (pp->p_uid)
224 if (pp->p_nice == NZERO && u.u_vm.vm_utime > 600 * HZ)
225 pp->p_nice = NZERO+4;
81263dba 226 (void) setpri(pp);
83be5fac
BJ
227 pp->p_pri = pp->p_usrpri;
228 }
229#endif
230 }
231 if (USERMODE(ps)) {
232 /*
233 * We do this last since it
234 * may block on a page fault in user space.
235 */
236 if (u.u_prof.pr_scale)
237 addupc(pc, &u.u_prof, 1);
238 }
239#ifdef KPROF
240 else if (!noproc) {
525dfa77 241 register int indx = ((int)pc & 0x7fffffff) / 4;
83be5fac
BJ
242
243 if (indx >= 0 && indx < 20000)
525dfa77
BJ
244 if (++kcount[indx] == 0)
245 --kcount[indx];
83be5fac
BJ
246 }
247#endif
248}
249
250/*
251 * timeout is called to arrange that
252 * fun(arg) is called in tim/HZ seconds.
253 * An entry is sorted into the callout
254 * structure. The time in each structure
255 * entry is the number of HZ's more
256 * than the previous entry.
257 * In this way, decrementing the
258 * first entry has the effect of
259 * updating all entries.
260 *
261 * The panic is there because there is nothing
262 * intelligent to be done if an entry won't fit.
263 */
264timeout(fun, arg, tim)
265int (*fun)();
266caddr_t arg;
267{
268 register struct callo *p1, *p2;
269 register int t;
270 int s;
271
272 t = tim;
273 p1 = &callout[0];
274 s = spl7();
275 while(p1->c_func != 0 && p1->c_time <= t) {
276 t -= p1->c_time;
277 p1++;
278 }
279 if (p1 >= &callout[NCALL-1])
280 panic("Timeout table overflow");
281 p1->c_time -= t;
282 p2 = p1;
283 while(p2->c_func != 0)
284 p2++;
285 while(p2 >= p1) {
286 (p2+1)->c_time = p2->c_time;
287 (p2+1)->c_func = p2->c_func;
288 (p2+1)->c_arg = p2->c_arg;
289 p2--;
290 }
291 p1->c_time = t;
292 p1->c_func = fun;
293 p1->c_arg = arg;
294 splx(s);
295}