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