counter in dz code
[unix-history] / usr / src / sys / kern / kern_clock.c
CommitLineData
daac5944 1/* kern_clock.c 3.9 %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 */
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;
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();
daac5944
BJ
172 switch (pp->p_stat) {
173
174 case SSLEEP:
8add37d7 175 setrun(pp);
daac5944
BJ
176 break;
177
178 case SSTOP:
179 unsleep(pp);
180 break;
181 }
8add37d7
BJ
182 pp->p_flag &= ~STIMO;
183 splx(s);
184 } else
cccb9ee6 185 psignal(pp, SIGALRM);
83be5fac
BJ
186 if(pp->p_stat==SSLEEP||pp->p_stat==SSTOP)
187 if (pp->p_slptime != 127)
188 pp->p_slptime++;
189 if(pp->p_flag&SLOAD) {
190 ave(pp->p_aveflt, pp->p_faults, 5);
191 pp->p_faults = 0;
192 }
193 a = (pp->p_cpu & 0377)*SCHMAG + pp->p_nice - NZERO;
194 if(a < 0)
195 a = 0;
196 if(a > 255)
197 a = 255;
198 pp->p_cpu = a;
81263dba 199 (void) setpri(pp);
83be5fac
BJ
200 s = spl6();
201 if(pp->p_pri >= PUSER) {
202 if ((pp != u.u_procp || noproc) &&
203 pp->p_stat == SRUN &&
204 (pp->p_flag & SLOAD) &&
205 pp->p_pri != pp->p_usrpri) {
206 remrq(pp);
207 pp->p_pri = pp->p_usrpri;
208 setrq(pp);
209 } else
210 pp->p_pri = pp->p_usrpri;
211 }
212 splx(s);
213 }
214 vmmeter();
215 if(runin!=0) {
216 runin = 0;
217 wakeup((caddr_t)&runin);
218 }
219 /*
220 * If there are pages that have been cleaned,
221 * jolt the pageout daemon to process them.
222 * We do this here so that these pages will be
223 * freed if there is an abundance of memory and the
224 * daemon would not be awakened otherwise.
225 */
226 if (bclnlist != NULL)
227 wakeup((caddr_t)&proc[2]);
228#ifdef ERNIE
229 if (USERMODE(ps)) {
230 pp = u.u_procp;
231 if (pp->p_uid)
232 if (pp->p_nice == NZERO && u.u_vm.vm_utime > 600 * HZ)
233 pp->p_nice = NZERO+4;
81263dba 234 (void) setpri(pp);
83be5fac
BJ
235 pp->p_pri = pp->p_usrpri;
236 }
237#endif
238 }
239 if (USERMODE(ps)) {
240 /*
241 * We do this last since it
242 * may block on a page fault in user space.
243 */
244 if (u.u_prof.pr_scale)
245 addupc(pc, &u.u_prof, 1);
246 }
247#ifdef KPROF
248 else if (!noproc) {
525dfa77 249 register int indx = ((int)pc & 0x7fffffff) / 4;
83be5fac
BJ
250
251 if (indx >= 0 && indx < 20000)
525dfa77
BJ
252 if (++kcount[indx] == 0)
253 --kcount[indx];
83be5fac
BJ
254 }
255#endif
256}
257
258/*
259 * timeout is called to arrange that
260 * fun(arg) is called in tim/HZ seconds.
261 * An entry is sorted into the callout
262 * structure. The time in each structure
263 * entry is the number of HZ's more
264 * than the previous entry.
265 * In this way, decrementing the
266 * first entry has the effect of
267 * updating all entries.
268 *
269 * The panic is there because there is nothing
270 * intelligent to be done if an entry won't fit.
271 */
272timeout(fun, arg, tim)
273int (*fun)();
274caddr_t arg;
275{
276 register struct callo *p1, *p2;
277 register int t;
278 int s;
279
280 t = tim;
281 p1 = &callout[0];
282 s = spl7();
283 while(p1->c_func != 0 && p1->c_time <= t) {
284 t -= p1->c_time;
285 p1++;
286 }
287 if (p1 >= &callout[NCALL-1])
288 panic("Timeout table overflow");
289 p1->c_time -= t;
290 p2 = p1;
291 while(p2->c_func != 0)
292 p2++;
293 while(p2 >= p1) {
294 (p2+1)->c_time = p2->c_time;
295 (p2+1)->c_func = p2->c_func;
296 (p2+1)->c_arg = p2->c_arg;
297 p2--;
298 }
299 p1->c_time = t;
300 p1->c_func = fun;
301 p1->c_arg = arg;
302 splx(s);
303}