Commit | Line | Data |
---|---|---|
cccb9ee6 | 1 | /* kern_clock.c 3.8 %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 | 33 | unsigned 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 | 40 | int rintvl = 0; /* every 1/60'th of sec check receivers */ |
1c108279 BJ |
41 | int rcnt; |
42 | ||
83be5fac BJ |
43 | clock(pc, ps) |
44 | caddr_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 | */ | |
97 | out: | |
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 | |
cccb9ee6 | 177 | psignal(pp, SIGALRM); |
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 | */ | |
264 | timeout(fun, arg, tim) | |
265 | int (*fun)(); | |
266 | caddr_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 | } |