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